UNPKG

mobdb

Version:

MarsDB is a lightweight client-side MongoDB-like database, Promise based, written in ES6

191 lines (151 loc) 5.93 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.joinObj = undefined; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _checkTypes = require('check-types'); var _checkTypes2 = _interopRequireDefault(_checkTypes); var _forEach = require('fast.js/forEach'); var _forEach2 = _interopRequireDefault(_forEach); var _map2 = require('fast.js/map'); var _map3 = _interopRequireDefault(_map2); var _filter2 = require('fast.js/array/filter'); var _filter3 = _interopRequireDefault(_filter2); var _reduce2 = require('fast.js/array/reduce'); var _reduce3 = _interopRequireDefault(_reduce2); var _keys2 = require('fast.js/object/keys'); var _keys3 = _interopRequireDefault(_keys2); var _Collection = require('../Collection'); var _Collection2 = _interopRequireDefault(_Collection); var _invariant = require('invariant'); var _invariant2 = _interopRequireDefault(_invariant); var _joinAll = require('./joinAll'); var _DocumentModifier = require('../DocumentModifier'); var _DocumentMatcher = require('../DocumentMatcher'); var _Document = require('../Document'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } /** * By given list of documents make mapping of joined * model ids to root document and vise versa. * @param {Array} docs * @param {String} key * @return {Object} */ function _decomposeDocuments(docs, key) { var lookupFn = (0, _DocumentMatcher.makeLookupFunction)(key); var allIds = []; var docsWrapped = (0, _map3.default)(docs, function (d) { var val = lookupFn(d); var joinIds = (0, _filter3.default)((0, _reduce3.default)((0, _map3.default)(val, function (x) { return x.value; }), function (a, b) { if (_checkTypes2.default.array(b)) { return [].concat(_toConsumableArray(a), _toConsumableArray(b)); } else { return [].concat(_toConsumableArray(a), [b]); } }, []), function (x) { return (0, _Document.selectorIsId)(x); }); allIds = allIds.concat(joinIds); return { doc: d, lookupResult: val }; }); return { allIds: allIds, docsWrapped: docsWrapped }; } /** * By given value of some key in join object return * an options object. * @param {Object|Collection} joinValue * @return {Object} */ function _getJoinOptions(key, value) { if (value instanceof _Collection2.default) { return { model: value, joinPath: key }; } else if (_checkTypes2.default.object(value)) { return { model: value.model, joinPath: value.joinPath || key }; } else { throw new Error('Invalid join object value'); } } /** * By given result of joining objects restriving and root documents * decomposition set joining object on each root document * (if it is exists). * @param {String} joinPath * @param {Array} res * @param {Object} docsById * @param {Object} childToRootMap */ function _joinDocsWithResult(joinPath, res, docsWrapped) { var resIdMap = {}; var initKeyparts = joinPath.split('.'); (0, _forEach2.default)(res, function (v) { return resIdMap[v._id] = v; }); (0, _forEach2.default)(docsWrapped, function (wrap) { (0, _forEach2.default)(wrap.lookupResult, function (branch) { if (branch.value) { // `findModTarget` will modify `keyparts`. So, it should // be copied each time. var keyparts = initKeyparts.slice(); var target = (0, _DocumentModifier.findModTarget)(wrap.doc, keyparts, { noCreate: false, forbidArray: false, arrayIndices: branch.arrayIndices }); var field = keyparts[keyparts.length - 1]; if (_checkTypes2.default.array(branch.value)) { target[field] = (0, _map3.default)(branch.value, function (id) { return resIdMap[id]; }); } else { target[field] = resIdMap[branch.value] || null; } } }); }); } var joinObj = exports.joinObj = { method: function method(obj) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; (0, _invariant2.default)(_checkTypes2.default.object(obj), 'joinObj(...): argument must be an object'); this._addPipeline('joinObj', obj, options); return this; }, process: function process(docs, pipeObj, cursor) { if (!docs) { return Promise.resolve(docs); } else { var obj = pipeObj.value; var options = pipeObj.args[0] || {}; var isObj = !_checkTypes2.default.array(docs); docs = !isObj ? docs : [docs]; var joinerFn = function joinerFn(dcs) { return (0, _map3.default)((0, _keys3.default)(obj), function (k) { var _getJoinOptions2 = _getJoinOptions(k, obj[k]), model = _getJoinOptions2.model, joinPath = _getJoinOptions2.joinPath; var _decomposeDocuments2 = _decomposeDocuments(docs, k), allIds = _decomposeDocuments2.allIds, docsWrapped = _decomposeDocuments2.docsWrapped; var execFnName = options.observe ? 'observe' : 'then'; return model.find({ _id: { $in: allIds } })[execFnName](function (res) { _joinDocsWithResult(joinPath, res, docsWrapped); }); }); }; var newPipeObj = _extends({}, pipeObj, { value: joinerFn }); return _joinAll.joinAll.process(docs, newPipeObj, cursor).then(function (res) { return isObj ? res[0] : res; }); } } };