forked from powmedia/mongoose-fixtures
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
188 lines (151 loc) · 5.18 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//Dependencies
var fs = require('fs'),
mongoose = require('mongoose');
/**
* Clears a collection and inserts the given data as new documents
*
* @param {Mixed} The data to load. This parameter accepts either:
* String: Path to a file or directory to load
* Object: Object literal in the form described above
* @param {Function} Callback
*/
var load = exports.load = function(data, callback) {
if (typeof data == 'object') {
loadObject(data, callback);
} else if (typeof data == 'string') {
//Get the absolute dir path if a relative path was given
if (data.substr(0, 1) !== '/') {
var parentPath = module.parent.filename.split('/');
parentPath.pop();
data = parentPath.join('/') + '/' + data;
}
//Determine if data is pointing to a file or directory
fs.stat(data, function(err, stats) {
if (err) throw err;
if (stats.isDirectory()) {
loadDir(data, callback);
} else { //File
loadFile(data, callback);
}
});
} else { //Unsupported type
callback(new Error('Data must be an object, array or string (file or dir path)'));
}
}
/**
* Clears a collection and inserts the given data as new documents
*
* @param {String} The name of the model e.g. User, Post etc.
* @param {Object} The data to insert, as an array or object. E.g.:
* { user1: {name: 'Alex'}, user2: {name: 'Bob'} }
* or:
* [ {name: 'Alex'}, {name:'Bob'} ]
* @param {Function} Callback
*/
function insertCollection(modelName, data, callback) {
callback = callback || {};
//Counters for managing callbacks
var tasks = { total: 0, done: 0 };
//Load model
var Model = mongoose.model(modelName);
//Clear existing collection
Model.collection.remove(function(err) {
if (err) return callback(err);
//Convert object to array
var items = [];
if (Array.isArray(data)) {
items = data;
} else {
for (var i in data) {
items.push(data[i]);
}
}
//Check number of tasks to run
if (items.length == 0) {
return callback();
} else {
tasks.total = items.length;
}
//Insert each item individually so we get Mongoose validation etc.
items.forEach(function(item) {
var doc = new Model(item);
doc.save(function(err) {
if (err) return callback(err);
//Check if task queue is complete
tasks.done++;
if (tasks.done == tasks.total) callback();
});
});
});
}
/**
* Loads fixtures from object data
*
* @param {Object} The data to load, keyed by the Mongoose model name e.g.:
* { User: [{name: 'Alex'}, {name: 'Bob'}] }
* @param {Function} Callback
*/
function loadObject(data, callback) {
callback = callback || function() {};
//Counters for managing callbacks
var tasks = { total: 0, done: 0 };
//Go through each model's data
for (var modelName in data) {
(function() {
tasks.total++;
insertCollection(modelName, data[modelName], function(err) {
if (err) throw(err);
tasks.done++;
if (tasks.done == tasks.total) callback();
});
})();
}
}
/**
* Loads fixtures from one file
*
* TODO: Add callback option
*
* @param {String} The full path to the file to load
* @param {Function} Callback
*/
function loadFile(file, callback) {
callback = callback || function() {};
if (file.substr(0, 1) !== '/') {
var parentPath = module.parent.filename.split('/');
parentPath.pop();
file = parentPath.join('/') + '/' + file;
}
load(require(file), callback);
}
/**
* Loads fixtures from all files in a directory
*
* TODO: Add callback option
*
* @param {String} The directory path to load e.g. 'data/fixtures' or '../data'
* @param {Function} Callback
*/
function loadDir(dir, callback) {
callback = callback || function() {};
//Get the absolute dir path if a relative path was given
if (dir.substr(0, 1) !== '/') {
var parentPath = module.parent.filename.split('/');
parentPath.pop();
dir = parentPath.join('/') + '/' + dir;
}
//Counters for managing callbacks
var tasks = { total: 0, done: 0 };
//Load each file in directory
fs.readdir(dir, function(err, files){
if (err) return callback(err);
tasks.total = files.length;
files.forEach(function(file) {
loadFile(dir + '/' + file, function(err) {
if (err) return callback(err);
tasks.done++;
if (tasks.total == tasks.done) callback();
});
});
});
};