UNPKG

lakutata

Version:

An IoC-based universal application framework.

496 lines (434 loc) 14.9 kB
"use strict"; const e = require("./Package.1.cjs"); const t = require("../src/lib/base/async-constructor/AsyncConstructor.cjs"); const s = require("../src/decorators/di/Lifetime.cjs"); const r = require("../src/exceptions/MethodNotFoundException.cjs"); const i = require("../src/lib/ioc/DependencyInjectionContainer.cjs"); const o = require("node:crypto"); const n = require("../src/lib/base/internal/ConfigurableRecordsInjection.cjs"); const a = require("../src/lib/base/internal/ObjectConfiguration.cjs"); const c = require("../src/lib/base/internal/ObjectInjection.cjs"); const l = require("../src/lib/base/internal/ObjectContainer.cjs"); const d = require("./Package.2.cjs"); const h = require("../src/lib/helpers/ObjectConstructor.cjs"); const u = require("../src/lib/helpers/As.cjs"); const p = require("../src/lib/helpers/DevNull.cjs"); const b = require("../src/lib/helpers/ObjectParentConstructors.cjs"); const y = require("../src/exceptions/di/DependencyInjectionException.cjs"); const O = require("../src/lib/base/internal/ConstructorSymbol.cjs"); const m = require("../src/decorators/dto/Expect.cjs"); const f = require("../src/decorators/dto/IndexSignature.cjs"); const j = require("../src/lib/ioc/Resolvers.cjs"); const g = require("../src/lib/base/internal/ObjectLifetime.cjs"); const w = require("../src/decorators/dto/Accept.cjs"); const C = require("../src/lib/ioc/ListModules.cjs"); const P = require("url"); const S = require("../src/lib/ioc/Utils.cjs"); const T = require("../src/lib/helpers/IsEmptyObject.cjs"); const R = require("../src/lib/base/internal/ObjectWeakRefs.cjs"); var x; const I = Symbol("OBJECT_ID"); exports.LoadObjectOptions = class LoadObjectOptions extends d.DTO { static { x = I; } }; e.__decorate([ m.Expect(d.DTO.Alternatives(d.DTO.String(), d.DTO.Symbol()).optional()), e.__metadata("design:type", Object) ], exports.LoadObjectOptions.prototype, x, void 0); e.__decorate([ m.Expect(d.DTO.Class((() => exports.BaseObject)).required()), e.__metadata("design:type", Object) ], exports.LoadObjectOptions.prototype, "class", void 0); exports.LoadObjectOptions = e.__decorate([ f.IndexSignature(d.DTO.Any()) ], exports.LoadObjectOptions); const A = Symbol("LAKUTATA.DI.CONTAINER.SYMBOL"); const N = Symbol("LAKUTATA.DI.OWNER.SYMBOL"); class Container { #e; #t; #s; constructor(e, t) { this.#t = new Set; this.#s = false; this.injectionNames = new Set; this.parent = e; this.#e = e ? e.#e.createScope() : i.createContainer({ injectionMode: "PROXY", strict: false }); if (this.parent) this.parent.#t.add(this); this.#e.register(A, j.asValue(this)); if (t) this.#e.register(N, j.asValue(new WeakRef(t))); } async disposer(e) { try { await e.getMethod(B, false)(); } catch (e) { p.DevNull(e); } } buildResolverOptions(e) { const t = g.GetObjectLifetime(e); return { lifetime: t, dispose: e => this.disposer(e) }; } async processResolved(e, t, s = {}) { const r = n.GetConfigurableRecords(u.As(e.constructor), t); const i = d.DTO.isValid(e.constructor, d.DTO.Class(exports.BaseObject)); if (i) { n.SetIdToInstance(u.As(e), t); n.SetConfigurableRecordsToInstance(u.As(e), { ...r, ...s }); } return Promise.resolve(e); } buildNameAndRegistrationPairFromOptions(e) { const t = {}; const s = e[I] ? e[I] : O.ConstructorSymbol(e.class); const r = { ...e, class: void 0 }; delete r.id; delete r.class; n.SetConfigurableRecords(e.class, s, r); t[s] = j.asClass(e.class, this.buildResolverOptions(e.class)); return t; } async buildNameAndRegistrationPairFromGlob(e) { const t = []; C.listModules(e).forEach((e => { t.push(new Promise((t => { import(P.pathToFileURL(e.path).toString()).then((e => { Object.keys(e).forEach((s => { const r = e[s]; if (S.isClass(r) && d.DTO.isValid(r, d.DTO.Class(exports.BaseObject))) { const e = r; const s = {}; s[O.ConstructorSymbol(e)] = j.asClass(e, this.buildResolverOptions(e)); return t(s); } else { return t({}); } })); })).catch((() => t({}))); }))); })); const s = await Promise.all(t); let r = {}; s.forEach((e => { r = { ...r, ...e }; })); return r; } owner() { const e = this.#e.resolve(N, { allowUnregistered: true }); return e ? e.deref() : undefined; } async load(e) { let t = {}; const s = []; e.forEach((e => { if (typeof e === "string") { s.push(new Promise(((t, s) => this.buildNameAndRegistrationPairFromGlob(e).then(t).catch(s)))); } else if (S.isClass(u.As(e))) { const s = { class: u.As(e) }; t = { ...t, ...this.buildNameAndRegistrationPairFromOptions(s) }; } else { const s = u.As(e); t = { ...t, ...this.buildNameAndRegistrationPairFromOptions(s) }; } })); if (s.length) { const e = await Promise.all(s); e.forEach((e => { t = { ...e, ...t }; })); } if (!T.IsEmptyObject(t)) { Object.getOwnPropertyNames(t).forEach((e => this.injectionNames.add(e))); Object.getOwnPropertySymbols(t).forEach((e => this.injectionNames.add(e))); this.#e.register(t); } } async get(e, t = {}) { const s = typeof e === "function" ? O.ConstructorSymbol(e) : e; if (!this.#e.hasRegistration(s) && typeof e === "function" && c.GetObjectIsAutoload(u.As(e))) { await this.load([ { id: s, class: u.As(e) } ]); } return (this.#e.getRegistration(s)?.lifetime === "SINGLETON" || this.#e.getRegistration(s)?.lifetime === "MODULE_SINGLETON") && !this.injectionNames.has(s) && this.parent ? await this.parent.get(s, t) : await this.processResolved(this.#e.resolve(s), s, t); } has(e) { if (typeof e === "function") return this.#e.hasRegistration(O.ConstructorSymbol(e)); return this.#e.hasRegistration(e); } async set(e, t = {}) { await this.load([ { ...t, class: e } ]); return await this.get(e); } async setNamed(e, t, s = {}) { await this.load([ { ...s, class: t, [I]: e } ]); return await this.get(e); } async register(e, t = {}) { await this.load([ { ...t, class: e } ]); } async registerNamed(e, t, s = {}) { await this.load([ { ...s, class: t, [I]: e } ]); } async build(e, t = {}) { const s = await this.processResolved(this.#e.build(e, this.buildResolverOptions(e)), O.ConstructorSymbol(e), t); R.AppendObjectWeakRefs(this.#e, s); return s; } createScope() { return new Container(this, this.owner()); } registerContainerToItsParent() { if (this.parent) this.parent.#t.add(this); } async clear() { const e = []; this.#t.forEach((t => e.push(new Promise(((e, s) => t.destroy().then(e).catch(s)))))); await Promise.all(e); await this.#e.dispose(); const t = []; R.GetObjectWeakRefs(this.#e).forEach((e => { let s = e.deref(); if (!s) return; if (s[B]) { t.push(new Promise((e => s ? Promise.resolve(s[B]()).then((() => { s = undefined; return e(); })).catch(p.DevNull) : e()))); } })); await Promise.all(t); R.ClearObjectWeakRefs(this.#e); } async destroy() { if (this.#s) return; this.#s = true; if (this.parent) this.parent.#t.delete(this); await this.clear(); } } e.__decorate([ w.Accept(d.DTO.Array(d.DTO.Alternatives(exports.LoadObjectOptions.Schema(), d.DTO.Class((() => exports.BaseObject)), d.DTO.Glob()))), e.__metadata("design:type", Function), e.__metadata("design:paramtypes", [ Array ]), e.__metadata("design:returntype", Promise) ], Container.prototype, "load", null); const _ = Symbol("OBJECT.TYPE"); exports.ObjectType = void 0; (function(e) { e["Unknown"] = "Unknown"; e["Object"] = "Object"; e["Provider"] = "Provider"; e["Controller"] = "Controller"; e["Component"] = "Component"; e["Module"] = "Module"; })(exports.ObjectType || (exports.ObjectType = {})); function D(e) { return t => v(t, e); } function v(e, t) { Reflect.defineMetadata(_, d.DTO.isValid(e, d.DTO.Class(exports.BaseObject)) ? t : exports.ObjectType.Unknown, e); return e; } function E(e) { if (Reflect.hasOwnMetadata(_, e)) return Reflect.getOwnMetadata(_, e); let t = exports.ObjectType.Unknown; for (const s of b.ObjectParentConstructors(e)) { if (Reflect.hasOwnMetadata(_, s)) { t = Reflect.getOwnMetadata(_, s); break; } } v(e, t); return E(e); } var q; var M; const L = Symbol("__init"); const B = Symbol("__destroy"); const G = Symbol("anonymous"); const k = Symbol("OBJECT.SYMBOL.PROPERTY"); exports.BaseObject = M = class BaseObject extends t.AsyncConstructor { #r; #i; #o=o.randomUUID(); #n=false; async #a() { const e = n.GetConfigurableRecordsFromInstance(this); const t = []; a.GetObjectConfigurableProperties(this).forEach(((s, r) => { if (d.IsSymbol(r)) return; t.push(new Promise(((t, i) => { d.DTO.validateAsync(e[u.As(r)], s.schema, { targetName: r }).then((e => Promise.resolve(s.fn.bind(this)(e)).then((e => { this[r] = e; return t(); })).catch(i))).catch(i); }))); })); await Promise.all(t); } async #c() { const e = c.GetObjectInjectItemsByPrototype(this); const t = []; e.forEach(((e, s) => { const r = e.name; t.push(new Promise(((t, i) => { this.#r.get(r).then((r => { Promise.resolve(e.transform(r)).then((e => { Reflect.set(this, s, e); return t(); })).catch(i); })).catch((e => i(new y.DependencyInjectionException("Unable to inject value for property {0} of {1} because: {2}", [ s, this.className, e.message ])))); }))); })); await Promise.all(t); } #l() { const e = n.GetIdFromInstance(this); this.#i = e ? e : G; } constructor(e) { super((async () => { this.#l(); const e = Object.getOwnPropertyDescriptor(this, "then"); if (e) Object.defineProperty(this, "then", { enumerable: false }); await this[L](); })); this.#r = new Container(e[A], this); l.SetObjectContainerGetter(this, this.#r); } static get className() { return this.name; } get className() { return h.ObjectConstructor(this).name; } async [L](...e) { this.#r.registerContainerToItsParent(); if (!this.#n) { await this.#c(); await this.#a(); this.#n = true; } for (const t of e) await t(); await this.init(); } async [B](...e) { await this.#r.destroy(); for (const t of e) await t(); await this.destroy(); } async init() {} async destroy() {} async getObject(e, t = {}) { return await this.#r.get(e, t); } async buildObject(e, t = {}) { return this.#r.build(e, t); } getParent() { return this.#r.parent?.owner(); } getModule() { let e = this.getParent(); while (e && E(u.As(h.ObjectConstructor(e))) !== exports.ObjectType.Module) { e = this.getParent(); } return u.As(e); } get $uuid() { return this.#o; } get $id() { return this.#i; } get $symbol() { if (Reflect.hasOwnMetadata(k, this)) return Reflect.getOwnMetadata(k, this); Reflect.defineMetadata(k, Symbol(this.$uuid), this); return this.$symbol; } setProperty(e, t) { this[e] = t; } getProperty(e, t) { if (this.hasProperty(e)) return u.As(this[e]); return u.As(t); } hasProperty(e) { return typeof e === "string" ? this.propertyNames().includes(e) : this.propertySymbols().includes(e); } propertySymbols() { return Object.getOwnPropertySymbols(this); } propertyNames() { return Object.getOwnPropertyNames(this); } hasMethod(e) { const t = this.hasProperty(e); if (t) return false; return typeof this[e] === "function"; } getMethod(e, t = false) { if (this.hasMethod(e)) { return (...t) => this[e](...t); } else if (t) { throw new r.MethodNotFoundException('Method "{methodName}" not found in "{className}"', { methodName: e, className: this.constructor.name }); } else { return (...e) => p.DevNull(...e); } } async dispose() { await this.destroy(); } }; exports.BaseObject = M = e.__decorate([ s.Transient(), D(exports.ObjectType.Object), e.__metadata("design:paramtypes", [ Object ]) ], exports.BaseObject); exports.Container = Container; exports.DefineObjectType = D; exports.GetObjectType = E; exports.OBJECT_ID = I; exports.SetObjectType = v; exports.__destroy = B; exports.__init = L; exports.anonymousId = G; exports.containerSymbol = A; exports.ownerSymbol = N;