UNPKG

@e22m4u/js-repository

Version:

Реализация репозитория для работы с базами данных в Node.js

1,526 lines (1,498 loc) 242 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __glob = (map) => (path) => { var fn = map[path]; if (fn) return fn(); throw new Error("Module not found in bundle: " + path); }; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; 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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); // src/utils/is-ctor.js function isCtor(value) { if (!value) return false; return typeof value === "function" && "prototype" in value; } var init_is_ctor = __esm({ "src/utils/is-ctor.js"() { "use strict"; __name(isCtor, "isCtor"); } }); // src/utils/is-promise.js function isPromise(value) { if (!value) return false; if (typeof value !== "object") return false; return typeof value.then === "function"; } var init_is_promise = __esm({ "src/utils/is-promise.js"() { "use strict"; __name(isPromise, "isPromise"); } }); // src/utils/capitalize.js function capitalize(string) { if (!string || typeof string !== "string") return string; return string.charAt(0).toUpperCase() + string.slice(1); } var init_capitalize = __esm({ "src/utils/capitalize.js"() { "use strict"; __name(capitalize, "capitalize"); } }); // src/utils/clone-deep.js function cloneDeep(value) { if (!value) return value; const types = [Number, String, Boolean]; let result; types.forEach((type) => { if (value instanceof type) result = type(value); }); if (result === void 0) { if (Array.isArray(value)) { result = []; value.forEach((child, index) => { result[index] = cloneDeep(child); }); } else if (typeof value === "object") { if ("nodeType" in value && value.nodeType && "cloneNode" in value && typeof value.cloneNode === "function") { result = value.cloneNode(true); } else if (!("prototype" in value) || !value.prototype) { if (value instanceof Date) { result = new Date(value); } else if (value.constructor && value.constructor.name === "Object") { result = {}; for (const key in value) { result[key] = cloneDeep(value[key]); } } else { result = value; } } else { result = value; } } else { result = value; } } return result; } var init_clone_deep = __esm({ "src/utils/clone-deep.js"() { "use strict"; __name(cloneDeep, "cloneDeep"); } }); // src/utils/singularize.js function singularize(noun) { if (!noun || typeof noun !== "string") return noun; const endings = { ves: "fe", ies: "y", i: "us", zes: "ze", ses: "s", es: "e", s: "" }; return noun.replace( new RegExp(`(${Object.keys(endings).join("|")})$`), (r) => endings[r] ); } var init_singularize = __esm({ "src/utils/singularize.js"() { "use strict"; __name(singularize, "singularize"); } }); // src/utils/is-deep-equal.js function isDeepEqual(firstValue, secondValue) { const cached = /* @__PURE__ */ new WeakMap(); const compare = /* @__PURE__ */ __name((a, b) => { if (a === null || b === null) return a === b; if (typeof a !== "object" || typeof b !== "object") return a === b; const dataTypeA = Array.isArray(a) ? "array" : "object"; const dataTypeB = Array.isArray(b) ? "array" : "object"; if (dataTypeA !== dataTypeB) return false; const keysA = Object.keys(a); const keysB = Object.keys(b); if (keysA.length !== keysB.length) return false; const symbolsA = Object.getOwnPropertySymbols(a); const symbolsB = Object.getOwnPropertySymbols(b); if (symbolsA.length !== symbolsB.length) return false; let setForA = cached.get(a); if (setForA == null) { setForA = /* @__PURE__ */ new Set(); cached.set(a, setForA); } else if (setForA.has(b)) { return true; } setForA.add(b); let setForB = cached.get(b); if (setForB == null) { setForB = /* @__PURE__ */ new Set(); cached.set(b, setForB); } else if (setForB.has(a)) { return true; } setForB.add(a); const propertyNamesA = [...keysA, ...symbolsA]; for (const propertyNameA of propertyNamesA) { if (!Object.prototype.hasOwnProperty.call(b, propertyNameA)) return false; const propertyValueA = a[propertyNameA]; const propertyValueB = b[propertyNameA]; if (!compare(propertyValueA, propertyValueB)) return false; } return true; }, "compare"); return compare(firstValue, secondValue); } var init_is_deep_equal = __esm({ "src/utils/is-deep-equal.js"() { "use strict"; __name(isDeepEqual, "isDeepEqual"); } }); // src/utils/get-ctor-name.js function getCtorName(value) { if (value === null) return "Null"; if (value === void 0) return "Undefined"; return value.constructor && value.constructor.name || void 0; } var init_get_ctor_name = __esm({ "src/utils/get-ctor-name.js"() { "use strict"; __name(getCtorName, "getCtorName"); } }); // src/utils/is-pure-object.js function isPureObject(value) { return Boolean( typeof value === "object" && value && !Array.isArray(value) && (!value.constructor || value.constructor && value.constructor.name === "Object") ); } var init_is_pure_object = __esm({ "src/utils/is-pure-object.js"() { "use strict"; __name(isPureObject, "isPureObject"); } }); // src/utils/string-to-regexp.js function stringToRegexp(pattern, flags = void 0) { if (pattern instanceof RegExp) { return new RegExp(pattern, flags); } let regex = ""; for (let i = 0, n = pattern.length; i < n; i++) { const char = pattern.charAt(i); if (char === "%") { regex += ".*"; } else { regex += char; } } return new RegExp(regex, flags); } var init_string_to_regexp = __esm({ "src/utils/string-to-regexp.js"() { "use strict"; __name(stringToRegexp, "stringToRegexp"); } }); // src/utils/get-value-by-path.js function getValueByPath(obj, path, orElse = void 0) { if (!obj || typeof obj !== "object") return orElse; if (!path || typeof path !== "string") return orElse; const keys = path.split("."); let value = obj; for (const key of keys) { if (typeof value === "object" && value !== null && key in value) { value = value[key]; } else { value = orElse; break; } } return value; } var init_get_value_by_path = __esm({ "src/utils/get-value-by-path.js"() { "use strict"; __name(getValueByPath, "getValueByPath"); } }); // src/utils/transform-promise.js function transformPromise(valueOrPromise, transformer) { return isPromise(valueOrPromise) ? valueOrPromise.then(transformer) : transformer(valueOrPromise); } var init_transform_promise = __esm({ "src/utils/transform-promise.js"() { "use strict"; init_is_promise(); __name(transformPromise, "transformPromise"); } }); // src/errors/not-implemented-error.js var import_js_format, _NotImplementedError, NotImplementedError; var init_not_implemented_error = __esm({ "src/errors/not-implemented-error.js"() { "use strict"; import_js_format = require("@e22m4u/js-format"); _NotImplementedError = class _NotImplementedError extends import_js_format.Errorf { }; __name(_NotImplementedError, "NotImplementedError"); NotImplementedError = _NotImplementedError; } }); // src/errors/invalid-argument-error.js var import_js_format2, _InvalidArgumentError, InvalidArgumentError; var init_invalid_argument_error = __esm({ "src/errors/invalid-argument-error.js"() { "use strict"; import_js_format2 = require("@e22m4u/js-format"); _InvalidArgumentError = class _InvalidArgumentError extends import_js_format2.Errorf { }; __name(_InvalidArgumentError, "InvalidArgumentError"); InvalidArgumentError = _InvalidArgumentError; } }); // src/errors/invalid-operator-value-error.js var import_js_format3, _InvalidOperatorValueError, InvalidOperatorValueError; var init_invalid_operator_value_error = __esm({ "src/errors/invalid-operator-value-error.js"() { "use strict"; import_js_format3 = require("@e22m4u/js-format"); _InvalidOperatorValueError = class _InvalidOperatorValueError extends Error { /** * Constructor. * * @param {string} operator * @param {string} expected * @param {*} value */ constructor(operator, expected, value) { super( (0, import_js_format3.format)( "Condition of {%s: ...} should have %s, but %v was given.", operator, expected, value ) ); } }; __name(_InvalidOperatorValueError, "InvalidOperatorValueError"); InvalidOperatorValueError = _InvalidOperatorValueError; } }); // src/errors/index.js var init_errors = __esm({ "src/errors/index.js"() { "use strict"; init_not_implemented_error(); init_invalid_argument_error(); init_invalid_operator_value_error(); } }); // src/utils/select-object-keys.js function selectObjectKeys(obj, keys) { if (!obj || typeof obj !== "object" || Array.isArray(obj)) throw new InvalidArgumentError( "The first argument of selectObjectKeys should be an Object, but %v was given.", obj ); if (!Array.isArray(keys)) throw new InvalidArgumentError( "The second argument of selectObjectKeys should be an Array of String, but %v was given.", keys ); keys.forEach((key) => { if (typeof key !== "string") throw new InvalidArgumentError( "The second argument of selectObjectKeys should be an Array of String, but %v was given.", key ); }); const result = {}; const allKeys = Object.keys(obj); allKeys.forEach((key) => { if (keys.includes(key)) result[key] = obj[key]; }); return result; } var init_select_object_keys = __esm({ "src/utils/select-object-keys.js"() { "use strict"; init_errors(); __name(selectObjectKeys, "selectObjectKeys"); } }); // src/utils/exclude-object-keys.js function excludeObjectKeys(obj, keys) { if (typeof obj !== "object" || !obj || Array.isArray(obj)) throw new InvalidArgumentError( "Cannot exclude keys from a non-Object value, %v was given.", obj ); const result = { ...obj }; keys = Array.isArray(keys) ? keys : [keys]; keys.forEach((key) => delete result[key]); return result; } var init_exclude_object_keys = __esm({ "src/utils/exclude-object-keys.js"() { "use strict"; init_errors(); __name(excludeObjectKeys, "excludeObjectKeys"); } }); // src/utils/model-name-to-model-key.js function modelNameToModelKey(modelName) { if (!modelName || typeof modelName !== "string" || /\s/.test(modelName)) throw new InvalidArgumentError( "The model name should be a non-empty String without spaces, but %v was given.", modelName ); if (modelName.toLowerCase() !== "model") modelName = modelName.replace(/[-_]?Model$/, "").replace(/[-_](MODEL|model)$/, ""); return modelName.toLowerCase().replace(/[-_]/g, ""); } var init_model_name_to_model_key = __esm({ "src/utils/model-name-to-model-key.js"() { "use strict"; init_errors(); __name(modelNameToModelKey, "modelNameToModelKey"); } }); // src/utils/get-decorator-target-type.js function getDecoratorTargetType(target, propertyKey, descriptorOrIndex) { const isCtor2 = typeof target === "function"; const isParameter = typeof descriptorOrIndex === "number"; const isProperty = propertyKey != null && descriptorOrIndex == null; const isMethod = propertyKey != null && descriptorOrIndex != null; const D = DecoratorTargetType; if (isCtor2) { if (isParameter) return propertyKey ? D.STATIC_METHOD_PARAMETER : D.CONSTRUCTOR_PARAMETER; if (isProperty) return D.STATIC_PROPERTY; if (isMethod) return D.STATIC_METHOD; return D.CONSTRUCTOR; } else { if (isParameter) return D.INSTANCE_METHOD_PARAMETER; if (isProperty) return D.INSTANCE_PROPERTY; if (isMethod) return D.INSTANCE_METHOD; return D.INSTANCE; } } var DecoratorTargetType; var init_get_decorator_target_type = __esm({ "src/utils/get-decorator-target-type.js"() { "use strict"; DecoratorTargetType = { CONSTRUCTOR: "constructor", INSTANCE: "instance", STATIC_METHOD: "staticMethod", INSTANCE_METHOD: "instanceMethod", STATIC_PROPERTY: "staticProperty", INSTANCE_PROPERTY: "instanceProperty", CONSTRUCTOR_PARAMETER: "constructorParameter", STATIC_METHOD_PARAMETER: "staticMethodParameter", INSTANCE_METHOD_PARAMETER: "instanceMethodParameter" }; __name(getDecoratorTargetType, "getDecoratorTargetType"); } }); // src/utils/index.js var init_utils = __esm({ "src/utils/index.js"() { "use strict"; init_is_ctor(); init_is_promise(); init_capitalize(); init_clone_deep(); init_singularize(); init_is_deep_equal(); init_get_ctor_name(); init_is_pure_object(); init_string_to_regexp(); init_get_value_by_path(); init_transform_promise(); init_select_object_keys(); init_exclude_object_keys(); init_model_name_to_model_key(); init_get_decorator_target_type(); } }); // src/filter/slice-clause-tool.js var import_js_service, _SliceClauseTool, SliceClauseTool; var init_slice_clause_tool = __esm({ "src/filter/slice-clause-tool.js"() { "use strict"; import_js_service = require("@e22m4u/js-service"); init_errors(); _SliceClauseTool = class _SliceClauseTool extends import_js_service.Service { /** * Slice. * * @param {object[]} entities * @param {number|undefined} skip * @param {number|undefined} limit * @returns {object[]} */ slice(entities, skip = void 0, limit = void 0) { if (!Array.isArray(entities)) throw new InvalidArgumentError( "The first argument of SliceClauseTool.slice should be an Array, but %v was given.", entities ); if (skip != null && typeof skip !== "number") throw new InvalidArgumentError( 'The provided option "skip" should be a Number, but %v was given.', skip ); if (limit != null && typeof limit !== "number") throw new InvalidArgumentError( 'The provided option "limit" should be a Number, but %v was given.', limit ); skip = skip || 0; limit = limit || entities.length; return entities.slice(skip, skip + limit); } /** * Validate skip clause. * * @param {number|undefined} skip */ static validateSkipClause(skip) { if (skip == null) return; if (typeof skip !== "number") throw new InvalidArgumentError( 'The provided option "skip" should be a Number, but %v was given.', skip ); } /** * Validate limit clause. * * @param {number|undefined} limit */ static validateLimitClause(limit) { if (limit == null) return; if (typeof limit !== "number") throw new InvalidArgumentError( 'The provided option "limit" should be a Number, but %v was given.', limit ); } }; __name(_SliceClauseTool, "SliceClauseTool"); SliceClauseTool = _SliceClauseTool; } }); // src/filter/order-clause-tool.js function compareFn(a, b) { let undefinedA, undefinedB; for (let i = 0, l = this.length; i < l; i++) { const aVal = getValueByPath(a, this[i].key); const bVal = getValueByPath(b, this[i].key); undefinedB = bVal === void 0 && aVal !== void 0; undefinedA = aVal === void 0 && bVal !== void 0; if (undefinedB || aVal > bVal) { return this[i].reverse; } else if (undefinedA || aVal < bVal) { return -1 * this[i].reverse; } } return 0; } var import_js_service2, _OrderClauseTool, OrderClauseTool; var init_order_clause_tool = __esm({ "src/filter/order-clause-tool.js"() { "use strict"; import_js_service2 = require("@e22m4u/js-service"); init_utils(); init_errors(); _OrderClauseTool = class _OrderClauseTool extends import_js_service2.Service { /** * Sort. * * @param {object[]} entities * @param {string|string[]|undefined} clause */ sort(entities, clause) { if (clause == null) return; if (Array.isArray(clause) === false) clause = [clause]; if (!clause.length) return; const mapping = []; clause.forEach((key, index) => { if (!key || typeof key !== "string") throw new InvalidArgumentError( 'The provided option "order" should be a non-empty String or an Array of non-empty String, but %v was given.', key ); let reverse = 1; const matches = key.match(/\s+(A|DE)SC$/i); if (matches) { key = key.replace(/\s+(A|DE)SC/i, ""); if (matches[1].toLowerCase() === "de") reverse = -1; } mapping[index] = { key, reverse }; }); entities.sort(compareFn.bind(mapping)); } /** * Validate order clause. * * @param {string|string[]|undefined} clause */ static validateOrderClause(clause) { if (clause == null) return; if (Array.isArray(clause) === false) clause = [clause]; if (!clause.length) return; clause.forEach((field) => { if (!field || typeof field !== "string") throw new InvalidArgumentError( 'The provided option "order" should be a non-empty String or an Array of non-empty String, but %v was given.', field ); }); } /** * Normalize order clause. * * @param {string|string[]|undefined} clause * @returns {string[]|undefined} */ static normalizeOrderClause(clause) { if (clause == null) return; if (Array.isArray(clause) === false) clause = [clause]; if (!clause.length) return; clause.forEach((field) => { if (!field || typeof field !== "string") throw new InvalidArgumentError( 'The provided option "order" should be a non-empty String or an Array of non-empty String, but %v was given.', field ); }); return clause; } }; __name(_OrderClauseTool, "OrderClauseTool"); OrderClauseTool = _OrderClauseTool; __name(compareFn, "compareFn"); } }); // src/filter/operator-clause-tool.js var import_js_service3, _OperatorClauseTool, OperatorClauseTool; var init_operator_clause_tool = __esm({ "src/filter/operator-clause-tool.js"() { "use strict"; import_js_service3 = require("@e22m4u/js-service"); init_utils(); init_errors(); init_errors(); _OperatorClauseTool = class _OperatorClauseTool extends import_js_service3.Service { /** * Compare. * * @param {*} val1 The 1st value * @param {*} val2 The 2nd value * @returns {number} 0: =, positive: >, negative < */ compare(val1, val2) { if (val1 == null || val2 == null) { return val1 == val2 ? 0 : NaN; } if (typeof val1 === "number") { if (typeof val2 === "number" || typeof val2 === "string" || typeof val2 === "boolean") { if (val1 === val2) return 0; return val1 - Number(val2); } return NaN; } if (typeof val1 === "string") { const isDigits = /^\d+$/.test(val1); if (isDigits) return this.compare(Number(val1), val2); try { if (val1 > val2) return 1; if (val1 < val2) return -1; if (val1 == val2) return 0; } catch (e) { } return NaN; } if (typeof val1 === "boolean") { return Number(val1) - Number(val2); } return val1 === val2 ? 0 : NaN; } /** * Test all operators. * * @param {object} clause * @param {*} value * @returns {boolean|undefined} */ testAll(clause, value) { if (!clause || typeof clause !== "object" || Array.isArray(clause)) throw new InvalidArgumentError( "The first argument of OperatorUtils.testAll should be an Object, but %v was given.", clause ); const eqNeqTest = this.testEqNeq(clause, value); if (eqNeqTest !== void 0) return eqNeqTest; const gtLtTest = this.testGtLt(clause, value); if (gtLtTest !== void 0) return gtLtTest; const incTest = this.testInq(clause, value); if (incTest !== void 0) return incTest; const ninTest = this.testNin(clause, value); if (ninTest !== void 0) return ninTest; const betweenTest = this.testBetween(clause, value); if (betweenTest !== void 0) return betweenTest; const existsTest = this.testExists(clause, value); if (existsTest !== void 0) return existsTest; const likeTest = this.testLike(clause, value); if (likeTest !== void 0) return likeTest; const nlikeTest = this.testNlike(clause, value); if (nlikeTest !== void 0) return nlikeTest; const ilikeTest = this.testIlike(clause, value); if (ilikeTest !== void 0) return ilikeTest; const nilikeTest = this.testNilike(clause, value); if (nilikeTest !== void 0) return nilikeTest; const regExpTest = this.testRegexp(clause, value); if (regExpTest !== void 0) return regExpTest; } /** * Test eq/neq operator. * * @example * ```ts * { * eq: 'foo', * } * ``` * * @example * ```ts * { * neq: 'foo', * } * ``` * * @param {object} clause * @param {*} value * @returns {boolean|undefined} */ testEqNeq(clause, value) { if (!clause || typeof clause !== "object") throw new InvalidArgumentError( "The first argument of OperatorUtils.testEqNeq should be an Object, but %v was given.", clause ); if ("eq" in clause) return this.compare(clause.eq, value) === 0; if ("neq" in clause) return this.compare(clause.neq, value) !== 0; } /** * Test lt/gt/lte/gte operator. * * @example * ```ts * { * lt: 10, * } * ``` * * @example * ```ts * { * lte: 10, * } * ``` * * @example * ```ts * { * gt: 10, * } * ``` * * @example * ```ts * { * gte: 10, * } * ``` * * @param {object} clause * @param {*} value * @returns {boolean|undefined} */ testGtLt(clause, value) { if (!clause || typeof clause !== "object") throw new InvalidArgumentError( "The first argument of OperatorUtils.testGtLt should be an Object, but %v was given.", clause ); if ("gt" in clause) return this.compare(value, clause.gt) > 0; if ("gte" in clause) return this.compare(value, clause.gte) >= 0; if ("lt" in clause) return this.compare(value, clause.lt) < 0; if ("lte" in clause) return this.compare(value, clause.lte) <= 0; } /** * Test inc operator. * * @example * ```ts * { * inc: ['foo', 'bar'], * } * ``` * * @param {object} clause * @param {*} value * @returns {boolean|undefined} */ testInq(clause, value) { if (!clause || typeof clause !== "object") throw new InvalidArgumentError( "The first argument of OperatorUtils.testInq should be an Object, but %v was given.", clause ); if ("inq" in clause && clause.inq !== void 0) { if (!clause.inq || !Array.isArray(clause.inq)) { throw new InvalidOperatorValueError( "inq", "an Array of possible values", clause.inq ); } for (let i = 0; i < clause.inq.length; i++) { if (clause.inq[i] == value) return true; } return false; } } /** * Test nin operator. * * @example * ```ts * { * nin: ['foo', 'bar'], * } * ``` * * @param {object} clause * @param {*} value * @returns {boolean|undefined} */ testNin(clause, value) { if (!clause || typeof clause !== "object") throw new InvalidArgumentError( "The first argument of OperatorUtils.testNin should be an Object, but %v was given.", clause ); if ("nin" in clause && clause.nin !== void 0) { if (!clause.nin || !Array.isArray(clause.nin)) { throw new InvalidOperatorValueError( "nin", "an Array of possible values", clause.nin ); } for (let i = 0; i < clause.nin.length; i++) { if (clause.nin[i] == value) return false; } return true; } } /** * Test between operator. * * @example * ```ts * { * between: [10, 20], * } * ``` * * @param {object} clause * @param {*} value * @returns {boolean|undefined} */ testBetween(clause, value) { if (!clause || typeof clause !== "object") throw new InvalidArgumentError( "The first argument of OperatorUtils.testBetween should be an Object, but %v was given.", clause ); if ("between" in clause && clause.between !== void 0) { if (!Array.isArray(clause.between) || clause.between.length !== 2) { throw new InvalidOperatorValueError( "between", "an Array of 2 elements", clause.between ); } return this.testGtLt({ gte: clause.between[0] }, value) && this.testGtLt({ lte: clause.between[1] }, value); } } /** * Test exists operator. * * @example * ```ts * { * exists: true, * } * ``` * * @param {object} clause * @param {*} value * @returns {boolean|undefined} */ testExists(clause, value) { if (!clause || typeof clause !== "object") throw new InvalidArgumentError( "The first argument of OperatorUtils.testExists should be an Object, but %v was given.", clause ); if ("exists" in clause && clause.exists !== void 0) { if (typeof clause.exists !== "boolean") { throw new InvalidOperatorValueError( "exists", "a Boolean", clause.exists ); } return clause.exists ? value !== void 0 : value === void 0; } } /** * Test like operator. * * @example * ```ts * { * like: 'foo', * } * ``` * * @param {object} clause * @param {*} value * @returns {boolean|undefined} */ testLike(clause, value) { if (!clause || typeof clause !== "object") throw new InvalidArgumentError( "The first argument of OperatorUtils.testLike should be an Object, but %v was given.", clause ); if ("like" in clause && clause.like !== void 0) { if (typeof clause.like !== "string" && !(clause.like instanceof RegExp)) throw new InvalidOperatorValueError("like", "a String", clause.like); return stringToRegexp(clause.like).test(value); } } /** * Test nlike operator. * * @example * ```ts * { * nlike: 'foo', * } * ``` * * @param {object} clause * @param {*} value * @returns {boolean|undefined} */ testNlike(clause, value) { if (!clause || typeof clause !== "object") throw new InvalidArgumentError( "The first argument of OperatorUtils.testNlike should be an Object, but %v was given.", clause ); if ("nlike" in clause && clause.nlike !== void 0) { if (typeof clause.nlike !== "string" && !(clause.nlike instanceof RegExp)) { throw new InvalidOperatorValueError("nlike", "a String", clause.nlike); } return !stringToRegexp(clause.nlike).test(value); } } /** * Test ilike operator. * * @example * ```ts * { * ilike: 'foo', * } * ``` * * @param {object} clause * @param {*} value * @returns {boolean|undefined} */ testIlike(clause, value) { if (!clause || typeof clause !== "object") throw new InvalidArgumentError( "The first argument of OperatorUtils.testIlike should be an Object, but %v was given.", clause ); if ("ilike" in clause && clause.ilike !== void 0) { if (typeof clause.ilike !== "string" && !(clause.ilike instanceof RegExp)) { throw new InvalidOperatorValueError("ilike", "a String", clause.ilike); } return stringToRegexp(clause.ilike, "i").test(value); } } /** * Test nilike operator. * * @example * ```ts * { * nilike: 'foo', * } * ``` * * @param {object} clause * @param {*} value * @returns {boolean|undefined} */ testNilike(clause, value) { if (!clause || typeof clause !== "object") throw new InvalidArgumentError( "The first argument of OperatorUtils.testNilike should be an Object, but %v was given.", clause ); if ("nilike" in clause && clause.nilike !== void 0) { if (typeof clause.nilike !== "string" && !(clause.nilike instanceof RegExp)) { throw new InvalidOperatorValueError( "nilike", "a String", clause.nilike ); } return !stringToRegexp(clause.nilike, "i").test(value); } } /** * Test regexp. * * @example * ```ts * { * regexp: 'foo.*', * } * ``` * * @example * ```ts * { * regexp: 'foo.*', * flags: 'i', * } * ``` * * @param {object} clause * @param {*} value * @returns {boolean|undefined} */ testRegexp(clause, value) { if (!clause || typeof clause !== "object") throw new InvalidArgumentError( "The first argument of OperatorUtils.testRegexp should be an Object, but %v was given.", clause ); if ("regexp" in clause && clause.regexp !== void 0) { if (typeof clause.regexp !== "string" && !(clause.regexp instanceof RegExp)) { throw new InvalidOperatorValueError( "regexp", "a String", clause.regexp ); } const flags = clause.flags || void 0; if (flags && typeof flags !== "string") throw new InvalidArgumentError( "RegExp flags should be a String, but %v was given.", clause.flags ); if (!value || typeof value !== "string") return false; const regExp = stringToRegexp(clause.regexp, flags); return !!value.match(regExp); } } }; __name(_OperatorClauseTool, "OperatorClauseTool"); OperatorClauseTool = _OperatorClauseTool; } }); // src/filter/where-clause-tool.js var import_js_service4, _WhereClauseTool, WhereClauseTool; var init_where_clause_tool = __esm({ "src/filter/where-clause-tool.js"() { "use strict"; import_js_service4 = require("@e22m4u/js-service"); init_utils(); init_errors(); init_operator_clause_tool(); _WhereClauseTool = class _WhereClauseTool extends import_js_service4.Service { /** * Filter by where clause. * * @example * ``` * const entities = [ * {foo: 1, bar: 'a'}, * {foo: 2, bar: 'b'}, * {foo: 3, bar: 'b'}, * {foo: 4, bar: 'b'}, * ]; * * const result = filterByWhereClause(entities, { * foo: {gt: 2}, * bar: 'b', * }); * * console.log(result); * // [ * // {foo: 3, bar: 'b'}, * // {foo: 4, bar: 'b'}, * // ]; * * ``` * * @param {object[]} entities * @param {WhereClause|undefined} where * @returns {object[]} */ filter(entities, where = void 0) { if (!Array.isArray(entities)) throw new InvalidArgumentError( "The first argument of WhereClauseTool.filter should be an Array of Object, but %v was given.", entities ); if (where == null) return entities; return entities.filter(this._createFilter(where)); } /** * Create where filter. * * @param {WhereClause} whereClause * @returns {Function} */ _createFilter(whereClause) { if (typeof whereClause !== "object" || Array.isArray(whereClause)) throw new InvalidArgumentError( 'The provided option "where" should be an Object, but %v was given.', whereClause ); const keys = Object.keys(whereClause); return (data) => { if (typeof data !== "object") throw new InvalidArgumentError( "The first argument of WhereClauseTool.filter should be an Array of Object, but %v was given.", data ); return keys.every((key) => { if (key === "and" && key in whereClause) { const andClause = whereClause[key]; if (Array.isArray(andClause)) return andClause.every((clause) => this._createFilter(clause)(data)); } else if (key === "or" && key in whereClause) { const orClause = whereClause[key]; if (Array.isArray(orClause)) return orClause.some((clause) => this._createFilter(clause)(data)); } const value = getValueByPath(data, key); const matcher = whereClause[key]; if (Array.isArray(value)) { if (typeof matcher === "object" && matcher !== null && "neq" in matcher && matcher.neq !== void 0) { if (value.length === 0) return true; return value.every((el, index) => { const where = {}; where[index] = matcher; return this._createFilter(where)({ ...value }); }); } return value.some((el, index) => { const where = {}; where[index] = matcher; return this._createFilter(where)({ ...value }); }); } if (this._test(matcher, value)) return true; }); }; } /** * Value testing. * * @param {*} example * @param {*} value * @returns {boolean} */ _test(example, value) { if (example === null) { return value === null; } if (example === void 0) { return value === void 0; } if (example instanceof RegExp) { if (typeof value === "string") return !!value.match(example); return false; } if (typeof example === "object") { const operatorsTest = this.getService(OperatorClauseTool).testAll( example, value ); if (operatorsTest !== void 0) return operatorsTest; } return example == value; } /** * Validate where clause. * * @param {WhereClause|undefined} clause */ static validateWhereClause(clause) { if (clause == null || typeof clause === "function") return; if (typeof clause !== "object" || Array.isArray(clause)) throw new InvalidArgumentError( 'The provided option "where" should be an Object, but %v was given.', clause ); } }; __name(_WhereClauseTool, "WhereClauseTool"); WhereClauseTool = _WhereClauseTool; } }); // src/definition/model/relations/relation-type.js var RelationType; var init_relation_type = __esm({ "src/definition/model/relations/relation-type.js"() { "use strict"; RelationType = { BELONGS_TO: "belongsTo", HAS_ONE: "hasOne", HAS_MANY: "hasMany", REFERENCES_MANY: "referencesMany" }; } }); // src/definition/model/relations/relation-definition.js var init_relation_definition = __esm({ "src/definition/model/relations/relation-definition.js"() { "use strict"; } }); // src/definition/model/relations/relations-definition-validator.js var import_js_service5, _RelationsDefinitionValidator, RelationsDefinitionValidator; var init_relations_definition_validator = __esm({ "src/definition/model/relations/relations-definition-validator.js"() { "use strict"; import_js_service5 = require("@e22m4u/js-service"); init_relation_type(); init_relation_type(); init_errors(); _RelationsDefinitionValidator = class _RelationsDefinitionValidator extends import_js_service5.Service { /** * Validate. * * @param {string} modelName * @param {object} relDefs */ validate(modelName, relDefs) { if (!modelName || typeof modelName !== "string") throw new InvalidArgumentError( "The first argument of RelationsDefinitionValidator.validate should be a non-empty String, but %v was given.", modelName ); if (!relDefs || typeof relDefs !== "object" || Array.isArray(relDefs)) throw new InvalidArgumentError( 'The provided option "relations" of the model %v should be an Object, but %v was given.', modelName, relDefs ); const relNames = Object.keys(relDefs); relNames.forEach((relName) => { const relDef = relDefs[relName]; this._validateRelation(modelName, relName, relDef); }); } /** * Validate relation. * * @param {string} modelName * @param {string} relName * @param {object} relDef */ _validateRelation(modelName, relName, relDef) { if (!modelName || typeof modelName !== "string") throw new InvalidArgumentError( "The first argument of RelationsDefinitionValidator._validateRelation should be a non-empty String, but %v was given.", modelName ); if (!relName || typeof relName !== "string") throw new InvalidArgumentError( "The relation name of the model %v should be a non-empty String, but %v was given.", modelName, relName ); if (!relDef || typeof relDef !== "object" || Array.isArray(relDef)) throw new InvalidArgumentError( "The relation %v of the model %v should be an Object, but %v was given.", relName, modelName, relDef ); if (!relDef.type || !Object.values(RelationType).includes(relDef.type)) throw new InvalidArgumentError( 'The relation %v of the model %v requires the option "type" to have one of relation types: %l, but %v was given.', relName, modelName, Object.values(RelationType), relDef.type ); this._validateBelongsTo(modelName, relName, relDef); this._validateHasOne(modelName, relName, relDef); this._validateHasMany(modelName, relName, relDef); this._validateReferencesMany(modelName, relName, relDef); } /** * Validate "belongsTo". * * @example The regular "belongsTo" relation. * ``` * { * type: RelationType.BELONGS_TO, * model: 'model', * foreignKey: 'modelId', // optional * } * ``` * * @example The polymorphic "belongsTo" relation. * ``` * { * type: RelationType.BELONGS_TO, * polymorphic: true, * foreignKey: 'referenceId', // optional * discriminator: 'referenceType', // optional * } * ``` * * @param {string} modelName * @param {string} relName * @param {object} relDef * @private */ _validateBelongsTo(modelName, relName, relDef) { if (relDef.type !== RelationType.BELONGS_TO) return; if (relDef.polymorphic) { if (typeof relDef.polymorphic !== "boolean") throw new InvalidArgumentError( 'The relation %v of the model %v has the type "belongsTo", so it expects the option "polymorphic" to be a Boolean, but %v was given.', relName, modelName, relDef.polymorphic ); if (relDef.foreignKey && typeof relDef.foreignKey !== "string") throw new InvalidArgumentError( 'The relation %v of the model %v is a polymorphic "belongsTo" relation, so it expects the provided option "foreignKey" to be a String, but %v was given.', relName, modelName, relDef.foreignKey ); if (relDef.discriminator && typeof relDef.discriminator !== "string") throw new InvalidArgumentError( 'The relation %v of the model %v is a polymorphic "belongsTo" relation, so it expects the provided option "discriminator" to be a String, but %v was given.', relName, modelName, relDef.discriminator ); } else { if (!relDef.model || typeof relDef.model !== "string") throw new InvalidArgumentError( 'The relation %v of the model %v has the type "belongsTo", so it requires the option "model" to be a non-empty String, but %v was given.', relName, modelName, relDef.model ); if (relDef.foreignKey && typeof relDef.foreignKey !== "string") throw new InvalidArgumentError( 'The relation %v of the model %v has the type "belongsTo", so it expects the provided option "foreignKey" to be a String, but %v was given.', relName, modelName, relDef.foreignKey ); if (relDef.discriminator) throw new InvalidArgumentError( 'The relation %v of the model %v is a non-polymorphic "belongsTo" relation, so it should not have the option "discriminator" to be provided.', relName, modelName ); } } /** * Validate "hasOne". * * @example The regular "hasOne" relation. * ``` * { * type: RelationType.HAS_ONE, * model: 'model', * foreignKey: 'modelId', * } * ``` * * @example The polymorphic "hasOne" relation with a target relation name. * ``` * { * type: RelationType.HAS_ONE, * model: 'model', * polymorphic: 'reference', * } * ``` * * @example The polymorphic "hasOne" relation with target relation keys. * ``` * { * type: RelationType.HAS_ONE, * model: 'model', * polymorphic: true, * foreignKey: 'referenceId', * discriminator: 'referenceType', * } * ``` * * @param {string} modelName * @param {string} relName * @param {object} relDef * @private */ _validateHasOne(modelName, relName, relDef) { if (relDef.type !== RelationType.HAS_ONE) return; if (!relDef.model || typeof relDef.model !== "string") throw new InvalidArgumentError( 'The relation %v of the model %v has the type "hasOne", so it requires the option "model" to be a non-empty String, but %v was given.', relName, modelName, relDef.model ); if (relDef.polymorphic) { if (typeof relDef.polymorphic === "string") { if (relDef.foreignKey) throw new InvalidArgumentError( 'The relation %v of the model %v has the option "polymorphic" with a String value, so it should not have the option "foreignKey" to be provided.', relName, modelName ); if (relDef.discriminator) throw new InvalidArgumentError( 'The relation %v of the model %v has the option "polymorphic" with a String value, so it should not have the option "discriminator" to be provided.', relName, modelName ); } else if (typeof relDef.polymorphic === "boolean") { if (!relDef.foreignKey || typeof relDef.foreignKey !== "string") throw new InvalidArgumentError( 'The relation %v of the model %v has the option "polymorphic" with "true" value, so it requires the option "foreignKey" to be a non-empty String, but %v was given.', relName, modelName, relDef.foreignKey ); if (!relDef.discriminator || typeof relDef.discriminator !== "string") throw new InvalidArgumentError( 'The relation %v of the model %v has the option "polymorphic" with "true" value, so it requires the option "discriminator" to be a non-empty String, but %v was given.', relName, modelName, relDef.discriminator ); } else { throw new InvalidArgumentError( 'The relation %v of the model %v has the type "hasOne", so it expects the provided option "polymorphic" to be a String or a Boolean, but %v was given.', relName, modelName, relDef.polymorphic ); } } else { if (!relDef.foreignKey || typeof relDef.foreignKey !== "string") throw new InvalidArgumentError( 'The relation %v of the model %v has the type "hasOne", so it requires the option "foreignKey" to be a non-empty String, but %v was given.', relName, modelName, relDef.foreignKey ); if (relDef.discriminator) throw new InvalidArgumentError( 'The relation %v of the model %v is a non-polymorphic "hasOne" relation, so it should not have the option "discriminator" to be provided.', relName, modelName ); } } /** * Validate "hasMany". * * @example The regular "hasMany" relation. * ``` * { * type: RelationType.HAS_MANY, * model: 'model', * foreignKey: 'modelId', * } * ``` * * @example The polymorphic "hasMany" relation with a target relation name. * ``` * { * type: RelationType.HAS_MANY, * model: 'model', * polymorphic: 'reference', * } * ``` * * @example The polymorphic "hasMany" relation with target relation keys. * ``` * {