UNPKG

helene

Version:
147 lines 5.08 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Cursor = void 0; const isEmpty_1 = __importDefault(require("lodash/isEmpty")); const omit_1 = __importDefault(require("lodash/omit")); const model_1 = require("./model"); class Cursor { db; query; _limit; _skip; _sort; _projection; constructor(db, query) { this.db = db; this.query = query || {}; } limit(limit) { this._limit = limit; return this; } skip(skip) { this._skip = skip; return this; } sort(sortQuery) { if (sortQuery) { this._sort = sortQuery; } return this; } projection(projection) { this._projection = projection; return this; } project(candidates) { const res = []; if ((0, isEmpty_1.default)(this._projection)) { return candidates; } const keepId = this._projection._id === 1 || this._projection._id === undefined; this._projection = (0, omit_1.default)(this._projection, '_id'); const keys = Object.keys(this._projection); let action = keys.length === 0 ? 1 : undefined; for (const k of keys) { if (action !== undefined && this._projection[k] !== action) { throw new Error("Can't both keep and omit fields except for _id"); } action = this._projection[k]; } if (action === 1) { for (const candidate of candidates) { const modifier = { $set: {} }; for (const k of keys) { const value = (0, model_1.getDotValue)(candidate, k); if (value !== undefined) { modifier.$set[k] = value; } } res.push((0, model_1.modify)({ ...(keepId && { _id: candidate._id }), }, modifier)); } } else if (action === 0) { for (const candidate of candidates) { const modifier = { $unset: {} }; for (const k of keys) { modifier.$unset[k] = true; } res.push((0, model_1.modify)(keepId ? candidate : (0, omit_1.default)(candidate, '_id'), modifier)); } } return res; } async exec() { await this.db.ensureReady(); let res = [], added = 0, skipped = 0, i, keys, key; const self = this; const candidates = await this.db.getCandidates(this.query); for (i = 0; i < candidates.length; i += 1) { if ((0, model_1.match)(candidates[i], self.query)) { // If a sort is defined, wait for the results to be sorted before applying limit and skip if (!self._sort) { if (self._skip && self._skip > skipped) { skipped += 1; } else { res.push(candidates[i]); added += 1; if (self._limit && self._limit <= added) { break; } } } else { res.push(candidates[i]); } } } // Apply all sorts if (self._sort) { keys = Object.keys(self._sort); // Sorting const criteria = []; for (i = 0; i < keys.length; i++) { key = keys[i]; criteria.push({ key: key, direction: self._sort[key] }); } res.sort(function (a, b) { let criterion, compare, i; for (i = 0; i < criteria.length; i++) { criterion = criteria[i]; compare = criterion.direction * (0, model_1.compareThings)((0, model_1.getDotValue)(a, criterion.key), (0, model_1.getDotValue)(b, criterion.key), self.db.compareStrings); if (compare !== 0) { return compare; } } return 0; }); // Applying limit and skip const limit = self._limit || res.length, skip = self._skip || 0; res = res.slice(skip, skip + limit); } res = self.project(res); res = res.map(doc => (0, model_1.deepCopy)(doc)); return res; } async map(fn) { const res = await this.exec(); const ret = []; for (const item of res) { ret.push(await fn(item)); } return ret; } then(onfulfilled, onrejected) { return this.exec().then(onfulfilled, onrejected); } } exports.Cursor = Cursor; //# sourceMappingURL=cursor.js.map