mingo
Version:
MongoDB query language for in-memory objects
188 lines (187 loc) • 6.2 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var cursor_exports = {};
__export(cursor_exports, {
Cursor: () => Cursor
});
module.exports = __toCommonJS(cursor_exports);
var import_core = require("./core");
var import_lazy = require("./lazy");
var import_limit = require("./operators/pipeline/limit");
var import_project = require("./operators/pipeline/project");
var import_skip = require("./operators/pipeline/skip");
var import_sort = require("./operators/pipeline/sort");
var import_util = require("./util");
const OPERATORS = { $sort: import_sort.$sort, $skip: import_skip.$skip, $limit: import_limit.$limit };
class Cursor {
#source;
#predicate;
#projection;
#options;
#operators = {};
#result = null;
#buffer = [];
/**
* Creates an instance of the Cursor class.
*
* @param source - The source of data to be iterated over.
* @param predicate - A function or condition to filter the data.
* @param projection - An object specifying the fields to include or exclude in the result.
* @param options - Optional settings to customize the behavior of the cursor.
*/
constructor(source, predicate, projection, options) {
this.#source = source;
this.#predicate = predicate;
this.#projection = projection;
this.#options = options;
}
/** Returns the iterator from running the query */
fetch() {
if (this.#result) return this.#result;
this.#result = (0, import_lazy.Lazy)(this.#source).filter(this.#predicate);
const mode = this.#options.processingMode;
if (mode & import_core.ProcessingMode.CLONE_INPUT) this.#result.map(import_util.cloneDeep);
for (const op of ["$sort", "$skip", "$limit"]) {
if ((0, import_util.has)(this.#operators, op)) {
this.#result = OPERATORS[op](
this.#result,
this.#operators[op],
this.#options
);
}
}
if (Object.keys(this.#projection).length) {
this.#result = (0, import_project.$project)(this.#result, this.#projection, this.#options);
}
if (mode & import_core.ProcessingMode.CLONE_OUTPUT) this.#result.map(import_util.cloneDeep);
return this.#result;
}
/** Returns an iterator with the buffered data included */
fetchAll() {
const buffered = (0, import_lazy.Lazy)([...this.#buffer]);
this.#buffer.length = 0;
return (0, import_lazy.concat)(buffered, this.fetch());
}
/**
* Return remaining objects in the cursor as an array. This method exhausts the cursor
* @returns {Array}
*/
all() {
return this.fetchAll().value();
}
/**
* Returns the number of objects return in the cursor. This method exhausts the cursor
* @returns {Number}
*/
count() {
return this.all().length;
}
/**
* Returns a cursor that begins returning results only after passing or skipping a number of documents.
* @param {Number} n the number of results to skip.
* @return {Cursor} Returns the cursor, so you can chain this call.
*/
skip(n) {
this.#operators["$skip"] = n;
return this;
}
/**
* Limits the number of items returned by the cursor.
*
* @param n - The maximum number of items to return.
* @returns The current cursor instance for chaining.
*/
limit(n) {
this.#operators["$limit"] = n;
return this;
}
/**
* Returns results ordered according to a sort specification.
* @param {AnyObject} modifier an object of key and values specifying the sort order. 1 for ascending and -1 for descending
* @return {Cursor} Returns the cursor, so you can chain this call.
*/
sort(modifier) {
this.#operators["$sort"] = modifier;
return this;
}
/**
* Sets the collation options for the cursor.
* Collation allows users to specify language-specific rules for string comparison,
* such as case sensitivity and accent marks.
*
* @param spec - The collation specification to apply.
* @returns The current cursor instance for chaining.
*/
collation(spec) {
this.#options = { ...this.#options, collation: spec };
return this;
}
/**
* Retrieves the next item in the cursor.
*/
next() {
if (this.#buffer.length > 0) {
return this.#buffer.pop();
}
const o = this.fetch().next();
if (o.done) return;
return o.value;
}
/**
* Determines if there are more elements available in the cursor.
*
* @returns {boolean} `true` if there are more elements to iterate over, otherwise `false`.
*/
hasNext() {
if (this.#buffer.length > 0) return true;
const o = this.fetch().next();
if (o.done) return false;
this.#buffer.push(o.value);
return true;
}
/**
* Transforms each element in the cursor using the provided callback function.
*
* @param f - A callback function.
* @returns An array of transformed elements.
*/
map(f) {
return this.all().map(f);
}
/**
* Applies the provided callback function to each element in the cursor.
*
* @param f - A callback function that is invoked for each element in the cursor.
*/
forEach(f) {
this.all().forEach(f);
}
/**
* Returns an iterator for the cursor, allowing it to be used in `for...of` loops.
* The iterator fetches all the results from the cursor.
*
* @returns {Iterator} An iterator over the fetched results.
*/
[Symbol.iterator]() {
return this.fetchAll();
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Cursor
});