UNPKG

@thisisagile/easy

Version:

Straightforward library for building domain-driven microservice architectures

1,619 lines (1,585 loc) 114 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 __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc2) => { 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: !(desc2 = __getOwnPropDesc(from, key)) || desc2.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 __decorateClass = (decorators, target, key, kind) => { var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target; for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result; if (kind && result) __defProp(target, key, result); return result; }; // src/index.ts var src_exports = {}; __export(src_exports, { Api: () => Api, ApiGateway: () => ApiGateway, App: () => App, Audit: () => Audit, AxiosProvider: () => AxiosProvider, BaseContext: () => BaseContext, BaseRequestContext: () => BaseRequestContext, CacheControl: () => CacheControl, Child: () => Child, Clause: () => Clause, Column: () => Column, Condition: () => Condition, ContentType: () => ContentType, Context: () => Context, Convert: () => Convert, Database: () => Database, DateTime: () => DateTime, DefaultProvider: () => DefaultProvider, Delete: () => Delete, DotEnvContext: () => DotEnvContext, EasyUri: () => EasyUri, Entity: () => Entity, Enum: () => Enum, Environment: () => Environment, Exception: () => Exception, Field: () => Field, Gateway: () => Gateway, HttpHeader: () => HttpHeader, HttpStatus: () => HttpStatus, HttpVerb: () => HttpVerb, InMemoryGateway: () => InMemoryGateway, Insert: () => Insert, Join: () => Join, Jwt: () => Jwt, List: () => List, LogicalCondition: () => LogicalCondition, Manage: () => Manage, MappedRouteGateway: () => MappedRouteGateway, Mapper: () => Mapper, OrderColumn: () => OrderColumn, PageList: () => PageList, ParathesizedClause: () => ParathesizedClause, Parser: () => Parser, PatternColumn: () => PatternColumn, Property: () => Property, Repo: () => Repo, Repository: () => Repository, Req: () => Req, RequestOptions: () => RequestOptions, Results: () => Results, RouteGateway: () => RouteGateway, Scope: () => Scope, Search: () => Search, Select: () => Select, Sentence: () => Sentence, SortCondition: () => SortCondition, SqlQuery: () => SqlQuery, State: () => State, Struct: () => Struct, Table: () => Table, TableGateway: () => TableGateway, Template: () => Template, ToText: () => ToText, Try: () => Try, Typo: () => Typo, Update: () => Update, UseCase: () => UseCase, Value: () => Value, View: () => View, ViewRouteGateway: () => ViewRouteGateway, Wait: () => Wait, When: () => When, accumulate: () => accumulate, any: () => any, api: () => api, array: () => array, asJson: () => asJson, asList: () => asList, asNumber: () => asNumber, asPageList: () => asPageList, asResults: () => asResults, asString: () => asString, asc: () => asc, base64: () => base64, build: () => build, cache: () => cache, cacheAge: () => cacheAge, capitalize: () => capitalize, choose: () => choose, clipUri: () => clipUri, constraint: () => constraint, convert: () => convert, ctx: () => ctx, days: () => days, defined: () => defined, desc: () => desc, dir: () => dir, dt: () => dt, entries: () => entries, extractKeys: () => extractKeys, future: () => future, gt: () => gt, gte: () => gte, ifA: () => ifA, ifDefined: () => ifDefined, ifFalse: () => ifFalse, ifGet: () => ifGet, ifNotEmpty: () => ifNotEmpty, ifTrue: () => ifTrue, inFuture: () => inFuture, inList: () => inList, inOptionalList: () => inOptionalList, inPast: () => inPast, includes: () => includes, isA: () => isA, isAn: () => isAn, isArray: () => isArray, isBoolean: () => isBoolean, isCacheAge: () => isCacheAge, isClause: () => isClause, isConstructor: () => isConstructor, isCurrency: () => isCurrency, isDate: () => isDate, isDateTime: () => isDateTime, isDefined: () => isDefined, isDoesNotExist: () => isDoesNotExist, isEmpty: () => isEmpty, isEmptyObject: () => isEmptyObject, isEnum: () => isEnum, isEqual: () => isEqual, isError: () => isError, isException: () => isException, isFalsy: () => isFalsy, isField: () => isField, isFunc: () => isFunc, isFunction: () => isFunction, isHttpStatus: () => isHttpStatus, isIdentity: () => isIdentity, isIn: () => isIn, isInstance: () => isInstance, isIntersecting: () => isIntersecting, isIsoDateString: () => isIsoDateString, isJson: () => isJson, isList: () => isList, isLoading: () => isLoading, isMapping: () => isMapping, isNotEmpty: () => isNotEmpty, isNotPresent: () => isNotPresent, isNullish: () => isNullish, isNumber: () => isNumber, isObject: () => isObject, isPageList: () => isPageList, isPresent: () => isPresent, isPrimitive: () => isPrimitive, isRequestOptions: () => isRequestOptions, isResponse: () => isResponse, isRestResult: () => isRestResult, isResult: () => isResult, isResults: () => isResults, isSimpleView: () => isSimpleView, isSortCondition: () => isSortCondition, isString: () => isString, isStruct: () => isStruct, isText: () => isText, isTrue: () => isTrue, isTruthy: () => isTruthy, isUndefined: () => isUndefined, isUuid: () => isUuid, isValid: () => isValid, isValidatable: () => isValidatable, isValue: () => isValue, json: () => json, kebab: () => kebab, keys: () => keys, log: () => log, lt: () => lt, lte: () => lte, mappings: () => mappings, maxLength: () => maxLength, maxValue: () => maxValue, meta: () => meta, minLength: () => minLength, minValue: () => minValue, notEmpty: () => notEmpty, ofConstruct: () => ofConstruct, ofGet: () => ofGet, ofMessage: () => ofMessage, ofProperty: () => ofProperty, on: () => on, optional: () => optional, past: () => past, quote: () => quote, reject: () => reject, replaceAll: () => replaceAll, required: () => required, resolve: () => resolve, rest: () => rest, rule: () => rule, searchable: () => searchable, seconds: () => seconds, settled: () => settled, singleton: () => singleton, tag: () => tag, takeFirstKey: () => takeFirstKey, template: () => template, text: () => text, textValue: () => textValue, toArray: () => toArray, toCacheOptions: () => toCacheOptions, toClause: () => toClause, toCondition: () => toCondition, toFilter: () => toFilter, toHttpStatus: () => toHttpStatus, toId: () => toId, toJson: () => toJson, toList: () => toList, toName: () => toName, toObject: () => toObject, toPageList: () => toPageList, toPageOptions: () => toPageOptions, toReq: () => toReq, toResponse: () => toResponse, toResult: () => toResult, toResults: () => toResults, toSegment: () => toSegment, toShortFilter: () => toShortFilter, toUuid: () => toUuid, toViewer: () => toViewer, toWords: () => toWords, traverse: () => traverse, traverseSet: () => traverseSet, tryTo: () => tryTo, tuple: () => tuple, tuple2: () => tuple2, tuple3: () => tuple3, tuple4: () => tuple4, tuple5: () => tuple5, uri: () => uri, use: () => use, valid: () => valid, validate: () => validate, validateReject: () => validateReject, values: () => values, view: () => view, views: () => views, wait: () => wait, we: () => we, when: () => when }); module.exports = __toCommonJS(src_exports); // src/types/Is.ts var isDefined = (o) => o !== void 0 && o !== null; var isUndefined = (v) => v === void 0 || v === null; var isEmpty = (o) => o === "" || o === null || o === void 0 || isArray(o) && o.length === 0; var isNotEmpty = (o) => o !== "" && o !== null && o !== void 0 && (!isArray(o) || o.length > 0); var isString = (o) => o instanceof String || typeof o === "string"; var isIsoDateString = (o) => isString(o) && /^\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)$/.test(o); var isBoolean = (o) => isDefined(o) && typeof o === "boolean"; var isTrue = (o) => isFunction(o) ? isTrue(o()) : isBoolean(o) ? o : !!o; var isNumber = (o) => isDefined(o) && typeof o === "number" && !Number.isNaN(o); var isObject = (o) => o != null && typeof o === "object" && !isArray(o); var isEmptyObject = (o) => isObject(o) && Object.getOwnPropertyNames(o).length === 0; var isFunction = (o) => isDefined(o) && typeof o === "function"; var isArray = (o) => isDefined(o) && o instanceof Array; var isIn = (o, values2) => isArray(values2) && values2.some((v) => v === o); var isIntersecting = (o, values2) => isArray(o) && isArray(values2) && o.some((ov) => isIn(ov, values2)); var isError = (e) => isDefined(e) && e instanceof Error; var isNotPresent = (...os) => os.some( (o) => o === null || o === void 0 || o === "" || o instanceof Array && o.length === 0 || typeof o === "object" && Object.getOwnPropertyNames(o).length === 0 ); var isPresent = (...os) => !isNotPresent(...os); // src/types/Primitive.ts var isPrimitive = (v) => { return v === null || v === void 0 || isIn(typeof v, ["string", "number", "bigint", "boolean", "symbol"]); }; // src/types/Func.ts var isFunc = (o) => !!o && typeof o === "function"; // src/types/Constructor.ts var isConstructor = (c) => (isDefined(c) && isFunc(c) && c.prototype && c.prototype.constructor) === c; var isInstance = (ctor, o) => isFunction(ctor) && o instanceof ctor; var ofConstruct = (c, ...args) => isConstructor(c) ? new c(...args) : isFunc(c) ? c(...args) : c; var toName = (subject, postfix = "") => subject?.constructor?.name?.replace(postfix, "").toLowerCase() ?? ""; var isPromise = (value) => { return value instanceof Promise; }; var on = (t, f) => { const result = f(t); return isPromise(result) ? result.then(() => t) : t; }; var use = (t, f) => f(t); var ifA = (c, t, alt) => !isPrimitive(t) && t instanceof c ? t : alt ? ifA(c, alt) : void 0; // src/types/IsA.ts var isA = (t, ...properties) => !isPrimitive(t) && properties.every((p) => p.toString() in t); var isAn = isA; var isIdentity = (by) => use(by, (b) => isObject(b) && isDefined(b.id)); // src/types/Get.ts var ofGet = (g, ...args) => isFunc(g) ? g(...args) : g; var ifGet = (pred, valid2, invalid) => ofGet(pred) ? ofGet(valid2) : ofGet(invalid); var ofProperty = (t, p) => isFunc(p) ? p(t) : t[p]; // src/utils/If.ts function ifTrue(o, f, alt) { return isTrue(o) ? ofConstruct(f, o) : ofConstruct(alt, o); } function ifFalse(o, f, alt) { return !isTrue(o) ? ofConstruct(f, o) : ofConstruct(alt, o); } function ifDefined(o, f, alt) { return isDefined(o) ? ofConstruct(f, o) : ofConstruct(alt); } function ifNotEmpty(o, f = (o2) => o2, alt) { return isNotEmpty(o) ? ofConstruct(f, o) : ofConstruct(alt, o); } // src/types/Array.ts var toArray = (...items) => items.length > 1 ? items : isArray(items[0]) ? items[0] : isDefined(items[0]) ? [items[0]] : []; var toObject = (key, ...items) => toArray(...items).reduce((o, i) => { o[i[key]] = i; return o; }, {}); var array = { merge: (first = [], second = [], firstKey = "id", secondKey = "id") => first.map((f) => ({ ...f, ...second.find((s) => isDefined(s[secondKey]) && isDefined(f[firstKey]) && s[secondKey] === f[firstKey]) })), switch: (items = [], item) => use([...items], (res) => { on(res.indexOf(item), (i) => i !== -1 ? res.splice(i, 1) : res.push(item)); return res; }), splitIn: (items = [], length = 2) => { const res = Array.from({ length }, () => []); items.forEach((i, index) => res[index % length].push(i)); return res; }, chunk: (items = [], length = 2) => { const chunks = Math.ceil(items.length / length); const res = Array.from({ length: chunks }, () => []); items.forEach((i, index) => res[Math.floor(index / chunks)].push(i)); return res; } }; // src/types/Text.ts var isText = (t) => isDefined(t) && isFunc(t.toString); var asString = (t, alt = "") => (isText(t) ? t : ofGet(alt)).toString(); var replaceAll = (origin, search, replace = "") => asString(origin).split(asString(search)).join(asString(replace)); var toWords = (input) => { return asString(input).replace(/(\p{Lower})(\p{Upper})/gu, "$1 $2").replace(/(\p{Upper})(\p{Upper}\p{Lower})/gu, "$1 $2").split(/[_\W]+/g).filter(Boolean); }; var kebab = (s = "") => toWords(s).join("-").toLowerCase(); var capitalize = (s = "") => s.charAt(0).toUpperCase() + s.slice(1); // src/types/List.ts var List = class extends Array { get ids() { return this.mapDefined((i) => i.id); } isSubSetOf(...items) { return this.diff(items).length === 0; } isSuperSetOf(...items) { return this.length > items.length && toList(...items).isSubSetOf(...this); } isIntersectingWith(...items) { return this.intersect(items).length > 0; } isDisjointWith(...items) { return !this.isIntersectingWith(...items); } areEqual(...items) { return this.isSubSetOf(...items) && toList(...items).isSubSetOf(...this); } asc(p) { return this.sort((e1, e2) => ofProperty(e1, p) > ofProperty(e2, p) ? 1 : -1); } desc(p) { return this.sort((e1, e2) => ofProperty(e1, p) < ofProperty(e2, p) ? 1 : -1); } first(p, params) { return p ? this.find(p, params) : this[0]; } firstValue(f, alt) { return ifDefined( this.first((t) => !!f(t)), f, (v) => ofGet(alt, v) ); } isFirst(value) { return value === this.first(); } next(p, params) { return p ? this[this.findIndex(p, params) + 1] : this[0]; } prev(p, params) { return p ? this[this.findIndex(p, params) - 1] : this[0]; } last(p, params) { return p ? this.filter(p, params).last() : this[this.length - 1]; } isLast(value) { return value === this.last(); } overlaps(...items) { return toList(...items).some((i) => this.some((t) => i === t)); } diff(others) { return this.filter((i) => !others.includes(i)); } diffByKey(others, key) { return this.filter((i) => !others.some((o) => o[key] === i[key])); } symmetricDiff(others) { return this.diff(others).concat(toList(...others).diff(this)); } symmetricDiffByKey(others, key) { return this.diffByKey(others, key).concat(toList(...others).diffByKey(this, key)); } intersect(others) { return this.filter((i) => others.includes(i)); } intersectByKey(others, key) { return this.filter((i) => others.some((o) => o[key] === i[key])); } intersectBy(others, f) { return this.filter((i) => others.some((o) => f(i, o))); } accumulate(...keys2) { return this.map((d, i, arr) => { const acc = keys2.reduce((acc2, v) => { acc2[v] = i === 0 ? d[v] : arr[i - 1][v] + d[v]; return acc2; }, d); arr[i] = acc; return acc; }); } toJSON() { return this.reduce((a, i) => { a.push(JSON.parse(JSON.stringify(i ?? {}))); return a; }, new Array()); } map(f, params) { return toList(super.map(f, params)); } flatMap(f, params) { return toList(super.flatMap(f, params)); } mapDefined(f, params) { return this.map(f, params).defined(); } mapAsync(f) { return Promise.all(super.map((e) => f(e))).then((a) => toList(a)); } mapSerial(f) { return super.reduce((p, item) => p.then((results) => on(results, async (r) => r.push(await f(item)))), Promise.resolve(toList())); } distinct() { return this.filter((i, index) => this.indexOf(i) === index); } distinctByKey(key) { const seen = /* @__PURE__ */ new Set(); return this.filter((item) => !seen.has(item[key]) && seen.add(item[key])); } distinctByValue() { const seen = /* @__PURE__ */ new Set(); return this.filter((item) => !seen.has(JSON.stringify(item)) && seen.add(JSON.stringify(item))); } filter(p, params) { return toList(super.filter(p, params)); } sum(p) { return this.reduce((sum, i) => sum + p(i), 0); } max(key) { return this.desc(key).first(); } min(key) { return this.asc(key).first(); } byId(id) { return this.first((i) => asString(i.id) === asString(id)); } byKey(key, value) { return this.first((i) => i[key] == value); } add(...items) { super.push(...toArray(...items)); return this; } concat(...items) { return toList(super.concat(...items)); } reverse() { return toList(super.reverse()); } splice(start, deleteCount, ...items) { return toList(super.splice(start, deleteCount, ...items)); } remove(item) { const index = this.indexOf(item); if (index > -1) { this.splice(index, 1); } return this; } replace(key, item) { const index = this.findIndex((i) => i[key] === item?.[key]); ifTrue(index != -1, () => this.splice(index, 1, item)); return this; } switch(item) { return this.includes(item) ? this.remove(item) : this.add(item); } defined() { return this.reduce((l, v) => isDefined(v) ? l.add(v) : l, toList()); } toObject(key, options = {}) { return this.reduce((o, i) => { o[i[key]] = i; if (options.deleteKey) delete o[i[key]][key]; return o; }, {}); } toObjectList(key) { return this.reduce( (a, t) => { const k = t[key]; a[k] = a[k] ?? toList(); a[k].push(t); return a; }, {} ); } orElse(...alt) { return !isEmpty(this) ? this : !isEmpty(...alt) ? toList(...alt) : void 0; } weave(insertFrom, interval) { for (let i = interval, n = 0; i <= this.length && n < insertFrom.length; i += interval + 1) { this.splice(i, 0, insertFrom[n++]); } return this; } slice(start, end) { return toList(super.slice(start, end)); } none(p) { return !this.some(p); } chunk(chunkSize) { return this.reduce((acc, _, index) => index % chunkSize === 0 ? on(acc, (a) => a.push(this.slice(index, index + chunkSize))) : acc, toList()); } //we needed to add U because of a Typescript issue with generics update(p, val) { return this.map((v, i, a) => p(v, i, a) ? ofGet(val, v, i, a) : v); } updateFirst(p, val) { const index = this.findIndex(p); return this.update((t, i) => p(t, i, this) && i == index, val); } updateFirstById(id, val) { return this.updateFirst((i) => asString(i?.id) === asString(id), val); } updateById(id, val) { return this.update((i) => asString(i?.id) === asString(id), val); } }; var toList = (...items) => new List().add(...items); var isList = (l) => isDefined(l) && isArray(l) && isA(l, "first", "last", "asc", "desc"); var asList = (c, items = []) => toList(toArray(items).map((i) => new c(i))); var maxValue = (l, key) => l.desc(key).first()?.[key]; var minValue = (l, key) => l.asc(key).first()?.[key]; // src/types/Object.ts function entries(subject) { return ifDefined( subject, () => toList([...Object.entries(subject), ...Object.entries(Object.getPrototypeOf(subject))]), () => toList() ); } function values(subject) { return toList([...Object.values(subject), ...Object.values(Object.getPrototypeOf(subject))]); } function keys(subject) { return toList([...Object.keys(subject), ...Object.keys(Object.getPrototypeOf(subject))]); } function extractKeys(obj, keys2) { return keys2.filter((k) => k in obj).reduce( (acc, key) => { acc.keys[key] = obj[key]; delete acc[key]; return acc; }, { keys: {}, ...obj } ); } // src/types/Json.ts var isJson = (subject) => isA(subject, "toJSON"); var json = { parse: (subject) => JSON.parse(JSON.stringify(subject ?? {})), merge: (...subjects) => json.parse(subjects.map((s) => asJson(s, (s2) => json.parse(s2))).reduce((js, j) => ({ ...js, ...j }), {})), delete: (subject, key) => { ifDefined(subject, () => delete subject[key]); return subject; }, set: (subject, key = "", value) => isEmpty(key) ? subject : value !== void 0 ? { ...subject, ...{ [key]: value } } : json.delete(subject, key), omit: (subject, ...keys2) => keys2.reduce((js, k) => json.delete(js, k), json.parse(subject)), pick: (subject, ...keys2) => keys2.reduce((js, k) => json.set(js, k, subject[k]), {}), defaults: (options = {}, defaults = {}) => json.merge(defaults, options), isSubset: (subject, subset) => !entries(subset).some(([k, v]) => subject[k] !== v) }; var toJson = json.merge; var asJson = (j, alt = {}) => isJson(j) ? j.toJSON() : isObject(j) ? j : ofGet(alt, j); var Any = class { constructor(value) { this.value = value; } merge = (...subjects) => any(json.merge(this.value, ...subjects)); delete = (key) => any(json.delete(this.value, key)); omit = (...keys2) => any(json.omit(this.value, ...keys2)); set = (key, value) => any(json.set(this.value, key, value)); toJSON() { return this.value; } }; var takeFirstKey = (j, alt = "") => entries(asJson(j)).first()?.[0] ?? alt; var any = (value) => new Any(value); // src/utils/Convert.ts var Convert = class { constructor(from, to) { this.from = from; this.to = to; } }; var convert = { default: new Convert( (a) => a, (a) => a ), ignore: new Convert( () => void 0, () => void 0 ), toBool: { fromNumber: new Convert( (b) => b ? 1 : 0, (n) => n !== 0 ), fromString: new Convert( (b) => b ? "true" : "false", (s) => s === "true" ) }, toDate: { fromString: new Convert( (s) => new Date(s).toISOString(), (s) => s ) }, toNumber: { fromString: new Convert( (n) => asString(n), (s) => parseInt(s) ) } }; // src/data/Condition.ts var Condition = class { constructor(key, operator, value) { this.key = key; this.operator = operator; this.value = value; } and = (...others) => new LogicalCondition("and", [this, ...others]); or = (...others) => new LogicalCondition("or", [this, ...others]); toJSON() { return { [this.key]: { [`$${this.operator}`]: json.parse(this.value) } }; } }; var LogicalCondition = class { constructor(operator, conditions) { this.operator = operator; this.conditions = conditions; } toJSON() { return { [`$${this.operator}`]: this.conditions.map((c) => c.toJSON()) }; } }; var SortCondition = class extends Condition { constructor(key, value) { super(key, "", value); this.key = key; this.value = value; } toJSON() { return { [this.key]: this.value }; } }; var toCondition = (field, operator, value, conv = convert.default) => new Condition(field, operator, conv.from(value)); var isSortCondition = (s) => isDefined(s) && s instanceof SortCondition; // src/types/Meta.ts var import_reflect_metadata = require("reflect-metadata"); var ClassMeta = class { constructor(subject, data = (subject.prototype ?? subject).constructor) { this.subject = subject; this.data = data; } get = (key) => Reflect.getMetadata(key, this.data); set = (key, value) => { Reflect.defineMetadata(key, value, this.data); return value; }; entries = () => entries(this.subject); parse = (f, options = {}) => { const { initial = {}, skipUndefined = false } = options; return this.entries().reduce((a, [k, val]) => use(f(val), (v) => isDefined(v) || !skipUndefined ? on(a, (a2) => a2[k] = v) : a), initial); }; properties = (key) => toList([...Object.getOwnPropertyNames(this.subject), ...Object.getOwnPropertyNames(Object.getPrototypeOf(this.subject))]).map((p) => this.property(p)).filter((p) => key ? p.get(key) : p); keys = (key) => this.properties().map((p) => p.get(key)).reduce((list, u) => u ? list.add(u) : list, toList()); values = () => values(this.subject); property = (property) => new PropertyMeta(this.subject, property); }; var PropertyMeta = class { constructor(subject, property, data = Reflect.getMetadata(property, subject)) { this.subject = subject; this.property = property; this.data = data; } get value() { return this.subject[this.property]; } get = (key) => isDefined(this.data) && isDefined(this.data[key]) ? this.data[key] : void 0; set = (key, value) => { Reflect.defineMetadata(this.property, { ...this.data, [key]: value }, this.subject); return value; }; }; var meta = (subject) => new ClassMeta(subject ?? {}); // src/types/Enum.ts var Enum = class { constructor(name, id = name.toLowerCase(), code = id.toString()) { this.name = name; this.id = id; this.code = code; } get isValid() { return isDefined(this.id); } static all() { return meta(this.allTuple()).values(); } static allTuple() { return meta(this).get(`all-${this.name}`) ?? meta(this).set(`all-${this.name}`, meta(this).values().filter(isEnum).toObject("id")); } static filter(p, params) { return this.all().filter(p, params); } static first(p, params) { return this.all().first(p, params); } static byIds(ids = []) { return toList(ids).mapDefined((id) => this.byId(id)).distinct(); } static byId(id, alt) { return this.allTuple()[id] ?? ofGet(alt); } equals(other) { return this.id === (isEnum(other) ? other.id : other); } isIn(...items) { return items.some((i) => this.equals(i)); } toJSON() { return this.id; } toString() { return this.id.toString(); } }; var isEnum = (e) => isDefined(e) && e instanceof Enum && isAn(e, "name", "id", "code"); // src/types/Template.ts var Template = class { constructor(template2, subject = {}, options = {}) { this.template = template2; this.subject = subject; this.options = options; } toString = () => { return entries(this.options).reduce((t, [k]) => this.option(t, k), this.object()).replace(" ", " "); }; props = (tmpl, key, result = toList()) => { const i1 = tmpl.indexOf(`{${key}`); if (i1 < 0) { return result; } const i2 = tmpl.indexOf("}", i1); return this.props(tmpl.slice(i2 + 1), key, result.add(tmpl.substring(i1 + 1, i2))); }; object = () => { return this.props(this.template, "this").reduce((t, p) => t.replace(`{${p}}`, textValue(this.subject, p.replace("this.", ""))), this.template); }; option = (tmpl, prop) => { return this.props(tmpl, prop).reduce((t, p) => t.replace(`{${p}}`, textValue(this.options, p)), tmpl); }; }; function template(tmpl, subject, options = {}) { return new Template(asString(tmpl), subject, { type: toName(subject), subject: text(JSON.stringify(subject)), ...options }); } var ToText = class { constructor(subject) { this.subject = subject; } get cap() { return this.map((s) => capitalize(s?.toLowerCase())); } get capFirst() { return this.map((s) => capitalize(s)); } get title() { return this.map( (s) => s.split(" ").map((w) => text(w).cap).join(" ") ); } get pascal() { return this.title.replace(" ", ""); } get lower() { return this.map((s) => s.toLowerCase()); } get upper() { return this.map((s) => s.toUpperCase()); } get camel() { return this.title.trim.map((s) => `${s.charAt(0).toLowerCase()}${s.slice(1)}`); } get kebab() { return this.lower.replace(" ", "-"); } get strictKebab() { return this.map((s) => s.replace(/[^a-z\d]+/gi, " ").trim()).kebab; } get slug() { return this.map( (s) => s.replace(/ß/g, "ss").normalize("NFKD").replace(/[\u0300-\u036F]/g, "").toLowerCase().replace(/[^a-z\d]+/g, "-").replace(/(^-)|(-$)/g, "") ); } get snake() { return this.upper.replace(" ", "_"); } get plural() { return this.ifLike("") ?? this.add("s"); } get space() { return this.map((s) => s.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ")); } get sentence() { return this.isEmpty ? this : this.map((s) => `${s.charAt(0).toUpperCase()}${s.slice(1)}.`); } get initials() { return this.map( (s) => s.split(" ").map((w) => w[0]).join("") ); } get trim() { return this.map((s) => s.replace(/[- ,_#]/g, "")); } get isEmpty() { return isEmpty(this.toString()); } parse = (subject, options = {}) => text(template(this.subject, subject, { type: toName(subject), ...options })); is = (...others) => others.some((o) => this.toString() === text(o).toString()); equals = this.is; isLike = (...others) => others.some((o) => this.trim.lower.is(text(o).trim.lower)); ifLike = (...others) => this.isLike(...others) ? this : void 0; endsWith = (end) => this.subject.endsWith(asString(end)); startsWith = (end) => this.subject.startsWith(asString(end)); first = (n) => this.map((s) => s.substring(0, n)); last = (n) => this.map((s) => s.substring(s.length - n)); map = (func) => text(ofGet(func, this.subject)); replace = (search, replace) => this.map((s) => replaceAll(s, search, replace)); add = (add, separator = "") => this.map((s) => isNotEmpty(add) ? `${s}${separator}${text(add)}` : s); with = (separator, ...other) => this.map( (s) => toList(s).add(...other.map((u) => text(u).toString())).filter((s2) => isNotEmpty(s2)).join(separator) ); split = (separator = " ") => toList(this.subject.split(separator)); toString() { return this.subject; } toJSON() { return this.subject; } }; function text(subject, alt = "") { const sub = subject ? asString(subject) : alt; return new ToText(sub !== "[object Object]" ? sub : ""); } function textValue(subject, prop) { const p = prop.split("."); const root = subject?.[p[0]]; const initial = typeof root === "object" && root !== null ? root : text(root); return p.splice(1).reduce((t, s) => t?.[s], initial)?.toString() ?? ""; } // src/types/Exception.ts var Exception = class _Exception extends Enum { constructor(message, id, reason) { super(message, id ?? text(message).pascal.toString()); this.message = message; this.reason = reason; } static AlreadyExists = new _Exception("Subject already exists"); static DoesNotExist = new _Exception("Does not exist"); static IsMissingId = new _Exception("Subject is missing an id"); static IsNotImplemented = new _Exception("Is not implemented"); static IsNotValid = new _Exception("Is not valid"); static Unknown = new _Exception("Unknown error"); static CouldNotExecute = (target) => new _Exception(`Could not execute ${target}.`, "CouldNotExecute"); static CouldNotValidate = (target) => new _Exception(`Could not validate ${target}.`, "CouldNotValidate"); static EnvironmentVariableNotFound = (variable) => new _Exception(`Environment variable ${text(variable).upper} could not be found.`, "EnvironmentVariableNotFound"); because = (reason) => new _Exception(this.message, this.id, reason); }; var isException = (e, t) => e instanceof Exception && (isDefined(t) ? e.equals(asString(t)) : true); var isDoesNotExist = (e) => e instanceof Exception && Exception.DoesNotExist.equals(e); // src/utils/Promise.ts var resolve = (subject) => Promise.resolve(subject); var reject = (e) => Promise.reject(e); var tuple = { 2: (first, second) => Promise.all([first, second]), 3: (first, second, third) => Promise.all([first, second, third]), 4: (first, second, third, forth) => Promise.all([first, second, third, forth]), 5: (first, second, third, forth, fifth) => Promise.all([first, second, third, forth, fifth]), all: (first, second) => Promise.all([first, Promise.all(second)]), spread: (first, ...second) => Promise.all([first, Promise.all(toArray(second))]), list: (list) => Promise.all([...list]).then(toList), settled: (list) => Promise.allSettled([...list]).then((rs) => ({ fulfilled: toList(...rs.filter((r) => r.status === "fulfilled").map((r) => r.value)), rejected: toList(...rs.filter((r) => r.status === "rejected").map((r) => asString(r.reason))) })) }; var tuple2 = tuple[2]; var tuple3 = tuple[3]; var tuple4 = tuple[4]; var tuple5 = tuple[5]; var settled = tuple.settled; // src/types/Gateway.ts var Gateway = class { all(options) { return reject(Exception.IsNotImplemented); } byId(id, options) { return reject(Exception.IsNotImplemented); } by(_key, _value, _options) { return reject(Exception.IsNotImplemented); } byIds(..._ids) { return reject(Exception.IsNotImplemented); } search(q, options) { return reject(Exception.IsNotImplemented); } filter(options) { return reject(Exception.IsNotImplemented); } exists(id, options) { return reject(Exception.IsNotImplemented); } add(item, options) { return reject(Exception.IsNotImplemented); } update(item, options) { return reject(Exception.IsNotImplemented); } remove(id, options) { return reject(Exception.IsNotImplemented); } }; // src/validation/When.ts var When = class _When { constructor(subject, valid2 = true, results) { this.subject = subject; this.valid = valid2; this.results = results; } get not() { return this.clone(!this.valid); } get and() { return this.clone(this.valid); } get isDefined() { return this.clone(this.valid === isDefined(this.subject)); } get isEmpty() { return this.clone(this.valid === isEmpty(this.subject)); } get isTrue() { return this.clone(this.valid === !!this.subject); } get isValid() { this.results = validate(this.subject); return this.clone(this.valid === this.results.isValid); } isInstance = (c) => this.clone(this.valid === this.subject instanceof c); with = (pred) => this.clone(this.valid === ofGet(pred, this.subject)); contains = (property) => this.clone(this.valid === isDefined(ofGet(property, this.subject))); in = (...items) => this.clone(this.valid === isIn(this.subject, toArray(...items))); is = (item) => this.clone(this.valid === (this.subject === item)); reject = (error) => !this.valid ? resolve(this.subject) : reject(ofGet(error, this.subject) ?? this.results ?? Exception.Unknown); recover = (f) => resolve(!this.valid ? this.subject : f(this.subject)); clone = (result = true) => new _When(this.subject, result, this.results); }; var when = (subject) => new When(subject); // src/types/Context.ts var DotEnvContext = class { domain = process.env.DOMAIN ?? "easy"; name = process.env.ENVIRONMENT_NAME ?? ""; host = process.env.HOST ?? ""; port = Number.parseInt(process.env.PORT ?? "8080"); app = process.env.APP ?? ""; get = (key, alt) => { const k = text(key).map((k2) => k2.replace(/([a-z])([A-Z])/g, "$1 $2")).snake.toString(); return process.env[k] ?? alt; }; }; var BaseRequestContext = class { state = {}; get token() { return this.get("token"); } set token(token) { this.set("token", token); } get identity() { return this.token; } get jwt() { return this.get("jwt"); } set jwt(jwt) { this.set("jwt", jwt); } get correlationId() { return this.get("correlationId"); } set correlationId(id) { this.set("correlationId", id); } get lastError() { return this.get("lastError"); } set lastError(error) { this.set("lastError", error); } get(key) { return this.state[key]; } set(key, value) { return this.state[key] = value; } create = (f) => f(); wrap = (f) => f(); }; var BaseContext = class extends BaseRequestContext { }; var Context = class { constructor(state = {}) { this.state = state; this.state = { ...{ env: new DotEnvContext(), request: new BaseRequestContext(), other: {} }, ...this.state }; } get env() { return this.state.env; } set env(env) { this.state.env = env; } get request() { return this.state.request; } set request(request) { this.state.request = request; } get other() { return this.state.other; } }; var ctx = new Context(); // src/types/Result.ts var toResult = (message, location, domain = ctx.env.domain) => ({ message: message.toString(), location: location?.toString(), domain: domain?.toString() }); var isResult = (r) => isA(r, "message"); // src/types/Results.ts var parse = (...rs) => toArray(...rs).map((r) => isResult(r) ? r : toResult(r)); var Results = class { results; constructor(...rs) { this.results = parse(...rs); } get length() { return this.results.length; } get isValid() { return this.results.length === 0; } add = (...rs) => toResults(...this.results, ...parse(...rs)); }; var toResults = (...r) => new Results(...r); var isResults = (r) => isDefined(r) && r instanceof Results; // src/types/Value.ts var Value = class { constructor(value) { this.value = value; this.value = value; } get isValid() { return isDefined(this.value); } toJSON() { return this.value; } toString() { return asString(this.value); } }; var isValue = (v) => v instanceof Value; // src/types/Validatable.ts var isValidatable = (v) => isA(v, "isValid"); // src/validation/Validate.ts var asResults = (subject, template2, options = {}) => toResults(toResult(text(template2).parse(subject, options), toName(subject))); var validators = (subject) => meta(subject).keys("constraint").reduce((list, vs) => list.add(vs), toList()); var runValidator = (v, subject) => { try { const actual = isFunction(subject[v.property]) ? subject[v.property]() : subject[v.property]; const constraint2 = v.constraint(actual); return isResults(constraint2) ? constraint2 : !constraint2 ? asResults(subject, v.text, { ...v, actual }) : toResults(); } catch (e) { return asResults(subject, asString(e)); } }; var constraints = (subject) => validators(subject).map((vs) => runValidator(vs, subject)).reduce((rs, r) => rs.add(...r.results), toResults()); var validate = (subject) => choose(subject).is.not.defined( (s) => s, () => toResults("Subject is not defined.") ).type(isEnum, (e) => e.isValid ? toResults() : asResults(e, "This is not a valid {type}.")).type(isValue, (v) => v.isValid ? toResults() : asResults(v, "This is not a valid {type}.")).type(isArray, (a) => a.map((i) => validate(i)).reduce((rs, r) => rs.add(...r.results), toResults())).type(isValidatable, (v) => constraints(v)).else(toResults()); var validateReject = (subject) => when(subject).not.isValid.reject(); var isValid = (t) => validate(t).isValid; // src/types/Try.ts var Try = class _Try { is = { defined: (prop) => this.filter((v) => isDefined(prop ? prop(v) : v)), empty: (prop) => this.filter((v) => isEmpty(prop ? prop(v) : v)), valid: (prop) => this.filter((v) => validate(prop ? prop(v) : v).isValid), true: (prop) => this.filter((v) => isTrue(prop ? prop(v) : v)), false: (prop) => this.filter((v) => !isTrue(prop ? prop(v) : v)), not: { defined: (prop) => this.filter((v) => !isDefined(prop ? prop(v) : v)), empty: (prop) => this.filter((v) => !isEmpty(prop ? prop(v) : v)), valid: (prop) => this.filter((v) => !validate(prop ? prop(v) : v).isValid) } }; if = this.is; static of = (c, ...args) => { try { const out = ofGet(c, ...args); return new Success(out instanceof _Try ? out.value : out); } catch (e) { return new Failure(e); } }; }; var Success = class extends Try { constructor(value) { super(); this.value = value; } get error() { throw new Error("No error found"); } get isValid() { return true; } map(f) { return tryTo(f, this.value); } recover(f) { return this; } recoverFrom(type, f) { return this; } accept(f) { return tryTo(() => { f(this.value); return this; }); } filter(predicate) { return tryTo(() => { if (predicate(this.value)) return this; throw new Error(`Applying filter(${predicate.toString()}) failed.`); }); } or(value) { return this.value; } orElse(value) { return this.value; } orThrow(_error) { return this.value; } }; var Failure = class _Failure extends Try { constructor(error) { super(); this.error = error; } get value() { throw this.error; } get isValid() { return false; } map(f) { return new _Failure(this.error); } recover(f) { return tryTo(f, this.error); } recoverFrom(type, f) { return tryTo(() => this.error instanceof type ? this.recover(f) : this); } accept(f) { return this; } filter(predicate) { return this; } or(value) { return ofGet(value); } orElse(value) { return ofGet(value); } orThrow(error) { throw ofConstruct(error); } }; var tryTo = (c, ...args) => Try.of(c, ...args); // src/types/Case.ts var CaseBuilder = class { constructor(v) { this.v = v; } case(pred, out) { return new Case(this.v).case(pred, out); } type(guard, out) { return new Case(this.v).type(guard, out); } equals(value, out) { return new Case(this.v).equals(value, out); } is = { defined: (prop, out) => new Case(this.v).case(isDefined(prop(this.v)), out), empty: (prop, out) => new Case(this.v).case(isEmpty(prop(this.v)), out), valid: (prop, out) => new Case(this.v).case(validate(prop(this.v)).isValid, out), not: { defined: (prop, out) => new Case(this.v).case(!isDefined(prop(this.v)), out), empty: (prop, out) => new Case(this.v).case(!isEmpty(prop(this.v)), out), valid: (prop, out) => new Case(this.v).case(!validate(prop(this.v)).isValid, out) } }; if = this.is; }; var Case = class _Case { constructor(value, outcome) { this.value = value; this.outcome = outcome; } case(pred, out) { return tryTo(pred, this.value).is.true().map(() => ofGet(out, this.value)).map((res) => new Found(this.value, res)).or(this); } type(guard, out) { return tryTo(guard, this.value).is.true().map(() => out(this.value)).map((res) => new Found(this.value, res)).or(this); } equals(value, out) { return this.case(this.value === value, out); } is = { defined: (prop, out) => new _Case(this.value).case(isDefined(prop(this.value)), out), empty: (prop, out) => new _Case(this.value).case(isEmpty(prop(this.value)), out), valid: (prop, out) => new _Case(this.value).case(validate(prop(this.value)).isValid, out), not: { defined: (prop, out) => new _Case(this.value).case(!isDefined(prop(this.value)), out), empty: (prop, out) => new _Case(this.value).case(!isEmpty(prop(this.value)), out), valid: (prop, out) => new _Case(this.value).case(!validate(prop(this.value)).isValid, out) } }; if = this.is; else(alt) { return ofGet(alt, this.value); } }; var Found = class extends Case { constructor(value, outcome) { super(value, outcome); this.value = value; this.outcome = outcome; } case(pred, out) { return this; } type(guard, out) { return this; } equals(value, out) { return this; } is = { defined: (_prop, _out) => this, empty: (_prop, _out) => this, valid: (_prop, _out) => this, not: { defined: (_prop, _out) => this, empty: (_prop, _out) => this, valid: (_prop, _out) => this } }; if = this.is; else(alt) { return this.outcome; } }; var choose = (value) => new CaseBuilder(value); // src/types/PageList.ts var toFilter = (field, value) => toShortFilter(field, field, value); var toShortFilter = (field, shortField, value) => ({ field, shortField, values: [{ value }] }); var PageList = class extends List { _options; get options() { return this._options; } get take() { return this._options?.take ?? 250; } get skip() { return this._options?.skip ?? 0; } get total() { return this._options?.total; } get sorts() { return this._options?.sorts; } get filters() { return this._options?.filters; } get meta() { return { take: this.take, skip: this.skip, total: this.total, sorts: this.sorts, filters: this.filters }; } get ids() { return this.mapDefined((i) => i.id); } asc(p) { return toPageList(super.asc(p), this); } desc(p) { return toPageList(super.desc(p), this); } diff(others) { return toPageList(super.diff(others), this); } diffByKey(others, key) { return toPageList(super.diffByKey(others, key), this); } symmetricDiff(others) { return toPageList(super.symmetricDiff(others), this); } symmetricDiffByKey(others, key) { return toPageList(super.symmetricDiffByKey(others, key), this); } intersect(others) { return toPageList(super.intersect(others), this); } intersectByKey(others, key) { return toPageList(super.intersectByKey(others, key), this); } map(f, params) { const items = super.map(f, params); return toPageList(items, this); } flatMap(f, params) { return toPageList(super.flatMap(f, params), this); } mapDefined(f, params) { return toPageList(super.mapDefined(f, params), this); } mapAsync(f) { return super.mapAsync(f).then((r) => toPageList(r, this)); } areEqual(...items) { return this.isSubSetOf(...items) && toList(...items).isSubSetOf(...this); } distinct() { return toPageList(super.distinct(), this); } distinctByKey(key) { return toPageList(super.distinctByKey(key), this); } distinctByValue() { return toPageList(super.distinctByValue(), this); } filter(p, params) { return toPageList(super.filter(p, params), this); } accumulate(...keys2) { return toPageList(super.accumulate(...keys2), this); } concat(...items) { return toPageList(super.concat(...items), this); } reverse() { return toPageList(super.reverse(), this); } splice(start, deleteCount, ...items) { return toPageList(super.splice(start, deleteCount, ...items), this); } remove(item) { return toPageList(super.remove(item), this); } replace(key, item) { return toPageList(super.replace(key, item), this); } switch(item) { return toPageList(super.switch(item), this); } defined() { return toPageList(super.defined(), this); } orElse(...alt) { return toPageList(super.orElse(...alt), this); } slice(start, end) { return toPageList(super.slice(start, end), this); } //we needed to add U because of a Typescript issue with generics update(p, val) { return toPageList(super.update(p, val), this); } updateFirst(p, val) { return toPageList(super.updateFirst(p, val), this); } updateFirstById(id, val) { return toPageList(super.updateFirstById(id, val), this); } updateById(id, val) { return toPageList(super.updateById(id, val), this); } setPageOptions(options) { this._options = options; return this; } }; var isPageList = (l) => isList(l) && isA(l, "total"); var toPageList = (items = [], options) => choose(items).case( (i) => i.length === 1 && isNumber(i[0]), (i) => new PageList().add(...i) ).else((i) => new PageList(...i)).setPageOptions(options); var asPageList = (c, items = toPageList()) => items.map((i) => ofConstruct(c, i)); // src/data/InMemoryGateway.ts var InMemoryGateway = class extends Gateway { constructor(data) { super(); this.data = data; } all(options) { return this.data.then((d) => toPageList(d, d)); } byId(id) { return this.data.then((d) => d.byId(id)).then((d) => d ? { ...d } : void 0); } by = (key, value) => { return this.data.then((d) => d.filter((i) => i[key] === value)); }; exists(id) { return this.byId(id).then((d) => isDefined(d)); } add(item) { return when(item).not.contains((i) => i.id).reject(Exception.IsMissingId).then((i) => this.exists(i.id)).then((ex) => when(ex).isTrue.reject(Exception.AlreadyExists)).then(() => this.data.then((d) => d.add(item))).then(() => ({ ...item })); } remove(id) { return this.data.then( (d) => when(d.findIndex((i) => i.id === id)).with((i) => i < 0).reject(Exception.DoesNotExist).then((i) => d.splice(i, 1)) ).then(() => true); } update(item) { return when(item).not.contains((i) => i.id).reject(Exception.IsMissingId).then((i) => this.remove(i.id).then(() => this.add(i))); } }; // src/data/Database.ts var DefaultProvider = class { }; var Database = class _Database extends Enum { constructor(name, provider, options) { super(name); this.provider = provider; this.options = options; } static Default = new _Database("Default", DefaultProvider); provide = () => ofConstruct(this.provider, this); }; // src/utils/Property.ts var Property = class { constructor(property, options) { this.property = property; this.options = options; this.options = { ...options, convert: options?.convert ?? convert.default }; } in = (source = {}) => this.options?.convert?.to(source[this.property] ?? ofGet(this.options?.dflt)); out = (source = {}, key = "") => this.options?.convert?.from(source[key]); toString