Skip to content

Commit 2b6b73a

Browse files
committed
Stable Version 0.8.0.
Closes #5.
1 parent 62e407c commit 2b6b73a

13 files changed

+404
-59
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
##### 0.8.0 - 09 July 2015
2+
3+
###### Backwards compatible API changes
4+
- #5 - Support for loading relations in `findAll`
5+
16
##### 0.7.0 - 02 July 2015
27

38
Stable Version 0.7.0

Gruntfile.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ module.exports = function (grunt) {
5151
'mout/array/map',
5252
'mout/lang/toString',
5353
'mout/string/underscore',
54+
'mout/array/unique',
5455
'js-data',
5556
'knex'
5657
],

dist/js-data-sql.js

Lines changed: 149 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,16 @@ module.exports =
5151

5252
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
5353

54+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
55+
5456
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
5557

56-
var knex = __webpack_require__(1);
57-
var JSData = __webpack_require__(2);
58-
var map = __webpack_require__(3);
59-
var underscore = __webpack_require__(4);
60-
var toString = __webpack_require__(5);
58+
var knex = __webpack_require__(2);
59+
var JSData = __webpack_require__(3);
60+
var map = __webpack_require__(4);
61+
var underscore = __webpack_require__(1);
62+
var unique = __webpack_require__(5);
63+
var toString = __webpack_require__(6);
6164
var DSUtils = JSData.DSUtils;
6265
var keys = DSUtils.keys;
6366
var isEmpty = DSUtils.isEmpty;
@@ -66,6 +69,7 @@ module.exports =
6669
var contains = DSUtils.contains;
6770
var forOwn = DSUtils.forOwn;
6871
var deepMixIn = DSUtils.deepMixIn;
72+
var filter = DSUtils.filter;
6973
var forEach = DSUtils.forEach;
7074
var isObject = DSUtils.isObject;
7175
var isString = DSUtils.isString;
@@ -207,7 +211,8 @@ module.exports =
207211

208212
forEach(resourceConfig.relationList, function (def) {
209213
var relationName = def.relation;
210-
if (contains(options['with'], relationName)) {
214+
if (contains(options['with'], relationName) || contains(options['with'], def.localField)) {
215+
DSUtils.remove(options['with'], relationName);
211216
var task = undefined;
212217
var params = {};
213218
if (resourceConfig.allowSimpleWhere) {
@@ -222,15 +227,15 @@ module.exports =
222227
if (def.type === 'hasMany' && params[def.foreignKey]) {
223228
task = _this.findAll(resourceConfig.getResource(relationName), params, options);
224229
} else if (def.type === 'hasOne') {
225-
if (def.localKey && instance[def.localKey]) {
226-
task = _this.find(resourceConfig.getResource(relationName), instance[def.localKey], options);
230+
if (def.localKey && DSUtils.get(instance, def.localKey)) {
231+
task = _this.find(resourceConfig.getResource(relationName), DSUtils.get(instance, def.localKey), options);
227232
} else if (def.foreignKey && params[def.foreignKey]) {
228233
task = _this.findAll(resourceConfig.getResource(relationName), params, options).then(function (hasOnes) {
229234
return hasOnes.length ? hasOnes[0] : null;
230235
});
231236
}
232-
} else if (instance[def.localKey]) {
233-
task = _this.find(resourceConfig.getResource(relationName), instance[def.localKey], options);
237+
} else if (DSUtils.get(instance, def.localKey)) {
238+
task = _this.find(resourceConfig.getResource(relationName), DSUtils.get(instance, def.localKey), options);
234239
}
235240

236241
if (task) {
@@ -249,27 +254,141 @@ module.exports =
249254
}
250255
}).then(function (loadedRelations) {
251256
forEach(fields, function (field, index) {
252-
return instance[field] = loadedRelations[index];
257+
return DSUtils.set(instance, field, loadedRelations[index]);
253258
});
254259
return instance;
255260
});
256261
}
257262
}, {
258263
key: 'findAll',
259264
value: function findAll(resourceConfig, params, options) {
260-
return filterQuery.call(this, resourceConfig, params, options);
265+
var _this2 = this;
266+
267+
var items = null;
268+
options = options || {};
269+
options['with'] = options['with'] || [];
270+
return filterQuery.call(this, resourceConfig, params, options).then(function (_items) {
271+
items = _items;
272+
var tasks = [];
273+
forEach(resourceConfig.relationList, function (def) {
274+
var relationName = def.relation;
275+
var relationDef = resourceConfig.getResource(relationName);
276+
var containedName = null;
277+
if (contains(options['with'], relationName)) {
278+
containedName = relationName;
279+
} else if (contains(options['with'], def.localField)) {
280+
containedName = def.localField;
281+
}
282+
if (containedName) {
283+
(function () {
284+
var __options = DSUtils.deepMixIn({}, options.orig ? options.orig() : options);
285+
__options = DSUtils._(relationDef, __options);
286+
DSUtils.remove(__options['with'], containedName);
287+
forEach(__options['with'], function (relation, i) {
288+
if (relation && relation.indexOf(containedName) === 0 && relation.length >= containedName.length && relation[containedName.length] === '.') {
289+
__options['with'][i] = relation.substr(containedName.length + 1);
290+
}
291+
});
292+
293+
var task = undefined;
294+
295+
if ((def.type === 'hasOne' || def.type === 'hasMany') && def.foreignKey) {
296+
task = _this2.findAll(resourceConfig.getResource(relationName), {
297+
where: _defineProperty({}, def.foreignKey, {
298+
'in': filter(map(items, function (item) {
299+
return DSUtils.get(item, resourceConfig.idAttribute);
300+
}), function (x) {
301+
return x;
302+
})
303+
})
304+
}, __options).then(function (relatedItems) {
305+
forEach(items, function (item) {
306+
var attached = [];
307+
forEach(relatedItems, function (relatedItem) {
308+
if (DSUtils.get(relatedItem, def.foreignKey) === item[resourceConfig.idAttribute]) {
309+
attached.push(relatedItem);
310+
}
311+
});
312+
if (def.type === 'hasOne' && attached.length) {
313+
DSUtils.set(item, def.localField, attached[0]);
314+
} else {
315+
DSUtils.set(item, def.localField, attached);
316+
}
317+
});
318+
return relatedItems;
319+
});
320+
} else if (def.type === 'hasMany' && def.localKeys) {
321+
(function () {
322+
var localKeys = [];
323+
forEach(items, function (item) {
324+
var itemKeys = item[def.localKeys] || [];
325+
itemKeys = Array.isArray(itemKeys) ? itemKeys : keys(itemKeys);
326+
localKeys = localKeys.concat(itemKeys || []);
327+
});
328+
task = _this2.findAll(resourceConfig.getResource(relationName), {
329+
where: _defineProperty({}, relationDef.idAttribute, {
330+
'in': filter(unique(localKeys), function (x) {
331+
return x;
332+
})
333+
})
334+
}, __options).then(function (relatedItems) {
335+
forEach(items, function (item) {
336+
var attached = [];
337+
var itemKeys = item[def.localKeys] || [];
338+
itemKeys = Array.isArray(itemKeys) ? itemKeys : keys(itemKeys);
339+
forEach(relatedItems, function (relatedItem) {
340+
if (itemKeys && contains(itemKeys, relatedItem[relationDef.idAttribute])) {
341+
attached.push(relatedItem);
342+
}
343+
});
344+
DSUtils.set(item, def.localField, attached);
345+
});
346+
return relatedItems;
347+
});
348+
})();
349+
} else if (def.type === 'belongsTo' || def.type === 'hasOne' && def.localKey) {
350+
task = _this2.findAll(resourceConfig.getResource(relationName), {
351+
where: _defineProperty({}, relationDef.idAttribute, {
352+
'in': filter(map(items, function (item) {
353+
return DSUtils.get(item, def.localKey);
354+
}), function (x) {
355+
return x;
356+
})
357+
})
358+
}, __options).then(function (relatedItems) {
359+
forEach(items, function (item) {
360+
forEach(relatedItems, function (relatedItem) {
361+
if (relatedItem[relationDef.idAttribute] === item[def.localKey]) {
362+
DSUtils.set(item, def.localField, relatedItem);
363+
}
364+
});
365+
});
366+
return relatedItems;
367+
});
368+
}
369+
370+
if (task) {
371+
tasks.push(task);
372+
}
373+
})();
374+
}
375+
});
376+
return DSUtils.Promise.all(tasks);
377+
}).then(function () {
378+
return items;
379+
});
261380
}
262381
}, {
263382
key: 'create',
264383
value: function create(resourceConfig, attrs) {
265-
var _this2 = this;
384+
var _this3 = this;
266385

267386
attrs = removeCircular(omit(attrs, resourceConfig.relationFields || []));
268387
return this.query(resourceConfig.table || underscore(resourceConfig.name)).insert(attrs, resourceConfig.idAttribute).then(function (ids) {
269388
if (attrs[resourceConfig.idAttribute]) {
270-
return _this2.find(resourceConfig, attrs[resourceConfig.idAttribute]);
389+
return _this3.find(resourceConfig, attrs[resourceConfig.idAttribute]);
271390
} else if (ids.length) {
272-
return _this2.find(resourceConfig, ids[0]);
391+
return _this3.find(resourceConfig, ids[0]);
273392
} else {
274393
throw new Error('Failed to create!');
275394
}
@@ -278,30 +397,30 @@ module.exports =
278397
}, {
279398
key: 'update',
280399
value: function update(resourceConfig, id, attrs) {
281-
var _this3 = this;
400+
var _this4 = this;
282401

283402
attrs = removeCircular(omit(attrs, resourceConfig.relationFields || []));
284403
return this.query(resourceConfig.table || underscore(resourceConfig.name)).where(resourceConfig.idAttribute, toString(id)).update(attrs).then(function () {
285-
return _this3.find(resourceConfig, id);
404+
return _this4.find(resourceConfig, id);
286405
});
287406
}
288407
}, {
289408
key: 'updateAll',
290409
value: function updateAll(resourceConfig, attrs, params, options) {
291-
var _this4 = this;
410+
var _this5 = this;
292411

293412
attrs = removeCircular(omit(attrs, resourceConfig.relationFields || []));
294413
return filterQuery.call(this, resourceConfig, params, options).then(function (items) {
295414
return map(items, function (item) {
296415
return item[resourceConfig.idAttribute];
297416
});
298417
}).then(function (ids) {
299-
return filterQuery.call(_this4, resourceConfig, params, options).update(attrs).then(function () {
418+
return filterQuery.call(_this5, resourceConfig, params, options).update(attrs).then(function () {
300419
var _params = { where: {} };
301420
_params.where[resourceConfig.idAttribute] = {
302421
'in': ids
303422
};
304-
return filterQuery.call(_this4, resourceConfig, _params, options);
423+
return filterQuery.call(_this5, resourceConfig, _params, options);
305424
});
306425
});
307426
}
@@ -331,28 +450,34 @@ module.exports =
331450
/* 1 */
332451
/***/ function(module, exports) {
333452

334-
module.exports = require("knex");
453+
module.exports = require("mout/string/underscore");
335454

336455
/***/ },
337456
/* 2 */
338457
/***/ function(module, exports) {
339458

340-
module.exports = require("js-data");
459+
module.exports = require("knex");
341460

342461
/***/ },
343462
/* 3 */
344463
/***/ function(module, exports) {
345464

346-
module.exports = require("mout/array/map");
465+
module.exports = require("js-data");
347466

348467
/***/ },
349468
/* 4 */
350469
/***/ function(module, exports) {
351470

352-
module.exports = require("mout/string/underscore");
471+
module.exports = require("mout/array/map");
353472

354473
/***/ },
355474
/* 5 */
475+
/***/ function(module, exports) {
476+
477+
module.exports = require("mout/array/unique");
478+
479+
/***/ },
480+
/* 6 */
356481
/***/ function(module, exports) {
357482

358483
module.exports = require("mout/lang/toString");

mocha.start.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ var JSData = require('js-data');
88
JSData.DSUtils.Promise = require('bluebird');
99
var DSSqlAdapter = require('./');
1010

11-
var adapter, store, DSUtils, DSErrors, User, Post, Comment;
11+
var adapter, store, DSUtils, DSErrors, Profile, User, Post, Comment;
1212

1313
var globals = module.exports = {
1414
fail: function (msg) {
@@ -55,12 +55,17 @@ beforeEach(function () {
5555
adapter = new DSSqlAdapter({
5656
client: 'mysql',
5757
connection: {
58-
user: 'ubuntu',
59-
database: 'circle_test'
58+
//user: 'ubuntu',
59+
//database: 'circle_test'
60+
user: 'root',
61+
database: 'test'
6062
}
6163
});
6264
DSUtils = JSData.DSUtils;
6365
DSErrors = JSData.DSErrors;
66+
globals.Profile = global.Profile = Profile = store.defineResource({
67+
name: 'profile'
68+
});
6469
globals.User = global.User = User = store.defineResource({
6570
name: 'user',
6671
relations: {
@@ -69,6 +74,12 @@ beforeEach(function () {
6974
localField: 'posts',
7075
foreignKey: 'post'
7176
}
77+
},
78+
hasOne: {
79+
profile: {
80+
localField: 'profile',
81+
localKey: 'profileId'
82+
}
7283
}
7384
}
7485
});

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "js-data-sql",
33
"description": "Postgres/MySQL/MariaDB/SQLite3 adapter for js-data.",
4-
"version": "0.7.0",
4+
"version": "0.8.0",
55
"homepage": "http://www.js-data.io/docs/dssqladapter",
66
"repository": {
77
"type": "git",

0 commit comments

Comments
 (0)