js-data-adapter
Advanced tools
Comparing version 0.1.4 to 0.2.0
@@ -0,1 +1,5 @@ | ||
##### 0.2.0 - 10 March 2016 | ||
Pulled a lot more common adapter functionality into js-data-adapter. | ||
##### 0.1.4 - 09 March 2016 | ||
@@ -2,0 +6,0 @@ |
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('js-data')) : | ||
typeof define === 'function' && define.amd ? define('js-data-adapter', ['exports', 'js-data'], factory) : | ||
(factory((global.Adapter = global.Adapter || {}),global.js-data)); | ||
}(this, function (exports,jsData) { 'use strict'; | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('js-data')) : | ||
typeof define === 'function' && define.amd ? define('js-data-adapter', ['js-data'], factory) : | ||
(factory(global.JSData)); | ||
}(this, function (jsData) { 'use strict'; | ||
@@ -29,2 +29,40 @@ var babelHelpers = {}; | ||
babelHelpers.slicedToArray = function () { | ||
function sliceIterator(arr, i) { | ||
var _arr = []; | ||
var _n = true; | ||
var _d = false; | ||
var _e = undefined; | ||
try { | ||
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { | ||
_arr.push(_s.value); | ||
if (i && _arr.length === i) break; | ||
} | ||
} catch (err) { | ||
_d = true; | ||
_e = err; | ||
} finally { | ||
try { | ||
if (!_n && _i["return"]) _i["return"](); | ||
} finally { | ||
if (_d) throw _e; | ||
} | ||
} | ||
return _arr; | ||
} | ||
return function (arr, i) { | ||
if (Array.isArray(arr)) { | ||
return arr; | ||
} else if (Symbol.iterator in Object(arr)) { | ||
return sliceIterator(arr, i); | ||
} else { | ||
throw new TypeError("Invalid attempt to destructure non-iterable instance"); | ||
} | ||
}; | ||
}(); | ||
babelHelpers; | ||
@@ -35,2 +73,3 @@ | ||
var fillIn = jsData.utils.fillIn; | ||
var forEachRelation = jsData.utils.forEachRelation; | ||
var get = jsData.utils.get; | ||
@@ -40,2 +79,3 @@ var isArray = jsData.utils.isArray; | ||
var isUndefined = jsData.utils.isUndefined; | ||
var omit = jsData.utils.omit; | ||
var plainCopy = jsData.utils.plainCopy; | ||
@@ -45,4 +85,2 @@ var resolve = jsData.utils.resolve; | ||
var reserved = ['orderBy', 'sort', 'limit', 'offset', 'skip', 'where']; | ||
var noop = function noop() { | ||
@@ -72,2 +110,19 @@ var self = this; | ||
var unique = function unique(array) { | ||
var seen = {}; | ||
var final = []; | ||
array.forEach(function (item) { | ||
if (item in seen) { | ||
return; | ||
} | ||
final.push(item); | ||
seen[item] = 0; | ||
}); | ||
return final; | ||
}; | ||
var withoutRelations = function withoutRelations(mapper, props) { | ||
return omit(props, mapper.relationFields || []); | ||
}; | ||
var DEFAULTS = { | ||
@@ -94,19 +149,2 @@ /** | ||
/** | ||
* Response object used when `raw` is `true`. May contain other fields in | ||
* addition to `data`. | ||
* | ||
* @typedef {Object} Response | ||
* @property {Object} data Response data. | ||
* @property {string} op The operation for which the response was created. | ||
*/ | ||
function Response(data, meta, op) { | ||
var self = this; | ||
meta || (meta = {}); | ||
self.data = data; | ||
fillIn(self, meta); | ||
self.op = op; | ||
} | ||
/** | ||
* Abstract class meant to be extended by adapters. | ||
@@ -128,3 +166,23 @@ * | ||
Adapter.reserved = ['orderBy', 'sort', 'limit', 'offset', 'skip', 'where']; | ||
/** | ||
* Response object used when `raw` is `true`. May contain other fields in | ||
* addition to `data`. | ||
* | ||
* @typedef {Object} Response | ||
* @property {Object} data Response data. | ||
* @property {string} op The operation for which the response was created. | ||
*/ | ||
function Response(data, meta, op) { | ||
var self = this; | ||
meta || (meta = {}); | ||
self.data = data; | ||
fillIn(self, meta); | ||
self.op = op; | ||
} | ||
Adapter.Response = Response; | ||
/** | ||
* Alternative to ES6 class syntax for extending `Adapter`. | ||
@@ -542,3 +600,3 @@ * | ||
/** | ||
* Create a new record. Called by `Mapper#create`. | ||
* Create a new record. Called by `Mapper#create`. | ||
* | ||
@@ -555,3 +613,34 @@ * @name Adapter#create | ||
create: function create(mapper, props, opts) { | ||
throw new Error('Not supported!'); | ||
var self = this; | ||
var op = void 0; | ||
props || (props = {}); | ||
opts || (opts = {}); | ||
// beforeCreate lifecycle hook | ||
op = opts.op = 'beforeCreate'; | ||
return resolve(self[op](mapper, props, opts)).then(function (_props) { | ||
// Allow for re-assignment from lifecycle hook | ||
props = isUndefined(_props) ? props : _props; | ||
props = withoutRelations(mapper, props); | ||
op = opts.op = 'create'; | ||
self.dbg(op, mapper, props, opts); | ||
return resolve(self._create(mapper, props, opts)); | ||
}).then(function (results) { | ||
var _results = babelHelpers.slicedToArray(results, 2); | ||
var data = _results[0]; | ||
var result = _results[1]; | ||
result || (result = {}); | ||
var response = new Response(data, result, 'create'); | ||
response.created = data ? 1 : 0; | ||
response = self.respond(response, opts); | ||
// afterCreate lifecycle hook | ||
op = opts.op = 'afterCreate'; | ||
return resolve(self[op](mapper, props, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response; | ||
}); | ||
}); | ||
}, | ||
@@ -573,3 +662,37 @@ | ||
createMany: function createMany(mapper, props, opts) { | ||
throw new Error('Not supported!'); | ||
var self = this; | ||
var op = void 0; | ||
props || (props = {}); | ||
opts || (opts = {}); | ||
// beforeCreateMany lifecycle hook | ||
op = opts.op = 'beforeCreateMany'; | ||
return resolve(self[op](mapper, props, opts)).then(function (_props) { | ||
// Allow for re-assignment from lifecycle hook | ||
props = isUndefined(_props) ? props : _props; | ||
props = props.map(function (record) { | ||
return withoutRelations(mapper, record); | ||
}); | ||
op = opts.op = 'createMany'; | ||
self.dbg(op, mapper, props, opts); | ||
return resolve(self._createMany(mapper, props, opts)); | ||
}).then(function (results) { | ||
var _results2 = babelHelpers.slicedToArray(results, 2); | ||
var data = _results2[0]; | ||
var result = _results2[1]; | ||
data || (data = []); | ||
result || (result = {}); | ||
var response = new Response(data, result, 'createMany'); | ||
response.created = data.length; | ||
response = self.respond(response, opts); | ||
// afterCreateMany lifecycle hook | ||
op = opts.op = 'afterCreateMany'; | ||
return resolve(self[op](mapper, props, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response; | ||
}); | ||
}); | ||
}, | ||
@@ -592,3 +715,29 @@ | ||
destroy: function destroy(mapper, id, opts) { | ||
throw new Error('Not supported!'); | ||
var self = this; | ||
var op = void 0; | ||
opts || (opts = {}); | ||
// beforeDestroy lifecycle hook | ||
op = opts.op = 'beforeDestroy'; | ||
return resolve(self[op](mapper, id, opts)).then(function () { | ||
op = opts.op = 'destroy'; | ||
self.dbg(op, mapper, id, opts); | ||
return resolve(self._destroy(mapper, id, opts)); | ||
}).then(function (results) { | ||
var _results3 = babelHelpers.slicedToArray(results, 2); | ||
var data = _results3[0]; | ||
var result = _results3[1]; | ||
result || (result = {}); | ||
var response = new Response(data, result, 'destroy'); | ||
response = self.respond(response, opts); | ||
// afterDestroy lifecycle hook | ||
op = opts.op = 'afterDestroy'; | ||
return resolve(self[op](mapper, id, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response; | ||
}); | ||
}); | ||
}, | ||
@@ -617,3 +766,30 @@ | ||
destroyAll: function destroyAll(mapper, query, opts) { | ||
throw new Error('Not supported!'); | ||
var self = this; | ||
var op = void 0; | ||
query || (query = {}); | ||
opts || (opts = {}); | ||
// beforeDestroyAll lifecycle hook | ||
op = opts.op = 'beforeDestroyAll'; | ||
return resolve(self[op](mapper, query, opts)).then(function () { | ||
op = opts.op = 'destroyAll'; | ||
self.dbg(op, mapper, query, opts); | ||
return resolve(self._destroyAll(mapper, query, opts)); | ||
}).then(function (results) { | ||
var _results4 = babelHelpers.slicedToArray(results, 2); | ||
var data = _results4[0]; | ||
var result = _results4[1]; | ||
result || (result = {}); | ||
var response = new Response(data, result, 'destroyAll'); | ||
response = self.respond(response, opts); | ||
// afterDestroyAll lifecycle hook | ||
op = opts.op = 'afterDestroyAll'; | ||
return resolve(self[op](mapper, query, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response; | ||
}); | ||
}); | ||
}, | ||
@@ -702,4 +878,103 @@ | ||
}, | ||
loadHasManyLocalKeys: function loadHasManyLocalKeys(mapper, def, records, __opts) { | ||
var self = this; | ||
var record = void 0; | ||
var relatedMapper = def.getRelation(); | ||
if (isObject(records) && !isArray(records)) { | ||
record = records; | ||
} | ||
if (record) { | ||
var localKeys = []; | ||
var itemKeys = get(record, def.localKeys) || []; | ||
itemKeys = isArray(itemKeys) ? itemKeys : Object.keys(itemKeys); | ||
localKeys = localKeys.concat(itemKeys); | ||
return self.findAll(relatedMapper, { | ||
where: babelHelpers.defineProperty({}, relatedMapper.idAttribute, { | ||
'in': unique(localKeys).filter(function (x) { | ||
return x; | ||
}) | ||
}) | ||
}, __opts).then(function (relatedItems) { | ||
def.setLocalField(record, relatedItems); | ||
}); | ||
} else { | ||
var _ret = function () { | ||
var localKeys = []; | ||
records.forEach(function (item) { | ||
var itemKeys = item[def.localKeys] || []; | ||
itemKeys = isArray(itemKeys) ? itemKeys : Object.keys(itemKeys); | ||
localKeys = localKeys.concat(itemKeys); | ||
}); | ||
return { | ||
v: self.findAll(relatedMapper, { | ||
where: babelHelpers.defineProperty({}, relatedMapper.idAttribute, { | ||
'in': unique(localKeys).filter(function (x) { | ||
return x; | ||
}) | ||
}) | ||
}, __opts).then(function (relatedItems) { | ||
records.forEach(function (item) { | ||
var attached = []; | ||
var itemKeys = get(item, def.localKeys) || []; | ||
itemKeys = isArray(itemKeys) ? itemKeys : Object.keys(itemKeys); | ||
relatedItems.forEach(function (relatedItem) { | ||
if (itemKeys && itemKeys.indexOf(relatedItem[relatedMapper.idAttribute]) !== -1) { | ||
attached.push(relatedItem); | ||
} | ||
}); | ||
def.setLocalField(item, attached); | ||
}); | ||
return relatedItems; | ||
}) | ||
}; | ||
}(); | ||
if ((typeof _ret === 'undefined' ? 'undefined' : babelHelpers.typeof(_ret)) === "object") return _ret.v; | ||
} | ||
}, | ||
loadHasManyForeignKeys: function loadHasManyForeignKeys(mapper, def, records, __opts) { | ||
var self = this; | ||
var relatedMapper = def.getRelation(); | ||
var idAttribute = mapper.idAttribute; | ||
var record = void 0; | ||
if (isObject(records) && !isArray(records)) { | ||
record = records; | ||
} | ||
if (record) { | ||
return self.findAll(def.getRelation(), { | ||
where: babelHelpers.defineProperty({}, def.foreignKeys, { | ||
'contains': self.makeHasManyForeignKeys(mapper, def, record) | ||
}) | ||
}, __opts).then(function (relatedItems) { | ||
def.setLocalField(record, relatedItems); | ||
}); | ||
} else { | ||
return self.findAll(relatedMapper, { | ||
where: babelHelpers.defineProperty({}, def.foreignKeys, { | ||
'isectNotEmpty': records.map(function (record) { | ||
return self.makeHasManyForeignKeys(mapper, def, record); | ||
}) | ||
}) | ||
}, __opts).then(function (relatedItems) { | ||
var foreignKeysField = def.foreignKeys; | ||
records.forEach(function (record) { | ||
var _relatedItems = []; | ||
var id = get(record, idAttribute); | ||
relatedItems.forEach(function (relatedItem) { | ||
var foreignKeys = get(relatedItems, foreignKeysField) || []; | ||
if (foreignKeys.indexOf(id) !== -1) { | ||
_relatedItems.push(relatedItem); | ||
} | ||
}); | ||
def.setLocalField(record, _relatedItems); | ||
}); | ||
}); | ||
} | ||
}, | ||
/** | ||
@@ -757,3 +1032,3 @@ * Load a hasOne relationship. | ||
if (isObject(records) && !isArray(records)) { | ||
var _ret = function () { | ||
var _ret2 = function () { | ||
var record = records; | ||
@@ -767,3 +1042,3 @@ return { | ||
if ((typeof _ret === 'undefined' ? 'undefined' : babelHelpers.typeof(_ret)) === "object") return _ret.v; | ||
if ((typeof _ret2 === 'undefined' ? 'undefined' : babelHelpers.typeof(_ret2)) === "object") return _ret2.v; | ||
} else { | ||
@@ -806,3 +1081,58 @@ var keys = records.map(function (record) { | ||
find: function find(mapper, id, opts) { | ||
throw new Error('Not supported!'); | ||
var self = this; | ||
var record = void 0, | ||
op = void 0; | ||
opts || (opts = {}); | ||
opts.with || (opts.with = []); | ||
// beforeFind lifecycle hook | ||
op = opts.op = 'beforeFind'; | ||
return resolve(self[op](mapper, id, opts)).then(function () { | ||
op = opts.op = 'find'; | ||
self.dbg(op, mapper, id, opts); | ||
return resolve(self._find(mapper, id, opts)); | ||
}).then(function (results) { | ||
var _results5 = babelHelpers.slicedToArray(results, 1); | ||
var _record = _results5[0]; | ||
if (!_record) { | ||
return; | ||
} | ||
record = _record; | ||
var tasks = []; | ||
forEachRelation(mapper, opts, function (def, __opts) { | ||
var task = void 0; | ||
if (def.foreignKey && (def.type === 'hasOne' || def.type === 'hasMany')) { | ||
if (def.type === 'hasOne') { | ||
task = self.loadHasOne(mapper, def, record, __opts); | ||
} else { | ||
task = self.loadHasMany(mapper, def, record, __opts); | ||
} | ||
} else if (def.type === 'hasMany' && def.localKeys) { | ||
task = self.loadHasManyLocalKeys(mapper, def, record, __opts); | ||
} else if (def.type === 'hasMany' && def.foreignKeys) { | ||
task = self.loadHasManyForeignKeys(mapper, def, record, __opts); | ||
} else if (def.type === 'belongsTo') { | ||
task = self.loadBelongsTo(mapper, def, record, __opts); | ||
} | ||
if (task) { | ||
tasks.push(task); | ||
} | ||
}); | ||
return Promise.all(tasks); | ||
}).then(function () { | ||
var response = new Response(record, {}, 'find'); | ||
response.found = record ? 1 : 0; | ||
response = self.respond(response, opts); | ||
// afterFind lifecycle hook | ||
op = opts.op = 'afterFind'; | ||
return resolve(self[op](mapper, id, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response; | ||
}); | ||
}); | ||
}, | ||
@@ -831,3 +1161,54 @@ | ||
findAll: function findAll(mapper, query, opts) { | ||
throw new Error('Not supported!'); | ||
var self = this; | ||
opts || (opts = {}); | ||
opts.with || (opts.with = []); | ||
var records = []; | ||
var op = void 0; | ||
// beforeFindAll lifecycle hook | ||
op = opts.op = 'beforeFindAll'; | ||
return resolve(self[op](mapper, query, opts)).then(function () { | ||
op = opts.op = 'findAll'; | ||
self.dbg(op, mapper, query, opts); | ||
return resolve(self._findAll(mapper, query, opts)); | ||
}).then(function (results) { | ||
var _results6 = babelHelpers.slicedToArray(results, 1); | ||
var _records = _results6[0]; | ||
_records || (_records = []); | ||
records = _records; | ||
var tasks = []; | ||
forEachRelation(mapper, opts, function (def, __opts) { | ||
var task = void 0; | ||
if (def.foreignKey && (def.type === 'hasOne' || def.type === 'hasMany')) { | ||
if (def.type === 'hasMany') { | ||
task = self.loadHasMany(mapper, def, records, __opts); | ||
} else { | ||
task = self.loadHasOne(mapper, def, records, __opts); | ||
} | ||
} else if (def.type === 'hasMany' && def.localKeys) { | ||
task = self.loadHasManyLocalKeys(mapper, def, records, __opts); | ||
} else if (def.type === 'hasMany' && def.foreignKeys) { | ||
task = self.loadHasManyForeignKeys(mapper, def, records, __opts); | ||
} else if (def.type === 'belongsTo') { | ||
task = self.loadBelongsTo(mapper, def, records, __opts); | ||
} | ||
if (task) { | ||
tasks.push(task); | ||
} | ||
}); | ||
return Promise.all(tasks); | ||
}).then(function () { | ||
var response = new Response(records, {}, 'findAll'); | ||
response.found = records.length; | ||
response = self.respond(response, opts); | ||
// afterFindAll lifecycle hook | ||
op = opts.op = 'afterFindAll'; | ||
return resolve(self[op](mapper, query, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response; | ||
}); | ||
}); | ||
}, | ||
@@ -914,3 +1295,33 @@ | ||
update: function update(mapper, id, props, opts) { | ||
throw new Error('Not supported!'); | ||
var self = this; | ||
props || (props = {}); | ||
opts || (opts = {}); | ||
var op = void 0; | ||
// beforeUpdate lifecycle hook | ||
op = opts.op = 'beforeUpdate'; | ||
return resolve(self[op](mapper, id, props, opts)).then(function (_props) { | ||
// Allow for re-assignment from lifecycle hook | ||
props = isUndefined(_props) ? props : _props; | ||
op = opts.op = 'update'; | ||
self.dbg(op, mapper, id, props, opts); | ||
return resolve(self._update(mapper, id, props, opts)); | ||
}).then(function (results) { | ||
var _results7 = babelHelpers.slicedToArray(results, 2); | ||
var data = _results7[0]; | ||
var result = _results7[1]; | ||
result || (result = {}); | ||
var response = new Response(data, result, 'update'); | ||
response.updated = data ? 1 : 0; | ||
response = self.respond(response, opts); | ||
// afterUpdate lifecycle hook | ||
op = opts.op = 'afterUpdate'; | ||
return resolve(self[op](mapper, id, props, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response; | ||
}); | ||
}); | ||
}, | ||
@@ -940,3 +1351,35 @@ | ||
updateAll: function updateAll(mapper, props, query, opts) { | ||
throw new Error('Not supported!'); | ||
var self = this; | ||
props || (props = {}); | ||
query || (query = {}); | ||
opts || (opts = {}); | ||
var op = void 0; | ||
// beforeUpdateAll lifecycle hook | ||
op = opts.op = 'beforeUpdateAll'; | ||
return resolve(self[op](mapper, props, query, opts)).then(function (_props) { | ||
// Allow for re-assignment from lifecycle hook | ||
props = isUndefined(_props) ? props : _props; | ||
op = opts.op = 'updateAll'; | ||
self.dbg(op, mapper, props, query, opts); | ||
return resolve(self._updateAll(mapper, props, query, opts)); | ||
}).then(function (results) { | ||
var _results8 = babelHelpers.slicedToArray(results, 2); | ||
var data = _results8[0]; | ||
var result = _results8[1]; | ||
data || (data = []); | ||
result || (result = {}); | ||
var response = new Response(data, result, 'updateAll'); | ||
response.updated = data.length; | ||
response = self.respond(response, opts); | ||
// afterUpdateAll lifecycle hook | ||
op = opts.op = 'afterUpdateAll'; | ||
return resolve(self[op](mapper, props, query, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response; | ||
}); | ||
}); | ||
}, | ||
@@ -958,11 +1401,48 @@ | ||
updateMany: function updateMany(mapper, records, opts) { | ||
throw new Error('Not supported!'); | ||
var self = this; | ||
records || (records = []); | ||
opts || (opts = {}); | ||
var op = void 0; | ||
var idAttribute = mapper.idAttribute; | ||
records = records.filter(function (record) { | ||
return get(record, idAttribute); | ||
}); | ||
// beforeUpdateMany lifecycle hook | ||
op = opts.op = 'beforeUpdateMany'; | ||
return resolve(self[op](mapper, records, opts)).then(function (_records) { | ||
// Allow for re-assignment from lifecycle hook | ||
records = isUndefined(_records) ? records : _records; | ||
records = records.map(function (record) { | ||
return withoutRelations(mapper, record); | ||
}); | ||
op = opts.op = 'updateMany'; | ||
self.dbg(op, mapper, records, opts); | ||
return resolve(self._updateMany(mapper, records, opts)); | ||
}).then(function (results) { | ||
var _results9 = babelHelpers.slicedToArray(results, 2); | ||
var data = _results9[0]; | ||
var result = _results9[1]; | ||
data || (data = []); | ||
result || (result = {}); | ||
var response = new Response(data, result, 'updateMany'); | ||
response.updated = data.length; | ||
response = self.respond(response, opts); | ||
// afterUpdateMany lifecycle hook | ||
op = opts.op = 'afterUpdateMany'; | ||
return resolve(self[op](mapper, records, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response; | ||
}); | ||
}); | ||
} | ||
}); | ||
exports.reserved = reserved; | ||
exports.Response = Response; | ||
exports['default'] = Adapter; | ||
module.exports = Adapter; | ||
})); | ||
//# sourceMappingURL=js-data-adapter.js.map |
{ | ||
"name": "js-data-adapter", | ||
"description": "Base adapter class that all other js-data adapters extend.", | ||
"version": "0.1.4", | ||
"version": "0.2.0", | ||
"homepage": "https://github.com/js-data/js-data-adapter", | ||
@@ -25,5 +25,9 @@ "repository": { | ||
"watch": "watch \"npm run bundle\" src/", | ||
"test": "npm run lint && npm run bundle", | ||
"build": "npm run lint && npm run bundle", | ||
"mocha": "mocha -t 30000 -R dot -r source-map-support/register mocha.start.js", | ||
"cover": "istanbul cover --hook-run-in-context node_modules/mocha/bin/_mocha -- -t 30000 -R dot -r source-map-support/register mocha.start.js", | ||
"test": "npm run build && npm run cover", | ||
"repo-tools": "repo-tools updates && repo-tools changelog && repo-tools authors", | ||
"release": "npm test && npm run repo-tools" | ||
"release": "npm test && npm run repo-tools", | ||
"ci": "npm run test && cat coverage/lcov.info | coveralls || true" | ||
}, | ||
@@ -35,8 +39,16 @@ "peerDependencies": { | ||
"babel-core": "6.7.0", | ||
"babel-polyfill": "6.6.1", | ||
"babel-preset-es2015-rollup": "1.1.1", | ||
"chai": "3.5.0", | ||
"coveralls": "2.11.8", | ||
"istanbul": "0.4.2", | ||
"js-data-adapter-tests": "^2.0.0-alpha.14", | ||
"js-data-repo-tools": "0.2.0", | ||
"mocha": "2.4.5", | ||
"rollup": "0.25.4", | ||
"rollup-plugin-babel": "2.4.0", | ||
"sinon": "1.17.3", | ||
"source-map-support": "0.4.0", | ||
"watch": "0.17.1" | ||
} | ||
} |
485
src/index.js
@@ -7,2 +7,3 @@ import {utils} from 'js-data' | ||
fillIn, | ||
forEachRelation, | ||
get, | ||
@@ -12,2 +13,3 @@ isArray, | ||
isUndefined, | ||
omit, | ||
plainCopy, | ||
@@ -17,11 +19,2 @@ resolve | ||
export const reserved = [ | ||
'orderBy', | ||
'sort', | ||
'limit', | ||
'offset', | ||
'skip', | ||
'where' | ||
] | ||
const noop = function (...args) { | ||
@@ -41,2 +34,19 @@ const self = this | ||
const unique = function (array) { | ||
const seen = {} | ||
const final = [] | ||
array.forEach(function (item) { | ||
if (item in seen) { | ||
return | ||
} | ||
final.push(item) | ||
seen[item] = 0 | ||
}) | ||
return final | ||
} | ||
const withoutRelations = function (mapper, props) { | ||
return omit(props, mapper.relationFields || []) | ||
} | ||
const DEFAULTS = { | ||
@@ -63,19 +73,2 @@ /** | ||
/** | ||
* Response object used when `raw` is `true`. May contain other fields in | ||
* addition to `data`. | ||
* | ||
* @typedef {Object} Response | ||
* @property {Object} data Response data. | ||
* @property {string} op The operation for which the response was created. | ||
*/ | ||
export function Response (data, meta, op) { | ||
const self = this | ||
meta || (meta = {}) | ||
self.data = data | ||
fillIn(self, meta) | ||
self.op = op | ||
} | ||
/** | ||
* Abstract class meant to be extended by adapters. | ||
@@ -90,3 +83,3 @@ * | ||
*/ | ||
export default function Adapter (opts) { | ||
function Adapter (opts) { | ||
const self = this | ||
@@ -98,3 +91,30 @@ opts || (opts = {}) | ||
Adapter.reserved = [ | ||
'orderBy', | ||
'sort', | ||
'limit', | ||
'offset', | ||
'skip', | ||
'where' | ||
] | ||
/** | ||
* Response object used when `raw` is `true`. May contain other fields in | ||
* addition to `data`. | ||
* | ||
* @typedef {Object} Response | ||
* @property {Object} data Response data. | ||
* @property {string} op The operation for which the response was created. | ||
*/ | ||
function Response (data, meta, op) { | ||
const self = this | ||
meta || (meta = {}) | ||
self.data = data | ||
fillIn(self, meta) | ||
self.op = op | ||
} | ||
Adapter.Response = Response | ||
/** | ||
* Alternative to ES6 class syntax for extending `Adapter`. | ||
@@ -507,3 +527,3 @@ * | ||
/** | ||
* Create a new record. Called by `Mapper#create`. | ||
* Create a new record. Called by `Mapper#create`. | ||
* | ||
@@ -520,3 +540,30 @@ * @name Adapter#create | ||
create (mapper, props, opts) { | ||
throw new Error('Not supported!') | ||
const self = this | ||
let op | ||
props || (props = {}) | ||
opts || (opts = {}) | ||
// beforeCreate lifecycle hook | ||
op = opts.op = 'beforeCreate' | ||
return resolve(self[op](mapper, props, opts)).then(function (_props) { | ||
// Allow for re-assignment from lifecycle hook | ||
props = isUndefined(_props) ? props : _props | ||
props = withoutRelations(mapper, props) | ||
op = opts.op = 'create' | ||
self.dbg(op, mapper, props, opts) | ||
return resolve(self._create(mapper, props, opts)) | ||
}).then(function (results) { | ||
let [data, result] = results | ||
result || (result = {}) | ||
let response = new Response(data, result, 'create') | ||
response.created = data ? 1 : 0 | ||
response = self.respond(response, opts) | ||
// afterCreate lifecycle hook | ||
op = opts.op = 'afterCreate' | ||
return resolve(self[op](mapper, props, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response | ||
}) | ||
}) | ||
}, | ||
@@ -537,3 +584,33 @@ | ||
createMany (mapper, props, opts) { | ||
throw new Error('Not supported!') | ||
const self = this | ||
let op | ||
props || (props = {}) | ||
opts || (opts = {}) | ||
// beforeCreateMany lifecycle hook | ||
op = opts.op = 'beforeCreateMany' | ||
return resolve(self[op](mapper, props, opts)).then(function (_props) { | ||
// Allow for re-assignment from lifecycle hook | ||
props = isUndefined(_props) ? props : _props | ||
props = props.map(function (record) { | ||
return withoutRelations(mapper, record) | ||
}) | ||
op = opts.op = 'createMany' | ||
self.dbg(op, mapper, props, opts) | ||
return resolve(self._createMany(mapper, props, opts)) | ||
}).then(function (results) { | ||
let [data, result] = results | ||
data || (data = []) | ||
result || (result = {}) | ||
let response = new Response(data, result, 'createMany') | ||
response.created = data.length | ||
response = self.respond(response, opts) | ||
// afterCreateMany lifecycle hook | ||
op = opts.op = 'afterCreateMany' | ||
return resolve(self[op](mapper, props, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response | ||
}) | ||
}) | ||
}, | ||
@@ -555,3 +632,25 @@ | ||
destroy (mapper, id, opts) { | ||
throw new Error('Not supported!') | ||
const self = this | ||
let op | ||
opts || (opts = {}) | ||
// beforeDestroy lifecycle hook | ||
op = opts.op = 'beforeDestroy' | ||
return resolve(self[op](mapper, id, opts)).then(function () { | ||
op = opts.op = 'destroy' | ||
self.dbg(op, mapper, id, opts) | ||
return resolve(self._destroy(mapper, id, opts)) | ||
}).then(function (results) { | ||
let [data, result] = results | ||
result || (result = {}) | ||
let response = new Response(data, result, 'destroy') | ||
response = self.respond(response, opts) | ||
// afterDestroy lifecycle hook | ||
op = opts.op = 'afterDestroy' | ||
return resolve(self[op](mapper, id, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response | ||
}) | ||
}) | ||
}, | ||
@@ -579,3 +678,26 @@ | ||
destroyAll (mapper, query, opts) { | ||
throw new Error('Not supported!') | ||
const self = this | ||
let op | ||
query || (query = {}) | ||
opts || (opts = {}) | ||
// beforeDestroyAll lifecycle hook | ||
op = opts.op = 'beforeDestroyAll' | ||
return resolve(self[op](mapper, query, opts)).then(function () { | ||
op = opts.op = 'destroyAll' | ||
self.dbg(op, mapper, query, opts) | ||
return resolve(self._destroyAll(mapper, query, opts)) | ||
}).then(function (results) { | ||
let [data, result] = results | ||
result || (result = {}) | ||
let response = new Response(data, result, 'destroyAll') | ||
response = self.respond(response, opts) | ||
// afterDestroyAll lifecycle hook | ||
op = opts.op = 'afterDestroyAll' | ||
return resolve(self[op](mapper, query, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response | ||
}) | ||
}) | ||
}, | ||
@@ -662,2 +784,101 @@ | ||
loadHasManyLocalKeys (mapper, def, records, __opts) { | ||
const self = this | ||
let record | ||
const relatedMapper = def.getRelation() | ||
if (isObject(records) && !isArray(records)) { | ||
record = records | ||
} | ||
if (record) { | ||
let localKeys = [] | ||
let itemKeys = get(record, def.localKeys) || [] | ||
itemKeys = isArray(itemKeys) ? itemKeys : Object.keys(itemKeys) | ||
localKeys = localKeys.concat(itemKeys) | ||
return self.findAll(relatedMapper, { | ||
where: { | ||
[relatedMapper.idAttribute]: { | ||
'in': unique(localKeys).filter(function (x) { return x }) | ||
} | ||
} | ||
}, __opts).then(function (relatedItems) { | ||
def.setLocalField(record, relatedItems) | ||
}) | ||
} else { | ||
let localKeys = [] | ||
records.forEach(function (item) { | ||
let itemKeys = item[def.localKeys] || [] | ||
itemKeys = isArray(itemKeys) ? itemKeys : Object.keys(itemKeys) | ||
localKeys = localKeys.concat(itemKeys) | ||
}) | ||
return self.findAll(relatedMapper, { | ||
where: { | ||
[relatedMapper.idAttribute]: { | ||
'in': unique(localKeys).filter(function (x) { return x }) | ||
} | ||
} | ||
}, __opts).then(function (relatedItems) { | ||
records.forEach(function (item) { | ||
let attached = [] | ||
let itemKeys = get(item, def.localKeys) || [] | ||
itemKeys = isArray(itemKeys) ? itemKeys : Object.keys(itemKeys) | ||
relatedItems.forEach(function (relatedItem) { | ||
if (itemKeys && itemKeys.indexOf(relatedItem[relatedMapper.idAttribute]) !== -1) { | ||
attached.push(relatedItem) | ||
} | ||
}) | ||
def.setLocalField(item, attached) | ||
}) | ||
return relatedItems | ||
}) | ||
} | ||
}, | ||
loadHasManyForeignKeys (mapper, def, records, __opts) { | ||
const self = this | ||
const relatedMapper = def.getRelation() | ||
const idAttribute = mapper.idAttribute | ||
let record | ||
if (isObject(records) && !isArray(records)) { | ||
record = records | ||
} | ||
if (record) { | ||
return self.findAll(def.getRelation(), { | ||
where: { | ||
[def.foreignKeys]: { | ||
'contains': self.makeHasManyForeignKeys(mapper, def, record) | ||
} | ||
} | ||
}, __opts).then(function (relatedItems) { | ||
def.setLocalField(record, relatedItems) | ||
}) | ||
} else { | ||
return self.findAll(relatedMapper, { | ||
where: { | ||
[def.foreignKeys]: { | ||
'isectNotEmpty': records.map(function (record) { | ||
return self.makeHasManyForeignKeys(mapper, def, record) | ||
}) | ||
} | ||
} | ||
}, __opts).then(function (relatedItems) { | ||
const foreignKeysField = def.foreignKeys | ||
records.forEach(function (record) { | ||
const _relatedItems = [] | ||
const id = get(record, idAttribute) | ||
relatedItems.forEach(function (relatedItem) { | ||
const foreignKeys = get(relatedItems, foreignKeysField) || [] | ||
if (foreignKeys.indexOf(id) !== -1) { | ||
_relatedItems.push(relatedItem) | ||
} | ||
}) | ||
def.setLocalField(record, _relatedItems) | ||
}) | ||
}) | ||
} | ||
}, | ||
/** | ||
@@ -755,3 +976,54 @@ * Load a hasOne relationship. | ||
find (mapper, id, opts) { | ||
throw new Error('Not supported!') | ||
const self = this | ||
let record, op | ||
opts || (opts = {}) | ||
opts.with || (opts.with = []) | ||
// beforeFind lifecycle hook | ||
op = opts.op = 'beforeFind' | ||
return resolve(self[op](mapper, id, opts)).then(function () { | ||
op = opts.op = 'find' | ||
self.dbg(op, mapper, id, opts) | ||
return resolve(self._find(mapper, id, opts)) | ||
}).then(function (results) { | ||
let [_record] = results | ||
if (!_record) { | ||
return | ||
} | ||
record = _record | ||
const tasks = [] | ||
forEachRelation(mapper, opts, function (def, __opts) { | ||
let task | ||
if (def.foreignKey && (def.type === 'hasOne' || def.type === 'hasMany')) { | ||
if (def.type === 'hasOne') { | ||
task = self.loadHasOne(mapper, def, record, __opts) | ||
} else { | ||
task = self.loadHasMany(mapper, def, record, __opts) | ||
} | ||
} else if (def.type === 'hasMany' && def.localKeys) { | ||
task = self.loadHasManyLocalKeys(mapper, def, record, __opts) | ||
} else if (def.type === 'hasMany' && def.foreignKeys) { | ||
task = self.loadHasManyForeignKeys(mapper, def, record, __opts) | ||
} else if (def.type === 'belongsTo') { | ||
task = self.loadBelongsTo(mapper, def, record, __opts) | ||
} | ||
if (task) { | ||
tasks.push(task) | ||
} | ||
}) | ||
return Promise.all(tasks) | ||
}).then(function () { | ||
let response = new Response(record, {}, 'find') | ||
response.found = record ? 1 : 0 | ||
response = self.respond(response, opts) | ||
// afterFind lifecycle hook | ||
op = opts.op = 'afterFind' | ||
return resolve(self[op](mapper, id, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response | ||
}) | ||
}) | ||
}, | ||
@@ -779,3 +1051,51 @@ | ||
findAll (mapper, query, opts) { | ||
throw new Error('Not supported!') | ||
const self = this | ||
opts || (opts = {}) | ||
opts.with || (opts.with = []) | ||
let records = [] | ||
let op | ||
// beforeFindAll lifecycle hook | ||
op = opts.op = 'beforeFindAll' | ||
return resolve(self[op](mapper, query, opts)).then(function () { | ||
op = opts.op = 'findAll' | ||
self.dbg(op, mapper, query, opts) | ||
return resolve(self._findAll(mapper, query, opts)) | ||
}).then(function (results) { | ||
let [_records] = results | ||
_records || (_records = []) | ||
records = _records | ||
const tasks = [] | ||
forEachRelation(mapper, opts, function (def, __opts) { | ||
let task | ||
if (def.foreignKey && (def.type === 'hasOne' || def.type === 'hasMany')) { | ||
if (def.type === 'hasMany') { | ||
task = self.loadHasMany(mapper, def, records, __opts) | ||
} else { | ||
task = self.loadHasOne(mapper, def, records, __opts) | ||
} | ||
} else if (def.type === 'hasMany' && def.localKeys) { | ||
task = self.loadHasManyLocalKeys(mapper, def, records, __opts) | ||
} else if (def.type === 'hasMany' && def.foreignKeys) { | ||
task = self.loadHasManyForeignKeys(mapper, def, records, __opts) | ||
} else if (def.type === 'belongsTo') { | ||
task = self.loadBelongsTo(mapper, def, records, __opts) | ||
} | ||
if (task) { | ||
tasks.push(task) | ||
} | ||
}) | ||
return Promise.all(tasks) | ||
}).then(function () { | ||
let response = new Response(records, {}, 'findAll') | ||
response.found = records.length | ||
response = self.respond(response, opts) | ||
// afterFindAll lifecycle hook | ||
op = opts.op = 'afterFindAll' | ||
return resolve(self[op](mapper, query, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response | ||
}) | ||
}) | ||
}, | ||
@@ -850,3 +1170,29 @@ | ||
update (mapper, id, props, opts) { | ||
throw new Error('Not supported!') | ||
const self = this | ||
props || (props = {}) | ||
opts || (opts = {}) | ||
let op | ||
// beforeUpdate lifecycle hook | ||
op = opts.op = 'beforeUpdate' | ||
return resolve(self[op](mapper, id, props, opts)).then(function (_props) { | ||
// Allow for re-assignment from lifecycle hook | ||
props = isUndefined(_props) ? props : _props | ||
op = opts.op = 'update' | ||
self.dbg(op, mapper, id, props, opts) | ||
return resolve(self._update(mapper, id, props, opts)) | ||
}).then(function (results) { | ||
let [data, result] = results | ||
result || (result = {}) | ||
let response = new Response(data, result, 'update') | ||
response.updated = data ? 1 : 0 | ||
response = self.respond(response, opts) | ||
// afterUpdate lifecycle hook | ||
op = opts.op = 'afterUpdate' | ||
return resolve(self[op](mapper, id, props, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response | ||
}) | ||
}) | ||
}, | ||
@@ -875,3 +1221,31 @@ | ||
updateAll (mapper, props, query, opts) { | ||
throw new Error('Not supported!') | ||
const self = this | ||
props || (props = {}) | ||
query || (query = {}) | ||
opts || (opts = {}) | ||
let op | ||
// beforeUpdateAll lifecycle hook | ||
op = opts.op = 'beforeUpdateAll' | ||
return resolve(self[op](mapper, props, query, opts)).then(function (_props) { | ||
// Allow for re-assignment from lifecycle hook | ||
props = isUndefined(_props) ? props : _props | ||
op = opts.op = 'updateAll' | ||
self.dbg(op, mapper, props, query, opts) | ||
return resolve(self._updateAll(mapper, props, query, opts)) | ||
}).then(function (results) { | ||
let [data, result] = results | ||
data || (data = []) | ||
result || (result = {}) | ||
let response = new Response(data, result, 'updateAll') | ||
response.updated = data.length | ||
response = self.respond(response, opts) | ||
// afterUpdateAll lifecycle hook | ||
op = opts.op = 'afterUpdateAll' | ||
return resolve(self[op](mapper, props, query, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response | ||
}) | ||
}) | ||
}, | ||
@@ -892,4 +1266,41 @@ | ||
updateMany (mapper, records, opts) { | ||
throw new Error('Not supported!') | ||
const self = this | ||
records || (records = []) | ||
opts || (opts = {}) | ||
let op | ||
const idAttribute = mapper.idAttribute | ||
records = records.filter(function (record) { | ||
return get(record, idAttribute) | ||
}) | ||
// beforeUpdateMany lifecycle hook | ||
op = opts.op = 'beforeUpdateMany' | ||
return resolve(self[op](mapper, records, opts)).then(function (_records) { | ||
// Allow for re-assignment from lifecycle hook | ||
records = isUndefined(_records) ? records : _records | ||
records = records.map(function (record) { | ||
return withoutRelations(mapper, record) | ||
}) | ||
op = opts.op = 'updateMany' | ||
self.dbg(op, mapper, records, opts) | ||
return resolve(self._updateMany(mapper, records, opts)) | ||
}).then(function (results) { | ||
let [data, result] = results | ||
data || (data = []) | ||
result || (result = {}) | ||
let response = new Response(data, result, 'updateMany') | ||
response.updated = data.length | ||
response = self.respond(response, opts) | ||
// afterUpdateMany lifecycle hook | ||
op = opts.op = 'afterUpdateMany' | ||
return resolve(self[op](mapper, records, opts, response)).then(function (_response) { | ||
// Allow for re-assignment from lifecycle hook | ||
return isUndefined(_response) ? response : _response | ||
}) | ||
}) | ||
} | ||
}) | ||
module.exports = Adapter |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
186126
15
2628
14