UNPKG

9.35 kBJavaScriptView Raw
1'use strict';
2var QueryObject = require('./query-object');
3var Relationship = require('./relationship');
4
5function ModelFactory() {
6 this.ORM = null;
7 this.Model = null;
8 this.tableName = '';
9 this.attributes = {};
10 this.relationships = {};
11 this.pre = {};
12 this.post = {};
13 this.static = {};
14 this.method = {};
15}
16
17//
18// Model Operations
19//
20
21ModelFactory.prototype.extend = function(ORM, tableName, data) {
22 this.ORM = ORM;
23 this.tableName = tableName;
24 this.Model = this.createModel(data.method);
25 this.addPre(data.pre);
26 this.addPost(data.post);
27 this.addStatic(data.static);
28 this.addTableAttributes(data.attributes);
29 console.log('Creating ModelFactory: ', this.tableName);
30 return this;
31};
32
33ModelFactory.prototype.createModel = function(methods) {
34
35 //
36 // Create base
37 var Model = function() {};
38
39 //
40 // Add methods to model prototype
41 for(var method in methods) {
42 Model.prototype[method] = methods[method];
43 }
44
45 //
46 // Return
47 return Model;
48};
49
50ModelFactory.prototype.addPre = function(pre) {
51 for(var method in pre) {
52 this.pre[method] = pre[method];
53 }
54};
55
56ModelFactory.prototype.addPost = function(post) {
57 for(var method in post) {
58 this.post[method] = post[method];
59 }
60};
61
62ModelFactory.prototype.addStatic = function(statics) {
63 for(var method in statics) {
64 this[method] = statics[method];
65 }
66};
67
68ModelFactory.prototype.addTableAttributes = function(attributes) {
69 for(var attribute in attributes) {
70 switch(typeof attributes[attribute]) {
71 case 'object': {
72 this.attributes[attribute] = attributes[attribute];
73 break;
74 }
75 case 'function': {
76 this.relationships[attribute] = attributes[attribute](this);
77 break;
78 }
79 }
80 }
81};
82
83//
84// Model Instance Operations
85//
86
87ModelFactory.prototype.initializeModel = function(data, created) {
88 var model = new this.Model();
89 // Set all attributes
90 for(var attribute in data) {
91 model[attribute] = data[attribute];
92 }
93 if(created) {
94 model.created = created;
95 }
96 // Set all model methods
97 return model;
98};
99
100ModelFactory.prototype.initializeModels = function(data) {
101 var self = this;
102 var models = data.map(function(d) {
103 return self.initializeModel(d);
104 });
105 return models;
106};
107
108//
109// Attribute Operations
110//
111
112ModelFactory.prototype.getReturnAttributes = function() {
113 var returnAttributes = [];
114 for(var attribute in this.attributes) {
115 if(!this.attributes[attribute].private) {
116 returnAttributes.push(attribute);
117 }
118 }
119 return returnAttributes;
120};
121
122//
123// Relationship Operations
124//
125
126//
127// Private
128//
129
130// TODO: Make private
131ModelFactory.prototype.includeForMany = function(models, include) {
132 var promises = [];
133 models.forEach(function(model) {
134 promises.push(this.includeForOne(model, include));
135 }, this);
136 return Promise.all(promises);
137};
138
139// TODO: Make private
140ModelFactory.prototype.includeForOne = function(model, include) {
141 var self = this;
142 var promises = [];
143 include.forEach(function(relationshipTableName) {
144 var relationship = self.relationships[relationshipTableName];
145 if(self.relationships.hasOwnProperty(relationshipTableName)) {
146 var promise = relationship.include(relationshipTableName, model);
147 promises.push(promise);
148 }
149 });
150 return Promise.all(promises).then(function() {
151 return model;
152 });
153};
154
155//
156// Query Operations
157//
158
159ModelFactory.prototype.hook = function(hook, data) {
160 return new Promise(function(resolve, reject) {
161 if(hook) {
162 hook(data, resolve);
163 } else {
164 resolve(data);
165 }
166 });
167};
168
169ModelFactory.prototype.create = function(where, options) {
170 var model, query, initial;
171
172 // TEMP
173 // Start transaction
174 if(!options) {
175 options = {};
176 if(!options.transaction) {
177 initial = true;
178 options.transaction = this.ORM.querier.transaction();
179 options.table = this.tableName;
180 options.depth = 0;
181 }
182 }
183 return options.transaction
184 .then(() => {
185 return this.hook(this.pre.create, where);
186 })
187 // Pre
188 .then((newWhere) => {
189 where = Object.assign({}, where, newWhere);
190 query = new QueryObject(this.tableName, where, this.relationships, options);
191 })
192 // Create belongs to one
193 .then(() => {
194 return query.createBelongsToOne();
195 })
196 // Create belongs to many
197 .then(() => {
198 return query.createBelongsToMany();
199 })
200 // Attach belongs to one
201 .then(() => {
202 return query.attachBelongsToOne();
203 })
204 // Create belongs to one
205 .then(() => {
206 return this.ORM.query.create({
207 ORM: this.ORM,
208 table: query.getTable(),
209 data: query.getAttributes(),
210 returning: this.getReturnAttributes()
211 });
212 })
213 // Attach
214 .then((rawData) => {
215 model = this.initializeModel(rawData[0], true);
216 })
217 // Attach belongs to many
218 .then(() => {
219 return query.attachBelongsToMany(model, options);
220 })
221 // Create has one
222 .then(() => {
223 return query.createHasOne(model);
224 })
225 // Create has many
226 .then(() => {
227 return query.createHasMany(model);
228 })
229 // Concat relationships
230 .then(() => {
231 model = query.concatCreatedRelationships(model);
232 })
233 // Post
234 .then(() => {
235 return this.hook(this.post.create, model);
236 })
237 .then(() => {
238 if(initial) {
239 return this.ORM.querier.commit();
240 } else {
241 return Promise.resolve();
242 }
243 })
244 // Return
245 .then(() => {
246 return model;
247 })
248 // Error
249 .catch((error) => {
250 return this.ORM.querier.rollback().then(() => {
251 console.error(error);
252 return error;
253 });
254 });
255
256};
257
258ModelFactory.prototype.update = function(where, data, options) {
259 // Create Query
260 var queryData = new QueryObject(this.tableName, data, this.relationships, options);
261 var queryWhere = new QueryObject(this.tableName, where, this.relationships, options);
262 // Make search
263 return this.ORM.query.update({
264 ORM: this.ORM,
265 table: queryWhere.getTable(),
266 where: queryWhere.getAttributes(),
267 data: queryData.getAttributes(),
268 returning: this.getReturnAttributes()
269 });
270};
271
272ModelFactory.prototype.find = function(where, options) {
273 // Create Query
274 var query = new QueryObject(this.tableName, where, this.relationships, options);
275 // Make search
276 return this.ORM.query.find({
277 ORM: this.ORM,
278 table: query.getTable(),
279 join: query.getJoin(),
280 where: query.getAttributes(),
281 relationships: query.getRelationships(),
282 options: query.getOptions(),
283 returning: this.getReturnAttributes()
284 })
285 // Initialize model
286 .then((rawData) => {
287 return this.initializeModels(rawData);
288 })
289 // Include relationships
290 .then((models) => {
291 return (options && options.include) ?
292 this.includeForMany(models, options.include) :
293 models;
294 });
295};
296
297ModelFactory.prototype.findOne = function(where, options) {
298 options = Object.assign({}, options, { limit: 1 });
299 return this.find(where, options).then((models) => {
300 return models[0];
301 });
302};
303
304ModelFactory.prototype.findOrCreate = function(where, options) {
305 /*
306 options.limit = 1;
307 return this.find(where, options).then((model) => {
308 if(model) {
309 return model;
310 } else {
311 return this.create(where);
312 }
313 });
314 */
315};
316
317ModelFactory.prototype.delete = function(where, options) {
318 // Create Query
319 var query = new QueryObject(this.tableName, where, this.relationships, options);
320 // Make search
321 return this.ORM.query.delete({
322 ORM: this.ORM,
323 table: query.getTable(),
324 where: query.getAttributes(),
325 returning: this.getReturnAttributes()
326 });
327};
328
329//
330// Relationship
331//
332
333ModelFactory.prototype.belongsToOne = function(modelFactoryName, parentIdentifer, childIdentifer) {
334 return new Relationship({
335 ORM: this.ORM,
336 type: Relationship.Types.belongsToOne,
337 modelFactoryName: modelFactoryName,
338 parentIdentifer: parentIdentifer,
339 childIdentifer: childIdentifer
340 });
341};
342
343ModelFactory.prototype.belongsToMany = function(modelFactoryName, throughTableName,
344 parentIdentifer_0, childIdentifer_0, parentIdentifer_1, childIdentifer_1) {
345 return new Relationship({
346 ORM: this.ORM,
347 type: Relationship.Types.belongsToMany,
348 modelFactoryName: modelFactoryName,
349 parentIdentifer_0: parentIdentifer_0,
350 childIdentifer_0: childIdentifer_0,
351 parentIdentifer_1: parentIdentifer_1,
352 childIdentifer_1: childIdentifer_1,
353 throughTableName: throughTableName
354 });
355};
356
357ModelFactory.prototype.hasMany = function(modelFactoryName, parentIdentifer, childIdentifer) {
358 return new Relationship({
359 ORM: this.ORM,
360 type: Relationship.Types.hasMany,
361 modelFactoryName: modelFactoryName,
362 parentIdentifer: parentIdentifer,
363 childIdentifer: childIdentifer
364 });
365};
366
367ModelFactory.prototype.hasOne = function(modelFactoryName, parentIdentifer, childIdentifer) {
368 return new Relationship({
369 ORM: this.ORM,
370 type: Relationship.Types.hasOne,
371 modelFactoryName: modelFactoryName,
372 parentIdentifer: parentIdentifer,
373 childIdentifer: childIdentifer
374 });
375};
376
377
378module.exports = ModelFactory;
\No newline at end of file