@e22m4u/js-repository
Version:
Реализация репозитория для работы с базами данных в Node.js
1,526 lines (1,498 loc) • 242 kB
JavaScript
"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.
* ```
* {