UNPKG

@scalars/grapi-mongodb

Version:

The mongodb package of Grapi

485 lines (484 loc) 30 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; exports.__esModule = true; exports.MongodbData = void 0; var grapi_1 = require("@scalars/grapi"); var lodash_1 = require("./lodash"); var MongodbData = (function () { function MongodbData(db, collectionName) { this.transformMutation = function (mutation, set) { if (set === void 0) { set = false; } var payload = set ? { $set: mutation.getData() } : mutation.getData(); mutation.getArrayOperations().forEach(function (operation) { var _a, _b; var fieldName = operation.fieldName, operator = operation.operator, value = operation.value; if (operator == grapi_1.ArrayOperator.set) { if (set) { payload.$set[fieldName] = value; } else { payload[fieldName] = value; } } else if (operator == grapi_1.ArrayOperator.add) { payload.$addToSet = __assign(__assign({}, payload.$addToSet), (_a = {}, _a[fieldName] = { $each: value }, _a)); } else if (operator == grapi_1.ArrayOperator.remove) { payload.$pull = __assign(__assign({}, payload.$pull), (_b = {}, _b[fieldName] = { $in: value }, _b)); } }); return payload; }; this.db = db; this.collectionName = collectionName; } MongodbData.prototype.findInCollection = function (filterQuery, orderBy) { if (orderBy === void 0) { orderBy = {}; } return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, this.db.collection(this.collectionName) .find(filterQuery) .sort(orderBy) .project({ _id: 0 }) .toArray()]; case 1: return [2, _a.sent()]; } }); }); }; MongodbData.prototype.findRecursive = function (where, orderBy, data) { if (data === void 0) { data = []; } return __awaiter(this, void 0, void 0, function () { var iteration; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: iteration = 0; return [4, grapi_1.iterateWhereFilter(where, function (whereFilter, operator) { return __awaiter(_this, void 0, void 0, function () { var _a, baseFilters_1, relationFilters_3, filters, filterQuery, baseFiltersOrAnd_1, whereFiltersOrAnd, dataCollection, _i, relationFilters_1, itemWhere, _b, _c, _d, relationFilters_2, itemWhere; return __generator(this, function (_e) { switch (_e.label) { case 0: if (!(operator === grapi_1.WhereOperator.relation)) return [3, 5]; if (!(lodash_1.isEmpty(data) && iteration === 0)) return [3, 2]; return [4, this.findInCollection({}, orderBy)]; case 1: _a = _e.sent(); return [3, 3]; case 2: _a = data; _e.label = 3; case 3: data = _a; return [4, this.executeRelationFilters(whereFilter, data)]; case 4: data = _e.sent(); return [3, 17]; case 5: baseFilters_1 = []; relationFilters_3 = []; if (operator === grapi_1.Operator.and || operator === grapi_1.Operator.or) { lodash_1.forEach(whereFilter, function (item) { if (lodash_1.findKey(item, 'relation')) { relationFilters_3.push(item); } else { baseFilters_1.push(item); } }); } if (!(lodash_1.isEmpty(baseFilters_1) === false || operator === grapi_1.WhereOperator.base || lodash_1.isEmpty(whereFilter))) return [3, 7]; filters = lodash_1.isEmpty(baseFilters_1) ? whereFilter : baseFilters_1; filterQuery = this.whereToFilterQuery(filters, operator); return [4, this.findInCollection(filterQuery, orderBy)]; case 6: data = _e.sent(); iteration = iteration + 1; _e.label = 7; case 7: if (!(lodash_1.isEmpty(relationFilters_3) === false)) return [3, 17]; baseFiltersOrAnd_1 = []; lodash_1.forEach(relationFilters_3, function (item) { lodash_1.forEach(item, function (value, key) { var _a; if (!lodash_1.get(value, 'relation')) { delete item[key]; baseFiltersOrAnd_1.push((_a = {}, _a[key] = value, _a)); } }); }); baseFiltersOrAnd_1 = lodash_1.uniqWith(baseFiltersOrAnd_1, lodash_1.isEqual); whereFiltersOrAnd = this.whereToFilterQuery(baseFiltersOrAnd_1, operator); return [4, this.findInCollection(whereFiltersOrAnd)]; case 8: dataCollection = _e.sent(); if (!(operator === grapi_1.Operator.or)) return [3, 13]; _i = 0, relationFilters_1 = relationFilters_3; _e.label = 9; case 9: if (!(_i < relationFilters_1.length)) return [3, 12]; itemWhere = relationFilters_1[_i]; _b = lodash_1.concat; _c = [data]; return [4, this.executeRelationFilters(itemWhere, dataCollection)]; case 10: data = _b.apply(void 0, _c.concat([_e.sent()])); _e.label = 11; case 11: _i++; return [3, 9]; case 12: data = lodash_1.uniqWith(lodash_1.compact(data), lodash_1.isEqual); return [3, 17]; case 13: data = lodash_1.isEmpty(data) && iteration === 0 ? dataCollection : data; _d = 0, relationFilters_2 = relationFilters_3; _e.label = 14; case 14: if (!(_d < relationFilters_2.length)) return [3, 17]; itemWhere = relationFilters_2[_d]; return [4, this.executeRelationFilters(itemWhere, data)]; case 15: data = _e.sent(); _e.label = 16; case 16: _d++; return [3, 14]; case 17: return [2]; } }); }); })]; case 1: _a.sent(); return [2, data]; } }); }); }; MongodbData.prototype.executeRelationFilters = function (where, data, filtered) { if (filtered === void 0) { filtered = []; } return __awaiter(this, void 0, void 0, function () { var _loop_1, _i, data_1, item, state_1; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: _loop_1 = function (item) { var filter; return __generator(this, function (_b) { switch (_b.label) { case 0: return [4, grapi_1.iterateRelationsWhere(where, function (relationWhere) { return __awaiter(_this, void 0, void 0, function () { var relation, relations, filters, targetKey, _a, list, ship, source, target, filter, foreignKey, relationData, isManyToMany, foreignKeyValue, filterWhere, totalRelationData, recursive, _b, itemId_1, key, relationData, filterId, status_1, filters_1, recursiveFilter; var _c; return __generator(this, function (_d) { switch (_d.label) { case 0: relation = relationWhere.relation; relations = {}; lodash_1.forEach(relationWhere.filters || {}, function (value, key) { if (value.relation) { relations[key] = value; } }); filters = relationWhere.filters, targetKey = relationWhere.targetKey; _a = relation || {}, list = _a.list, ship = _a.ship, source = _a.source, target = _a.target, filter = _a.filter, foreignKey = _a.foreignKey; if (!list) return [3, 14]; relationData = void 0; isManyToMany = ship === grapi_1.RelationShip.ManyToMany; foreignKeyValue = foreignKey || lodash_1.toLower(source) + "Id"; if (!isManyToMany) return [3, 2]; return [4, this.filterManyFromManyRelation(lodash_1.toLower(source), lodash_1.toLower(target), item.id, targetKey, grapi_1.iterateBaseFilter(filters))]; case 1: relationData = _d.sent(); relationData = lodash_1.compact(relationData); return [3, 4]; case 2: return [4, this.findManyRelation(foreignKeyValue, item.id, targetKey, filters)]; case 3: relationData = _d.sent(); _d.label = 4; case 4: filterWhere = void 0; if (!(filter === "some")) return [3, 5]; filterWhere = !lodash_1.isEmpty(relationData); return [3, 11]; case 5: if (!(filter === "none")) return [3, 6]; filterWhere = lodash_1.isEmpty(relationData); return [3, 11]; case 6: totalRelationData = []; if (!isManyToMany) return [3, 8]; return [4, this.filterManyFromManyRelation(lodash_1.toLower(source), lodash_1.toLower(target), item.id, targetKey, {})]; case 7: totalRelationData = _d.sent(); return [3, 10]; case 8: return [4, this.findManyRelation(foreignKeyValue, item.id, targetKey, filters)]; case 9: totalRelationData = _d.sent(); _d.label = 10; case 10: filterWhere = totalRelationData.length === relationData.length; _d.label = 11; case 11: if (!(filterWhere && lodash_1.isEmpty(relations) === false)) return [3, 13]; return [4, this.executeRelationFilters(relations, relationData)]; case 12: recursive = _d.sent(); return [2, lodash_1.isEmpty(recursive) === false]; case 13: return [2, filterWhere]; case 14: _b = grapi_1.getRelationItemKeyId(item, relation), itemId_1 = _b.itemId, key = _b.key; relationData = void 0; if (!itemId_1) return [3, 16]; filterId = lodash_1.get(relationWhere, 'filters.id'); if (filterId) { status_1 = false; grapi_1.iterateWhere({ id: filterId }, function (field, op, value) { switch (op) { case grapi_1.Operator.eq: status_1 = itemId_1 === value; break; case grapi_1.Operator.neq: status_1 = itemId_1 !== value; break; } }); return [2, status_1]; } filters_1 = lodash_1.assign((_c = {}, _c[key] = { eq: itemId_1 }, _c), relationWhere.filters); return [4, this.findOneRelation(relationWhere.targetKey, grapi_1.iterateBaseFilter(filters_1))]; case 15: relationData = _d.sent(); _d.label = 16; case 16: if (!(relationData && lodash_1.isEmpty(relations) === false)) return [3, 18]; return [4, this.executeRelationFilters(relations, [relationData])]; case 17: recursiveFilter = _d.sent(); return [2, lodash_1.isEmpty(recursiveFilter) === false]; case 18: return [2, relationData !== null]; } }); }); })]; case 1: filter = _b.sent(); if (filter === undefined) { return [2, { value: data }]; } if (filter) { filtered.push(item); } return [2]; } }); }; _i = 0, data_1 = data; _a.label = 1; case 1: if (!(_i < data_1.length)) return [3, 4]; item = data_1[_i]; return [5, _loop_1(item)]; case 2: state_1 = _a.sent(); if (typeof state_1 === "object") return [2, state_1.value]; _a.label = 3; case 3: _i++; return [3, 1]; case 4: return [2, filtered]; } }); }); }; MongodbData.prototype.findOneRelation = function (colectionName, where) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, this.db.collection(colectionName).findOne(this.whereToFilterQuery(where))]; case 1: return [2, _a.sent()]; } }); }); }; MongodbData.prototype.findManyRelation = function (foreignKey, foreignId, collectionName, where) { return __awaiter(this, void 0, void 0, function () { var filterQuery; var _a, _b; return __generator(this, function (_c) { switch (_c.label) { case 0: filterQuery = this.whereToFilterQuery(__assign(__assign({}, where), (_a = {}, _a[foreignKey] = (_b = {}, _b[grapi_1.Operator.eq] = foreignId, _b), _a))); return [4, this.db.collection(collectionName) .find(filterQuery) .project({ _id: 0 }) .toArray()]; case 1: return [2, _c.sent()]; } }); }); }; MongodbData.prototype.filterManyFromManyRelation = function (sourceSideName, targetSideName, sourceSideId, collection, where) { return __awaiter(this, void 0, void 0, function () { var relationTableName, relationData, relationIds; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: relationTableName = "_" + sourceSideName + "_" + targetSideName; return [4, this.db.collection(relationTableName).findOne({ sourceSideId: sourceSideId })]; case 1: relationData = _a.sent(); relationIds = lodash_1.get(relationData, "targetSideIds", []); return [4, Promise.all(relationIds.map(function (id) { var currentWhere = __assign({}, where); if (!lodash_1.has(currentWhere, "id.eq")) { currentWhere.id = { eq: id }; } else if (!lodash_1.includes(relationIds, lodash_1.get(currentWhere, "id.eq"))) { return null; } return _this.findOneRelation(collection, currentWhere); }))]; case 2: return [2, _a.sent()]; } }); }); }; MongodbData.prototype.whereToFilterQuery = function (where, operator) { var _this = this; if (operator === void 0) { operator = undefined; } var filterQuery = {}; var whereCallback = function (field, operator, value) { switch (operator) { case grapi_1.Operator.eq: filterQuery[field] = value; break; case grapi_1.Operator.contains: filterQuery[field] = new RegExp(".*" + value + ".*", "i"); break; case grapi_1.Operator.notcontains: filterQuery[field] = new RegExp("^((?!" + value + ").)*$", "i"); break; case grapi_1.Operator.neq: filterQuery[field] = { $ne: value }; break; case grapi_1.Operator.gt: filterQuery[field] = { $gt: value }; break; case grapi_1.Operator.gte: filterQuery[field] = { $gte: value }; break; case grapi_1.Operator.lt: filterQuery[field] = { $lt: value }; break; case grapi_1.Operator.lte: filterQuery[field] = { $lte: value }; break; case grapi_1.Operator["in"]: filterQuery[field] = { $in: value }; break; case grapi_1.Operator.all: filterQuery[field] = { $all: value }; break; case grapi_1.Operator.notIn: filterQuery[field] = { $nin: value }; break; case grapi_1.Operator.between: filterQuery[field] = { $gte: value.from, $lte: value.to }; break; case grapi_1.Operator.object: lodash_1.assign(filterQuery, value); break; } }; if (lodash_1.isEmpty(where) === false && (operator === grapi_1.Operator.or || operator === grapi_1.Operator.and)) { var filtersQuery_1 = []; lodash_1.forEach(where, function (whereItem) { if (lodash_1.isEmpty(whereItem) === false) { var _a = _this.findRecursiveOperator(whereItem), operator_1 = _a.operator, filters = _a.filters; if (operator_1) { filtersQuery_1.push(_this.whereToFilterQuery(filters, operator_1)); } else { filtersQuery_1.push(_this.whereToFilterQuery(whereItem)); } } }); filterQuery["$" + lodash_1.toLower(operator)] = filtersQuery_1; } else { grapi_1.iterateWhere(where, whereCallback); } return filterQuery; }; MongodbData.prototype.findRecursiveOperator = function (where) { if (lodash_1.get(where, grapi_1.Operator.or)) { return { operator: grapi_1.Operator.or, filters: lodash_1.get(where, grapi_1.Operator.or) }; } else if (lodash_1.get(where, grapi_1.Operator.and)) { return { operator: grapi_1.Operator.and, filters: lodash_1.get(where, grapi_1.Operator.and) }; } return {}; }; MongodbData.prototype.handleMongoDbError = function (error) { if (error.code === 11000) { var keyValues = lodash_1.values(error.keyValue).join(' '); throw new Error("Constraint unique value \"" + keyValues + "\" duplicate on " + lodash_1.capitalize(this.collectionName) + " model"); } else if (error.code === 121) { throw new Error("Document failed validation on " + lodash_1.capitalize(this.collectionName) + " model, review types or required values in data"); } throw new Error("" + error.message); }; return MongodbData; }()); exports.MongodbData = MongodbData;