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