assemblerjs
Advanced tools
Comparing version
@@ -51,6 +51,6 @@ /** | ||
abstract register<T>(injection: Injection<T>, instance?: boolean): Injectable<T>; | ||
abstract use<T>(identifier: string | Symbol, object: T): T; | ||
abstract use<T>(identifier: string | symbol, object: T): T; | ||
abstract prepareInitHook<T = AbstractAssemblage>(instance: T, configuration?: Record<string, any>): unknown[]; | ||
abstract has<T>(identifier: Identifier<T>): boolean; | ||
abstract require<T>(identifier: Identifier<T> | string | Symbol): T; | ||
abstract require<T>(identifier: Identifier<T> | string | symbol): T; | ||
abstract concrete<T>(identifier: Identifier<T>): Concrete<T> | undefined; | ||
@@ -75,3 +75,3 @@ abstract tagged(...tags: string[]): any[]; | ||
abstract readonly publicContext: AssemblerContext; | ||
abstract readonly identifier: Identifier<T> | string | Symbol; | ||
abstract readonly identifier: Identifier<T> | string | symbol; | ||
abstract readonly concrete: Concrete<T>; | ||
@@ -93,2 +93,17 @@ abstract readonly configuration: Record<string, any>; | ||
/** | ||
* An abstract class for `ListenerCollection` implementation. | ||
*/ | ||
export declare abstract class AbstractListenerCollection { | ||
[key: EventChannel]: any; | ||
abstract listeners: Listener[]; | ||
abstract channels: EventChannel[]; | ||
abstract add(channel: EventChannel, listener: Listener): AbstractListenerCollection; | ||
abstract remove(channel: EventChannel, listener?: Listener): AbstractListenerCollection; | ||
abstract has(...args: (EventChannel | Listener)[]): boolean; | ||
abstract get(...args: (EventChannel | Listener)[]): (EventChannel | Listener)[]; | ||
abstract clear(): AbstractListenerCollection; | ||
abstract [Symbol.iterator](): Iterator<EventChannel>; | ||
} | ||
/** | ||
* Generic `Array` items. | ||
@@ -132,3 +147,3 @@ */ | ||
protected injectables: Map<Identifier<unknown>, Injectable<unknown>>; | ||
protected objects: Map<string | Symbol, unknown>; | ||
protected objects: Map<string | symbol, unknown>; | ||
private initCache; | ||
@@ -184,3 +199,3 @@ /** | ||
*/ | ||
use<T>(identifier: string | Symbol, object: T): T; | ||
use<T>(identifier: string | symbol, object: T): T; | ||
/** | ||
@@ -199,6 +214,6 @@ * Cache an instaance to be inited with `onInit` hook | ||
* @param { Identifier<T> | string | symbol } identifier An abstract or concrete class, | ||
* or a string or Symbol as identifier. | ||
* or a string or symbol as identifier. | ||
* @returns { boolean } `true` if dependency has been registered. | ||
*/ | ||
has<T>(identifier: Identifier<T> | string | Symbol): boolean; | ||
has<T>(identifier: Identifier<T> | string | symbol): boolean; | ||
/** | ||
@@ -210,3 +225,3 @@ * Get or instantiate an assemblage for given identifier. | ||
*/ | ||
require<T>(identifier: Identifier<T> | string | Symbol): T; | ||
require<T>(identifier: Identifier<T> | string | symbol): T; | ||
/** | ||
@@ -361,3 +376,3 @@ * Return a `Concrete` class for given identifier. | ||
*/ | ||
export declare const decorateUse: (identifier: string | Symbol, target: any, index: number) => void; | ||
export declare const decorateUse: (identifier: string | symbol, target: any, index: number) => void; | ||
@@ -374,2 +389,12 @@ /** | ||
/** | ||
* `EventChannel` extends `string`. | ||
*/ | ||
export declare type EventChannel = string; | ||
/** | ||
* Describes a list of event channels as Record<EventChannel, string> | ||
*/ | ||
export declare type EventChannelList = Record<EventChannel, string>; | ||
export declare class EventManager implements AbstractEventManager { | ||
@@ -401,3 +426,3 @@ private readonly listeners; | ||
readonly publicContext: AssemblerContext; | ||
readonly identifier: Identifier<T> | string | Symbol; | ||
readonly identifier: Identifier<T> | string | symbol; | ||
readonly concrete: Concrete<T>; | ||
@@ -462,3 +487,3 @@ readonly configuration: Record<string, any>; | ||
*/ | ||
declare type InstanceInjection<T> = Tuple<[Identifier<T> | string | Symbol, T]>; | ||
declare type InstanceInjection<T> = Tuple<[Identifier<T> | string | symbol, T]>; | ||
@@ -476,4 +501,93 @@ /** | ||
*/ | ||
declare type Listener = (...args: any[]) => void | Promise<void>; | ||
export declare type Listener = (...args: any[]) => void | Promise<void>; | ||
export declare class ListenerCollection implements AbstractListenerCollection { | ||
/** | ||
* Class is indexable by `EventChannel`. | ||
*/ | ||
[key: string]: Listener[] | any; | ||
/** | ||
* Internal listeners `Object`. | ||
*/ | ||
readonly collection: Record<EventChannel, Array<Listener>>; | ||
constructor(); | ||
/** | ||
* Clean up the collection by removing all listeners and channels | ||
* and deleting listeners private property. | ||
*/ | ||
dispose(): void; | ||
/** | ||
* Add a listener to the collection. | ||
* | ||
* @param { EventChannel } channel The channel to add the listener to. | ||
* @param { Listener } listener The callback function to run when the event is emitted. | ||
* @returns { ListenerCollection } This collection. | ||
*/ | ||
add(channel: EventChannel, listener: Listener): ListenerCollection; | ||
/** | ||
* Add a listener to the collection. | ||
* | ||
* @param { Tuple<EventChannel, Listener> } tuple The channel and its listener in a tuple. | ||
* @returns { ListenerCollection } This collection. | ||
*/ | ||
add(tuple: Tuple<[EventChannel, Listener]>): ListenerCollection; | ||
/** | ||
* Removes a listener or all listeners for a given channel. | ||
* If the channel or the provided listener does not exist, fails silently. | ||
* | ||
* @param { EventChannel } channel The channel the listener is listening to. | ||
* @param { Listener } listener The listener to remove. If not provided, remove all listeners for given channel. | ||
* @returns { ListenerCollection } This collection. | ||
*/ | ||
remove(channel: string, listener?: Listener): ListenerCollection; | ||
/** | ||
* Checks if the collection includes a specific channel or listener. | ||
* | ||
* @param { EventChannel | Listener } value The channel or the listener to find in the collection. | ||
* @returns { boolean } true if the collection includes this channel / this listener, | ||
* false if not. | ||
*/ | ||
has(value: EventChannel): boolean; | ||
has(value: Listener): boolean; | ||
/** | ||
* Get a specific channel listeners array or a specific listener channels array. | ||
* | ||
* @param { EventChannel | Listener } value The channel or the listener to find in the collection. | ||
* @returns { EventChannel[] | Listener[] } An array of channels or listeners. | ||
*/ | ||
get(value: EventChannel): Listener[]; | ||
get(value: Listener): EventChannel[]; | ||
/** | ||
* Clear the entire collction. | ||
* | ||
* @returns { ListenerCollection } This collection. | ||
*/ | ||
clear(): ListenerCollection; | ||
/** | ||
* The listeners of this collection flatten in a single array. | ||
*/ | ||
get listeners(): Listener[]; | ||
/** | ||
* The listeners collection channels. | ||
*/ | ||
get channels(): EventChannel[]; | ||
/** | ||
* Returns the total listeners length. | ||
*/ | ||
get length(): number; | ||
/** | ||
* Allows iterating over listeners in specific channel with 'for... of...' loop. | ||
* | ||
* @returns { Listener } A listener function. | ||
* | ||
* @example | ||
* // Iterates listeners in a specific channel. | ||
* for (const listener of myListenerCollection) { | ||
* // Calls the registered listener. | ||
* listener(); | ||
* } | ||
*/ | ||
[Symbol.iterator](): Iterator<EventChannel>; | ||
} | ||
declare interface ParametersDecoratorsIndexes { | ||
@@ -515,6 +629,6 @@ Context: number[]; | ||
/** | ||
* Injects an object passed with `string` or `Symbol` identifier. | ||
* Injects an object passed with `string` or `symbol` identifier. | ||
*/ | ||
export declare const Use: (identifier: string | Symbol) => ParameterDecorator; | ||
export declare const Use: (identifier: string | symbol) => ParameterDecorator; | ||
export { } |
@@ -1,1 +0,921 @@ | ||
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="design:paramtypes";var t=function(e){return e.IsAssemblage="is_assemblage",e}({}),n=function(e){return e.AssemblageDefinition="assemblage:definition.value",e}({});const s=(...e)=>{},i=(...e)=>t=>{if(e.includes(typeof t))return typeof t},r=e=>!(e=>void 0===e)(e)&&!(e=>null===e)(e),o=e=>e&&"function"==typeof e&&void 0!==e.constructor,c=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,a=(e,...t)=>{t.map(((e,n)=>{const s=/\S/.test(e);return s&&(t[n]=t[n].trim()),s?-1:n})).filter((e=>e>=0)).every((e=>{t[e]=" ",((e,t,n)=>{const s=e[t];e.splice(t,1),e.splice(n,0,s)})(t,e,t.length-1)})),t=(e=>Array.from(new Set(e)))(t);const n=new RegExp(`[^A-Za-zĆ-ĆĆ-öø-Ćæ0-9${t.join("")}]`,"gi");return e.replace(n,"")},l=(...e)=>t=>e.reduce(((e,t)=>t(e)),t),h=e=>t=>e.if(t)?e.then(t):e.else?e.else(t):void 0,u=e=>t=>{const n=Array.isArray(e)?e=>parseInt(e):s;for(const[s,i]of Object.entries(e))t(i,n(s))},f=(e,t)=>{const n=new Proxy(e,{get:function(n,s){return s===Symbol.iterator?n[Symbol.iterator].bind(n):((e,t)=>[...Object.getOwnPropertyNames(t.prototype),...Object.getOwnPropertyNames(Object.getPrototypeOf(e)),...Object.getOwnPropertyNames(e)])(e,t).includes(s)?n[s]:n.collection[s]},set:function(e,t,n){return Reflect.set(e,t,n)}});return n},d=(e,t)=>{const n=e;for(const s of((e,t)=>[...Object.getOwnPropertyNames(t.prototype),...Object.getOwnPropertyNames(Object.getPrototypeOf(e)),...Object.getOwnPropertyNames(e)])(e,t))delete n[s]},p=(e,t,n)=>{Reflect.defineMetadata(`__${e}__`,t,n)},g=(e,t)=>Reflect.getOwnMetadata(`__${e}__`,t),b=t=>Reflect.getMetadata(e,t)||[],m=e=>g(t.IsAssemblage,e)||!1,y={singleton:{test:e=>"boolean"==typeof e||void 0===e,throw:()=>{throw new Error("'singleton' property must be of type 'boolean' or 'undefined'.")},transform:e=>void 0===e||!!e},events:{test:e=>void 0===e||Array.isArray(e)&&e.every((e=>"string"==typeof e)),throw:()=>{throw new Error("'events' property must be an array of strings or 'undefined'.")},transform:e=>e},inject:{test:e=>void 0===e||Array.isArray(e)&&e.every((e=>Array.isArray(e)&&e.length>=1&&e.length<=3)),throw:()=>{throw new Error("'inject' property must be an array of tuples of length 1, 2 or 3.")},transform:e=>e},use:{test:e=>void 0===e||Array.isArray(e)&&e.every((e=>Array.isArray(e)&&2==e.length)),throw:()=>{throw new Error("'use' property must be an array of tuples of length 2.")},transform:e=>e},tags:{test:e=>void 0===e||"string"==typeof e||Array.isArray(e)&&e.every((e=>"string"==typeof e)),throw:()=>{throw new Error("'tags' property must be a string or an array of strings.")},transform:e=>"string"==typeof e?[e]:e},metadata:{test:e=>("object"==typeof e||void 0===e)&&!Array.isArray(e),throw:()=>{throw new Error("'metadata' property must be of type 'object' or 'undefined'.")},transform:e=>e}},v=e=>{const t={...e};for(const n in t)if(!Object.keys(y).includes(n))throw new Error(`Property '${n}' is not a valid assemblage definition property.`);for(const n in y){const e=y[n].test,s=y[n].throw,i=y[n].transform;e(t[n])||s(),t[n]=i(t[n])}return t},C=e=>{if(!m(e))throw new Error(`Class '${e.name}' is not an assemblage.`);return g(n.AssemblageDefinition,e)},w=(e,t)=>C(t)[e],x=e=>{const t=()=>o(e[0])&&(e=>"object"==typeof e&&!Array.isArray(e)&&!o(e))(e[1]);return l(h({if:()=>o(e[0])&&o(e[1]),then:()=>({identifier:e[0],concrete:e[1],configuration:{}})}),h({if:()=>t(),then:()=>({identifier:e[0],concrete:e[0],configuration:e[1]}),else:e=>e}))()},j=(e,s)=>{const i=v(s||{});return p(t.IsAssemblage,!0,e),p(n.AssemblageDefinition,i,e),e};let A=Symbol.iterator;class I{dispose(){d(this,I)}add(...e){const t=e=>this.collection[e.channel].push(e.listener),n=h({if:()=>2===e.length,then:()=>({channel:e[0],listener:e[1]}),else:()=>{const t=e[0];return{channel:t[0],listener:t[1]}}}),s=h({if:e=>!r(this.collection[e.channel]),then:e=>{this.collection[e.channel]=[],t(e)},else:e=>{t(e)}});return l(n,s)(),this}remove(e,t){const n=t=>this.collection[e].splice(t,1),s=h({if:()=>this.collection[e]&&0===this.collection[e].length,then:()=>delete this.collection[e]}),i=h({if:()=>r(t),then:()=>n(this.collection[e].indexOf(t)),else:()=>delete this.collection[e]}),o=h({if:e=>this.has(e),then:e=>this.collection[e]});return l(o,i,s)(),this}has(...e){return i("string")(e[0])?Object.keys(this.collection).includes(e[0]):!!i("function")(e[0])&&Object.values(this.collection).flat().includes(e[0])}get(...e){return i("string")(e[0])?this.collection[e[0]]:i("function")(e[0])?Object.values(this.collection).flat().filter((t=>t===e[0])):[]}clear(){const e=(e=>t=>{const n=Array.isArray(e)?e=>parseInt(e):e=>e;for(const s in e)t(n(s))})(this.collection),t=e=>u(this.collection[e])((t=>this.remove(e,t)));return e((e=>t(e))),this}get listeners(){return Object.values(this.collection).flat()}get channels(){return Object.keys(this.collection)}get length(){return Object.values(this.collection).flat().length}[A](){let e=-1;const t=this.collection?Object.keys(this.collection):[];return{next:()=>({value:t[++e],done:!(e in t)})}}constructor(){!function(e,t,n){t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}(this,"collection",{});return f(this,I)}}class O{}function D(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class P{dispose(){this.listeners.dispose(),this.channels.clear(),d(this,P)}addChannels(...e){return u(e)((e=>{const t=this.cleanChannel(e);if(this.channels.has(t))throw new Error(`Channel '${t}' already exists.`);this.channels.add(t)})),this}removeChannels(...e){return u(e)((e=>{const t=this.cleanChannel(e);"*"!==t&&this.channels.has(t)&&(this.channels.delete(t),this.listeners.remove(t),this.onceListeners.remove(t))})),this}on(e,t){const n=this.cleanChannel(e);if(!this.channels.has(n))throw new Error(`Channel '${n}' was not registered.`);return this.listeners.add(n,t),this}once(e,t){const n=this.cleanChannel(e);if(!this.channels.has(n))throw new Error(`Channel '${n}' was not registered.`);return this.onceListeners.add(n,t),this}off(e,t){const n=this.cleanChannel(e);return this.listeners.remove(n,t),this}emit(e,...t){const n=this.cleanChannel(e);if(this.channels.has(n)){const e=this.onceListeners.get("*")||[],s=this.listeners.get("*")||[],i=this.onceListeners.get(n)||[],r=this.listeners.get(n)||[],o=u(e),c=u(s),a=u(i),l=u(r);o((e=>{this.run(e,...t),this.onceListeners.remove("*",e)})),c((e=>{this.run(e,...t)})),a((e=>{this.run(e,...t),this.onceListeners.remove(n,e)})),l((e=>{this.run(e,...t)}))}return this}run(e,...t){if(c(e)){return e(...t).then((()=>Promise.resolve()))}e(...t)}cleanChannel(e){return a(e,"*")}constructor(...e){D(this,"listeners",new I),D(this,"onceListeners",new I),D(this,"channels",new Set(["*"])),this.addChannels(...e)}}var E=function(e){return e.UseIdentifier="assemblage:use.param.value",e}({}),U=function(e){return e.Context="assembler:context.param.index",e.Dispose="assembler:dispose.param.index",e.Definition="assemblage:definition.param.index",e.Configuration="assemblage:configuration.param.index",e.Use="assemblage:use.param.index",e}({});const S=e=>()=>(t,n,s)=>{const i=g(e,t)||[];i.push(s),p(e,i,t)},$=S(U.Context),R=S(U.Configuration),M=S(U.Definition),_=S(U.Dispose),k=(e,t,n)=>{const s=g(U.Use,t)||[];s.push(n),p(U.Use,s,t);const i=g(E.UseIdentifier,t)||{};i[n]=e,p(E.UseIdentifier,i,t)},L=e=>{const t=(e=>g(U.Context,e)||[])(e),n=(e=>g(U.Definition,e)||[])(e),s=(e=>g(U.Configuration,e)||[])(e),i=(e=>g(U.Dispose,e)||[])(e),r=(e=>g(U.Use,e)||[])(e);return{Context:t,Definition:n,Configuration:s,Dispose:i,Use:r}},q=(t,s=!0)=>i=>{const r=class extends i{constructor(...e){super(...e),t&&t.call(this)}};if(Object.defineProperty(r,"name",{value:i.name}),!s)return r;const o=Reflect.getOwnMetadata(e,i)||[],c=L(i),a=[];for(let e=0;e<o.length;e++)if(c.Context.includes(e)){const t=g(U.Context,i)||[];t.push(e),p(U.Context,t,r)}else if(c.Definition.includes(e)){const t=g(U.Definition,i)||[];t.push(e),p(U.Definition,t,r)}else if(c.Configuration.includes(e)){const t=g(U.Configuration,i)||[];t.push(e),p(U.Configuration,t,r)}else if(c.Dispose.includes(e)){const t=g(U.Dispose,i)||[];t.push(e),p(U.Dispose,t,r),a.push(o[e])}else if(c.Use.includes(e)){const t=g(E.UseIdentifier,i);k(t[e],r,e)}else;return s?j(r,g(n.AssemblageDefinition,i)):r};function N(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class H{static of(e,t,n){return new H(e,t,n)}dispose(){this.singletonInstance&&(((e,t)=>{if(e.concrete.prototype instanceof P){const n=t;for(const t of e.events)n.off(t);n.removeChannels(...e.events),e.privateContext.removeChannels(...e.events)}})(this,this.singletonInstance),z(this.singletonInstance,"onDispose",this.publicContext,this.configuration),d(this.singletonInstance,this.concrete)),d(this,H)}build(){if(this.singletonInstance)return this.singletonInstance;const e=(e=>{const t=[],n=b(e.concrete),s=L(e.concrete);let i=0;for(const r of n)if(s.Context.includes(i))t.push(e.publicContext),i++;else if(s.Configuration.includes(i))t.push(e.configuration),i++;else if(s.Definition.includes(i))t.push(e.definition),i++;else if(s.Dispose.includes(i))t.push(e.privateContext.dispose),i++;else if(s.Use.includes(i)){const n=g(E.UseIdentifier,e.concrete)[i];t.push(e.privateContext.require(n)),i++}else t.push(e.privateContext.require(r)),i++;return t})(this),t=new this.concrete(...e);return((e,t)=>{if(e.concrete.prototype instanceof P){const n=t,s=n.channels;for(const t of e.events)s.has(t)||n.addChannels(t),e.privateContext.events.has(t)||e.privateContext.addChannels(t);for(const i of e.events)t.on(i,((...t)=>{e.privateContext.emit(i,...t)}))}})(this,t),this.isSingleton?(this.singletonInstance=t,this.privateContext.prepareInitHook(t,this.configuration),this.singletonInstance):(z(t,"onInit",this.publicContext),t)}get dependencies(){return this.dependenciesIds}get definition(){return C(this.concrete)||{}}get isSingleton(){return w("singleton",this.concrete)}get singleton(){return this.singletonInstance}get injections(){return w("inject",this.concrete)||[]}get objects(){return w("use",this.concrete)||[]}get tags(){return w("tags",this.concrete)||[]}get events(){return w("events",this.concrete)||[]}constructor(e,t,n){if(N(this,"privateContext",void 0),N(this,"publicContext",void 0),N(this,"identifier",void 0),N(this,"concrete",void 0),N(this,"configuration",void 0),N(this,"dependenciesIds",void 0),N(this,"singletonInstance",void 0),this.privateContext=t,this.publicContext=n,this.dependenciesIds=[],this.identifier=e.identifier,this.concrete=e.concrete,this.configuration=e.configuration,!m(this.concrete))throw new Error(`Class '${this.concrete.name}' is not an Assemblage.`);const s=u(this.injections),i=u(this.objects);s((e=>this.privateContext.register(e))),i((e=>{"string"==typeof e[0]||"symbol"==typeof e[0]?this.privateContext.use(e[0],e[1]):this.privateContext.register(e,!0)})),this.dependenciesIds=(e=>{const t=[],n=b(e),s=L(e);let i=0;for(const r of n)s.Context.includes(i)||s.Configuration.includes(i)||s.Definition.includes(i)||s.Dispose.includes(i)||s.Use.includes(i)||t.push(r),i++;return t})(this.concrete),e.instance?this.singletonInstance=e.instance:this.isSingleton}}const z=(e,t,n,s)=>new Promise((i=>{const r=e[t];if(r){if(c(r))return void r.bind(e)(n,s).then((()=>{i()}));i(r.bind(e)(n,s))}}));function F(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class T extends P{static build(e){const t=new T;((e,t,s)=>{const i=C(s);i[e]=t;const r=v(i);p(n.AssemblageDefinition,r,s)})("singleton",!0,e);const s=t.register([e]),i=t.require(s.identifier),r=t.initCache.find((e=>e.instance===i));if(!r)throw new Error("Root instance not found in assemblages cache.");const o=t.initCache.indexOf(r);t.initCache.splice(o,1);for(const n of t.initCache)z(n.instance,"onInit",t.publicContext,n.configuration);return z(i,"onInit",t.publicContext,s.configuration),t.initCache.length=0,i}dispose(){for(const[e,t]of this.injectables)t.dispose();d(this,T)}register(e,t=!1){const n=!0===t?(e=>({identifier:e[0],concrete:e[0],instance:e[1],configuration:{}}))(e):(e=>((e,t)=>(n,...s)=>e[n]?e[n](...s):t?t(n,...s):void 0)({1:()=>(e=>({identifier:e[0],concrete:e[0],configuration:{}}))(e),2:()=>x(e),3:()=>(e=>({identifier:e[0],concrete:e[1],configuration:e[2]}))(e)},(()=>{throw new Error("Injection tuple must be of length 1, 2 or 3.")}))(e.length))(e);if(this.has(n.identifier))throw new Error(`An assemblage is already registered with identifier '${n.identifier.name}'.`);const s=H.of(n,this.privateContext,this.publicContext);return this.injectables.set(s.identifier,s),z(s.concrete,"onRegister",this.publicContext,s.configuration),s}use(e,t){if(this.has(e))throw new Error(`A value is already registered with identifier '${String(e)}'.`);return this.objects.set(e,t),t}prepareInitHook(e,t){return this.initCache.push({instance:e,configuration:t}),this.initCache}has(e){return"string"==typeof e||"symbol"==typeof e?this.objects.has(e):this.injectables.has(e)}require(e){switch(typeof e){case"string":case"symbol":if(!this.objects.has(e))throw new Error(`Injected object with identifier '${String(e)}' has not been registered.`);return this.objects.get(e);default:if(!this.injectables.has(e))throw new Error(`Class with identifier '${e.name}' has not been registered or is a circular dependency.`);return this.injectables.get(e).build()}}concrete(e){const t=this.injectables.get(e);if(t)return t.concrete}tagged(...e){const t=[];for(const n of e)for(const[e,s]of this.injectables)s.tags.includes(n)&&t.push(s.build());return t}get size(){return this.injectables.size}constructor(){super(),F(this,"injectables",new Map),F(this,"objects",new Map),F(this,"initCache",[]),F(this,"privateContext",void 0),F(this,"publicContext",void 0),this.publicContext={has:this.has.bind(this),require:this.require.bind(this),concrete:this.concrete.bind(this),tagged:this.tagged.bind(this),dispose:this.dispose.bind(this),on:this.on.bind(this),once:this.once.bind(this),off:this.off.bind(this),events:this.channels},this.privateContext={...this.publicContext,register:this.register.bind(this),use:this.use.bind(this),prepareInitHook:this.prepareInitHook.bind(this),emit:this.emit.bind(this),addChannels:this.addChannels.bind(this),removeChannels:this.removeChannels.bind(this)}}}exports.AbstractAssemblage=class{static onRegister(e,t){}},exports.AbstractAssembler=class extends O{},exports.AbstractEventManager=O,exports.Assemblage=e=>t=>j(t,e),exports.Assembler=T,exports.Await=(e,t=25)=>(n,s,i)=>{const r=i.value;i.value=async function(){return new Promise((n=>{if(this[e])r.apply(this),n();else{const s=setInterval((()=>{this[e]&&(clearInterval(s),r.apply(this),n())}),t)}}))}},exports.Configuration=R,exports.ConstructorDecorator=q,exports.Context=$,exports.Definition=M,exports.Dispose=_,exports.EventManager=P,exports.ReflectParamIndex=U,exports.ReflectParamValue=E,exports.Use=e=>(t,n,s)=>{k(e,t,s)},exports.createConstructorDecorator=e=>(t=!0)=>q(e,t),exports.decorateAssemblage=j,exports.decorateUse=k,exports.getDecoratedParametersIndexes=L,exports.isAssemblage=m; | ||
class AbstractAssemblage { | ||
static onRegister(s, t) {} | ||
} | ||
const ReflectParamTypes = 'design:paramtypes'; | ||
const ReflectPrefix = '__'; | ||
const ReflectSuffix = '__'; | ||
var ReflectFlags; | ||
(function(e) { | ||
e["IsAssemblage"] = "is_assemblage"; | ||
})(ReflectFlags || (ReflectFlags = {})); | ||
var ReflectValue; | ||
(function(e) { | ||
e["AssemblageDefinition"] = "assemblage:definition.value"; | ||
})(ReflectValue || (ReflectValue = {})); | ||
const NoOp = (...e)=>{}; | ||
const isOfType = (...e)=>(t)=>{ | ||
if (!e.includes(typeof t)) return undefined; | ||
return typeof t; | ||
}; | ||
const isUndefined = (e)=>typeof e === 'undefined'; | ||
const isNull = (e)=>e === null; | ||
const isDefined = (e)=>!isUndefined(e) && !isNull(e); | ||
const isClass = (e)=>{ | ||
return e && typeof e === 'function' && typeof e.constructor !== 'undefined'; | ||
}; | ||
const isObject = (e)=>typeof e === 'object' && !Array.isArray(e) && !isClass(e); | ||
const isAsync = (e)=>typeof e === 'function' && e.constructor.name === 'AsyncFunction'; | ||
const moveArrayItem = (e, t, r)=>{ | ||
const o = e[t]; | ||
e.splice(t, 1); | ||
e.splice(r, 0, o); | ||
return e; | ||
}; | ||
const dedupeArray = (e)=>Array.from(new Set(e)); | ||
const onlyAlphanumeric = (e, ...t)=>{ | ||
t.map((e, r)=>{ | ||
const o = /\S/.test(e); | ||
if (o) t[r] = t[r].trim(); | ||
return !o ? r : -1; | ||
}).filter((e)=>e >= 0).every((e)=>{ | ||
t[e] = ' '; | ||
moveArrayItem(t, e, t.length - 1); | ||
}); | ||
t = dedupeArray(t); | ||
const r = new RegExp(`[^A-Za-zĆ-ĆĆ-öø-Ćæ0-9${t.join('')}]`, 'gi'); | ||
return e.replace(r, ''); | ||
}; | ||
const switchCase = (e, t)=>(r, ...o)=>e[r] ? e[r](...o) : t ? t(r, ...o) : NoOp(); | ||
const pipe = (...e)=>(t)=>e.reduce((e, t)=>t(e), t); | ||
const conditionally = (e)=>(t)=>{ | ||
return e.if(t) ? e.then(t) : e.else ? e.else(t) : undefined; | ||
}; | ||
const forOf = (e)=>(t)=>{ | ||
const r = Array.isArray(e) ? (e)=>parseInt(e) : NoOp; | ||
for (const [o, n] of Object.entries(e)){ | ||
t(n, r(o)); | ||
} | ||
}; | ||
const forIn = (e)=>(t)=>{ | ||
const r = Array.isArray(e) ? (e)=>parseInt(e) : (e)=>e; | ||
for(const o in e){ | ||
t(r(o)); | ||
} | ||
}; | ||
const e$2 = (e, t)=>{ | ||
return [ | ||
...Object.getOwnPropertyNames(t.prototype), | ||
...Object.getOwnPropertyNames(Object.getPrototypeOf(e)), | ||
...Object.getOwnPropertyNames(e) | ||
]; | ||
}; | ||
const proxifyIterable = (t, r)=>{ | ||
const o = new Proxy(t, { | ||
get: function(o, n) { | ||
if (n === Symbol.iterator) { | ||
return o[Symbol.iterator].bind(o); | ||
} else if (!e$2(t, r).includes(n)) { | ||
return o.collection[n]; | ||
} | ||
return o[n]; | ||
}, | ||
set: function(e, t, r) { | ||
return Reflect.set(e, t, r); | ||
} | ||
}); | ||
return o; | ||
}; | ||
const clearInstance = (e, t)=>{ | ||
const r = (e, t)=>{ | ||
return [ | ||
...Object.getOwnPropertyNames(t.prototype), | ||
...Object.getOwnPropertyNames(Object.getPrototypeOf(e)), | ||
...Object.getOwnPropertyNames(e) | ||
]; | ||
}; | ||
const o = e; | ||
for (const n of r(e, t)){ | ||
delete o[n]; | ||
} | ||
}; | ||
const defineCustomMetadata = (t, o, n)=>{ | ||
Reflect.defineMetadata(`${ReflectPrefix}${t}${ReflectSuffix}`, o, n); | ||
}; | ||
const getOwnCustomMetadata = (t, o)=>{ | ||
return Reflect.getOwnMetadata(`${ReflectPrefix}${t}${ReflectSuffix}`, o); | ||
}; | ||
const getParamTypes = (e)=>{ | ||
return Reflect.getMetadata(ReflectParamTypes, e) || []; | ||
}; | ||
const isAssemblage = (m)=>{ | ||
return getOwnCustomMetadata(ReflectFlags.IsAssemblage, m) || false; | ||
}; | ||
const n = { | ||
singleton: { | ||
test: (r)=>typeof r === 'boolean' || typeof r === 'undefined', | ||
throw: ()=>{ | ||
throw new Error(`'singleton' property must be of type 'boolean' or 'undefined'.`); | ||
}, | ||
transform: (r)=>{ | ||
return typeof r === 'undefined' ? true : r ? true : false; | ||
} | ||
}, | ||
events: { | ||
test: (r)=>typeof r === 'undefined' || Array.isArray(r) && r.every((r)=>typeof r === 'string'), | ||
throw: ()=>{ | ||
throw new Error(`'events' property must be an array of strings or 'undefined'.`); | ||
}, | ||
transform: (r)=>r | ||
}, | ||
inject: { | ||
test: (r)=>typeof r === 'undefined' || Array.isArray(r) && r.every((r)=>Array.isArray(r) && r.length >= 1 && r.length <= 3), | ||
throw: ()=>{ | ||
throw new Error(`'inject' property must be an array of tuples of length 1, 2 or 3.`); | ||
}, | ||
transform: (r)=>r | ||
}, | ||
use: { | ||
test: (r)=>typeof r === 'undefined' || Array.isArray(r) && r.every((r)=>Array.isArray(r) && r.length == 2), | ||
throw: ()=>{ | ||
throw new Error(`'use' property must be an array of tuples of length 2.`); | ||
}, | ||
transform: (r)=>r | ||
}, | ||
tags: { | ||
test: (r)=>typeof r === 'undefined' || typeof r === 'string' || Array.isArray(r) && r.every((r)=>typeof r === 'string'), | ||
throw: ()=>{ | ||
throw new Error(`'tags' property must be a string or an array of strings.`); | ||
}, | ||
transform: (r)=>typeof r === 'string' ? [ | ||
r | ||
] : r | ||
}, | ||
metadata: { | ||
test: (r)=>(typeof r === 'object' || typeof r === 'undefined') && !Array.isArray(r), | ||
throw: ()=>{ | ||
throw new Error(`'metadata' property must be of type 'object' or 'undefined'.`); | ||
}, | ||
transform: (r)=>r | ||
} | ||
}; | ||
const validateDefinition = (r)=>{ | ||
const t = { | ||
...r | ||
}; | ||
for(const r in t){ | ||
if (!Object.keys(n).includes(r)) { | ||
throw new Error(`Property '${r}' is not a valid assemblage definition property.`); | ||
} | ||
} | ||
for(const r in n){ | ||
const e = n[r].test; | ||
const o = n[r].throw; | ||
const s = n[r].transform; | ||
if (!e(t[r])) { | ||
o(); | ||
} | ||
t[r] = s(t[r]); | ||
} | ||
return t; | ||
}; | ||
const getDefinition = (t)=>{ | ||
if (!isAssemblage(t)) { | ||
throw new Error(`Class '${t.name}' is not an assemblage.`); | ||
} | ||
return getOwnCustomMetadata(ReflectValue.AssemblageDefinition, t); | ||
}; | ||
const getDefinitionValue = (r, t)=>{ | ||
const e = getDefinition(t); | ||
return e[r]; | ||
}; | ||
const setDefinitionValue = (e, o, n)=>{ | ||
const s = getDefinition(n); | ||
s[e] = o; | ||
const i = validateDefinition(s); | ||
defineCustomMetadata(ReflectValue.AssemblageDefinition, i, n); | ||
return i; | ||
}; | ||
const i$1 = (n)=>{ | ||
return { | ||
identifier: n[0], | ||
concrete: n[0], | ||
configuration: {} | ||
}; | ||
}; | ||
const c$2 = (r)=>{ | ||
const i = ()=>isClass(r[0]) && isClass(r[1]); | ||
const c = ()=>isClass(r[0]) && isObject(r[1]); | ||
const f = ()=>pipe(conditionally({ | ||
if: ()=>i(), | ||
then: ()=>{ | ||
return { | ||
identifier: r[0], | ||
concrete: r[1], | ||
configuration: {} | ||
}; | ||
} | ||
}), conditionally({ | ||
if: ()=>c(), | ||
then: ()=>{ | ||
return { | ||
identifier: r[0], | ||
concrete: r[0], | ||
configuration: r[1] | ||
}; | ||
}, | ||
else: (n)=>n | ||
}))(); | ||
return f(); | ||
}; | ||
const f = (n)=>{ | ||
return { | ||
identifier: n[0], | ||
concrete: n[1], | ||
configuration: n[2] | ||
}; | ||
}; | ||
const resolveInjectionTuple = (n)=>switchCase({ | ||
1: ()=>i$1(n), | ||
2: ()=>c$2(n), | ||
3: ()=>f(n) | ||
}, ()=>{ | ||
throw new Error(`Injection tuple must be of length 1, 2 or 3.`); | ||
})(n.length); | ||
const resolveInstanceInjectionTuple = (e)=>{ | ||
return { | ||
identifier: e[0], | ||
concrete: e[0], | ||
instance: e[1], | ||
configuration: {} | ||
}; | ||
}; | ||
const Assemblage = (e)=>{ | ||
return (o)=>{ | ||
return decorateAssemblage(o, e); | ||
}; | ||
}; | ||
const decorateAssemblage = (s, m)=>{ | ||
const n = m ? validateDefinition(m) : validateDefinition({}); | ||
defineCustomMetadata(ReflectFlags.IsAssemblage, true, s); | ||
defineCustomMetadata(ReflectValue.AssemblageDefinition, n, s); | ||
return s; | ||
}; | ||
class AbstractListenerCollection { | ||
} | ||
class ListenerCollection { | ||
dispose() { | ||
clearInstance(this, ListenerCollection); | ||
} | ||
add(...t) { | ||
const n = (t)=>this.collection[t.channel].push(t.listener); | ||
const l = conditionally({ | ||
if: ()=>t.length === 2, | ||
then: ()=>{ | ||
return { | ||
channel: t[0], | ||
listener: t[1] | ||
}; | ||
}, | ||
else: ()=>{ | ||
const e = t[0]; | ||
return { | ||
channel: e[0], | ||
listener: e[1] | ||
}; | ||
} | ||
}); | ||
const c = conditionally({ | ||
if: (t)=>!isDefined(this.collection[t.channel]), | ||
then: (t)=>{ | ||
this.collection[t.channel] = []; | ||
n(t); | ||
}, | ||
else: (t)=>{ | ||
n(t); | ||
} | ||
}); | ||
pipe(l, c)(); | ||
return this; | ||
} | ||
remove(t, n) { | ||
const l = (e)=>this.collection[t].splice(e, 1); | ||
const c = conditionally({ | ||
if: ()=>this.collection[t] && this.collection[t].length === 0, | ||
then: ()=>delete this.collection[t] | ||
}); | ||
const s = conditionally({ | ||
if: ()=>isDefined(n), | ||
then: ()=>l(this.collection[t].indexOf(n)), | ||
else: ()=>delete this.collection[t] | ||
}); | ||
const r = conditionally({ | ||
if: (t)=>this.has(t), | ||
then: (t)=>this.collection[t] | ||
}); | ||
pipe(r, s, c)(); | ||
return this; | ||
} | ||
has(...t) { | ||
if (isOfType('string')(t[0])) { | ||
return Object.keys(this.collection).includes(t[0]); | ||
} else if (isOfType('function')(t[0])) { | ||
return Object.values(this.collection).flat().includes(t[0]); | ||
} | ||
return false; | ||
} | ||
get(...t) { | ||
if (isOfType('string')(t[0])) { | ||
return this.collection[t[0]]; | ||
} else if (isOfType('function')(t[0])) { | ||
return Object.values(this.collection).flat().filter((e)=>e === t[0]); | ||
} | ||
return []; | ||
} | ||
clear() { | ||
const t = forIn(this.collection); | ||
const e = (t)=>forOf(this.collection[t])((e)=>this.remove(t, e)); | ||
t((t)=>e(t)); | ||
return this; | ||
} | ||
get listeners() { | ||
return Object.values(this.collection).flat(); | ||
} | ||
get channels() { | ||
return Object.keys(this.collection); | ||
} | ||
get length() { | ||
return Object.values(this.collection).flat().length; | ||
} | ||
[Symbol.iterator]() { | ||
let t = -1; | ||
const e = this.collection ? Object.keys(this.collection) : []; | ||
return { | ||
next: ()=>({ | ||
value: e[++t], | ||
done: !(t in e) | ||
}) | ||
}; | ||
} | ||
constructor(){ | ||
this.collection = {}; | ||
const t = proxifyIterable(this, ListenerCollection); | ||
return t; | ||
} | ||
} | ||
class AbstractEventManager { | ||
} | ||
class EventManager { | ||
dispose() { | ||
this.listeners.dispose(); | ||
this.channels.clear(); | ||
clearInstance(this, EventManager); | ||
} | ||
addChannels(...e) { | ||
const s = forOf(e); | ||
s((e)=>{ | ||
const n = this.cleanChannel(e); | ||
if (this.channels.has(n)) { | ||
throw new Error(`Channel '${n}' already exists.`); | ||
} | ||
this.channels.add(n); | ||
}); | ||
return this; | ||
} | ||
removeChannels(...e) { | ||
const s = forOf(e); | ||
s((e)=>{ | ||
const n = this.cleanChannel(e); | ||
if (n !== '*' && this.channels.has(n)) { | ||
this.channels.delete(n); | ||
this.listeners.remove(n); | ||
this.onceListeners.remove(n); | ||
} | ||
}); | ||
return this; | ||
} | ||
on(e, n) { | ||
const s = this.cleanChannel(e); | ||
if (!this.channels.has(s)) { | ||
throw new Error(`Channel '${s}' was not registered.`); | ||
} | ||
this.listeners.add(s, n); | ||
return this; | ||
} | ||
once(e, n) { | ||
const s = this.cleanChannel(e); | ||
if (!this.channels.has(s)) { | ||
throw new Error(`Channel '${s}' was not registered.`); | ||
} | ||
this.onceListeners.add(s, n); | ||
return this; | ||
} | ||
off(e, n) { | ||
const s = this.cleanChannel(e); | ||
this.listeners.remove(s, n); | ||
return this; | ||
} | ||
emit(e, ...s) { | ||
const t = this.cleanChannel(e); | ||
if (this.channels.has(t)) { | ||
const e = this.onceListeners.get('*') || []; | ||
const i = this.listeners.get('*') || []; | ||
const h = this.onceListeners.get(t) || []; | ||
const r = this.listeners.get(t) || []; | ||
const o = forOf(e); | ||
const c = forOf(i); | ||
const a = forOf(h); | ||
const l = forOf(r); | ||
o((e)=>{ | ||
this.run(e, ...s); | ||
this.onceListeners.remove('*', e); | ||
}); | ||
c((e)=>{ | ||
this.run(e, ...s); | ||
}); | ||
a((e)=>{ | ||
this.run(e, ...s); | ||
this.onceListeners.remove(t, e); | ||
}); | ||
l((e)=>{ | ||
this.run(e, ...s); | ||
}); | ||
} | ||
return this; | ||
} | ||
run(e, ...n) { | ||
if (isAsync(e)) { | ||
const s = e; | ||
return s(...n).then(()=>Promise.resolve()); | ||
} | ||
e(...n); | ||
} | ||
cleanChannel(e) { | ||
return onlyAlphanumeric(e, '*'); | ||
} | ||
constructor(...e){ | ||
this.listeners = new ListenerCollection(); | ||
this.onceListeners = new ListenerCollection(); | ||
this.channels = new Set([ | ||
'*' | ||
]); | ||
this.addChannels(...e); | ||
} | ||
} | ||
const registerEvents = (t, n)=>{ | ||
const o = t.concrete.prototype instanceof EventManager; | ||
if (o) { | ||
const e = n; | ||
const o = e.channels; | ||
for (const n of t.events){ | ||
if (!o.has(n)) e.addChannels(n); | ||
if (!t.privateContext.events.has(n)) t.privateContext.addChannels(n); | ||
} | ||
for (const e of t.events){ | ||
n.on(e, (...n)=>{ | ||
t.privateContext.emit(e, ...n); | ||
}); | ||
} | ||
} | ||
}; | ||
const unregisterEvents = (t, n)=>{ | ||
const o = t.concrete.prototype instanceof EventManager; | ||
if (o) { | ||
const e = n; | ||
for (const n of t.events){ | ||
e.off(n); | ||
} | ||
e.removeChannels(...t.events); | ||
t.privateContext.removeChannels(...t.events); | ||
} | ||
}; | ||
const Await = (t, e = 25)=>{ | ||
return (n, s, a)=>{ | ||
const i = a.value; | ||
a.value = async function() { | ||
return new Promise((n)=>{ | ||
if (this[t]) { | ||
i.apply(this); | ||
n(); | ||
} else { | ||
const s = setInterval(()=>{ | ||
if (this[t]) { | ||
clearInterval(s); | ||
i.apply(this); | ||
n(); | ||
} | ||
}, e); | ||
} | ||
}); | ||
}; | ||
}; | ||
}; | ||
var ReflectParamValue; | ||
(function(e) { | ||
e["UseIdentifier"] = "assemblage:use.param.value"; | ||
})(ReflectParamValue || (ReflectParamValue = {})); | ||
var ReflectParamIndex; | ||
(function(e) { | ||
e["Context"] = "assembler:context.param.index"; | ||
e["Dispose"] = "assembler:dispose.param.index"; | ||
e["Definition"] = "assemblage:definition.param.index"; | ||
e["Configuration"] = "assemblage:configuration.param.index"; | ||
e["Use"] = "assemblage:use.param.index"; | ||
})(ReflectParamIndex || (ReflectParamIndex = {})); | ||
const i = (t)=>()=>{ | ||
return (i, s, r)=>{ | ||
const c = getOwnCustomMetadata(t, i) || []; | ||
c.push(r); | ||
defineCustomMetadata(t, c, i); | ||
}; | ||
}; | ||
const s$1 = i(ReflectParamIndex.Context); | ||
const r$1 = i(ReflectParamIndex.Configuration); | ||
const c$1 = i(ReflectParamIndex.Definition); | ||
const e$1 = i(ReflectParamIndex.Dispose); | ||
const Use = (e)=>{ | ||
return (o, t, s)=>{ | ||
decorateUse(e, o, s); | ||
}; | ||
}; | ||
const decorateUse = (r, n, c)=>{ | ||
const U = getOwnCustomMetadata(ReflectParamIndex.Use, n) || []; | ||
U.push(c); | ||
defineCustomMetadata(ReflectParamIndex.Use, U, n); | ||
const i = getOwnCustomMetadata(ReflectParamValue.UseIdentifier, n) || {}; | ||
i[c] = r; | ||
defineCustomMetadata(ReflectParamValue.UseIdentifier, i, n); | ||
}; | ||
const o = (o)=>{ | ||
return getOwnCustomMetadata(ReflectParamIndex.Context, o) || []; | ||
}; | ||
const r = (o)=>{ | ||
return getOwnCustomMetadata(ReflectParamIndex.Configuration, o) || []; | ||
}; | ||
const e = (o)=>{ | ||
return getOwnCustomMetadata(ReflectParamIndex.Definition, o) || []; | ||
}; | ||
const s = (o)=>{ | ||
return getOwnCustomMetadata(ReflectParamIndex.Dispose, o) || []; | ||
}; | ||
const c = (o)=>{ | ||
return getOwnCustomMetadata(ReflectParamIndex.Use, o) || []; | ||
}; | ||
const getDecoratedParametersIndexes = (t)=>{ | ||
const n = o(t) || []; | ||
const i = e(t) || []; | ||
const m = r(t) || []; | ||
const u = s(t) || []; | ||
const a = c(t) || []; | ||
return { | ||
Context: n, | ||
Definition: i, | ||
Configuration: m, | ||
Dispose: u, | ||
Use: a | ||
}; | ||
}; | ||
const createConstructorDecorator = (t)=>{ | ||
return (o = true)=>ConstructorDecorator(t, o); | ||
}; | ||
const ConstructorDecorator = (f, a = true)=>(p)=>{ | ||
const m = class extends p { | ||
constructor(...t){ | ||
super(...t); | ||
if (f) f.call(this); | ||
} | ||
}; | ||
Object.defineProperty(m, 'name', { | ||
value: p.name | ||
}); | ||
if (!a) { | ||
return m; | ||
} | ||
const l = Reflect.getOwnMetadata(ReflectParamTypes, p) || []; | ||
const D = getDecoratedParametersIndexes(p); | ||
const d = []; | ||
for(let n = 0; n < l.length; n++){ | ||
if (D.Context.includes(n)) { | ||
const e = getOwnCustomMetadata(ReflectParamIndex.Context, p) || []; | ||
e.push(n); | ||
defineCustomMetadata(ReflectParamIndex.Context, e, m); | ||
continue; | ||
} | ||
if (D.Definition.includes(n)) { | ||
const e = getOwnCustomMetadata(ReflectParamIndex.Definition, p) || []; | ||
e.push(n); | ||
defineCustomMetadata(ReflectParamIndex.Definition, e, m); | ||
continue; | ||
} | ||
if (D.Configuration.includes(n)) { | ||
const e = getOwnCustomMetadata(ReflectParamIndex.Configuration, p) || []; | ||
e.push(n); | ||
defineCustomMetadata(ReflectParamIndex.Configuration, e, m); | ||
continue; | ||
} | ||
if (D.Dispose.includes(n)) { | ||
const e = getOwnCustomMetadata(ReflectParamIndex.Dispose, p) || []; | ||
e.push(n); | ||
defineCustomMetadata(ReflectParamIndex.Dispose, e, m); | ||
d.push(l[n]); | ||
continue; | ||
} | ||
if (D.Use.includes(n)) { | ||
const t = getOwnCustomMetadata(ReflectParamValue.UseIdentifier, p); | ||
decorateUse(t[n], m, n); | ||
continue; | ||
} | ||
} | ||
if (!a) return m; | ||
return decorateAssemblage(m, getOwnCustomMetadata(ReflectValue.AssemblageDefinition, p)); | ||
}; | ||
const resolveInjectableParameters = (i)=>{ | ||
const s = []; | ||
const c = getParamTypes(i.concrete); | ||
const r = getDecoratedParametersIndexes(i.concrete); | ||
let u = 0; | ||
for (const n of c){ | ||
if (r.Context.includes(u)) { | ||
s.push(i.publicContext); | ||
u++; | ||
continue; | ||
} | ||
if (r.Configuration.includes(u)) { | ||
s.push(i.configuration); | ||
u++; | ||
continue; | ||
} | ||
if (r.Definition.includes(u)) { | ||
s.push(i.definition); | ||
u++; | ||
continue; | ||
} | ||
if (r.Dispose.includes(u)) { | ||
s.push(i.privateContext.dispose); | ||
u++; | ||
continue; | ||
} | ||
if (r.Use.includes(u)) { | ||
const n = getOwnCustomMetadata(ReflectParamValue.UseIdentifier, i.concrete); | ||
const t = n[u]; | ||
s.push(i.privateContext.require(t)); | ||
u++; | ||
continue; | ||
} | ||
s.push(i.privateContext.require(n)); | ||
u++; | ||
} | ||
return s; | ||
}; | ||
const resolveDependencies = (e)=>{ | ||
const o = []; | ||
const i = getParamTypes(e); | ||
const s = getDecoratedParametersIndexes(e); | ||
let c = 0; | ||
for (const e of i){ | ||
if (s.Context.includes(c) || s.Configuration.includes(c) || s.Definition.includes(c) || s.Dispose.includes(c) || s.Use.includes(c)) { | ||
c++; | ||
continue; | ||
} | ||
o.push(e); | ||
c++; | ||
} | ||
return o; | ||
}; | ||
class Injectable { | ||
static of(t, e, n) { | ||
return new Injectable(t, e, n); | ||
} | ||
dispose() { | ||
if (this.singletonInstance) { | ||
unregisterEvents(this, this.singletonInstance); | ||
callHook(this.singletonInstance, 'onDispose', this.publicContext, this.configuration); | ||
clearInstance(this.singletonInstance, this.concrete); | ||
} | ||
clearInstance(this, Injectable); | ||
} | ||
build() { | ||
if (this.singletonInstance) return this.singletonInstance; | ||
const t = resolveInjectableParameters(this); | ||
const e = new this.concrete(...t); | ||
registerEvents(this, e); | ||
if (this.isSingleton) { | ||
this.singletonInstance = e; | ||
this.privateContext.prepareInitHook(e, this.configuration); | ||
return this.singletonInstance; | ||
} | ||
callHook(e, 'onInit', this.publicContext); | ||
return e; | ||
} | ||
get dependencies() { | ||
return this.dependenciesIds; | ||
} | ||
get definition() { | ||
return getDefinition(this.concrete) || {}; | ||
} | ||
get isSingleton() { | ||
return getDefinitionValue('singleton', this.concrete); | ||
} | ||
get singleton() { | ||
return this.singletonInstance; | ||
} | ||
get injections() { | ||
return getDefinitionValue('inject', this.concrete) || []; | ||
} | ||
get objects() { | ||
return getDefinitionValue('use', this.concrete) || []; | ||
} | ||
get tags() { | ||
return getDefinitionValue('tags', this.concrete) || []; | ||
} | ||
get events() { | ||
return getDefinitionValue('events', this.concrete) || []; | ||
} | ||
constructor(t, i, s){ | ||
this.privateContext = i; | ||
this.publicContext = s; | ||
this.dependenciesIds = []; | ||
this.identifier = t.identifier; | ||
this.concrete = t.concrete; | ||
this.configuration = t.configuration; | ||
if (!isAssemblage(this.concrete)) { | ||
throw new Error(`Class '${this.concrete.name}' is not an Assemblage.`); | ||
} | ||
const o = forOf(this.injections); | ||
const r = forOf(this.objects); | ||
o((t)=>this.privateContext.register(t)); | ||
r((t)=>{ | ||
if (typeof t[0] === 'string' || typeof t[0] === 'symbol') { | ||
this.privateContext.use(t[0], t[1]); | ||
} else { | ||
this.privateContext.register(t, true); | ||
} | ||
}); | ||
this.dependenciesIds = resolveDependencies(this.concrete); | ||
if (t.instance) { | ||
this.singletonInstance = t.instance; | ||
} else if (this.isSingleton) ; | ||
} | ||
} | ||
const callHook = (n, r, t, e)=>{ | ||
return new Promise((i)=>{ | ||
const m = n[r]; | ||
if (m) { | ||
if (isAsync(m)) { | ||
m.bind(n)(t, e).then(()=>{ | ||
i(); | ||
}); | ||
return; | ||
} | ||
i(m.bind(n)(t, e)); | ||
} | ||
}); | ||
}; | ||
class Assembler extends EventManager { | ||
static build(e) { | ||
const i = new Assembler(); | ||
setDefinitionValue('singleton', true, e); | ||
const s = i.register([ | ||
e | ||
]); | ||
const n = i.require(s.identifier); | ||
const r = i.initCache.find((e)=>e.instance === n); | ||
if (!r) { | ||
throw new Error('Root instance not found in assemblages cache.'); | ||
} | ||
const h = i.initCache.indexOf(r); | ||
i.initCache.splice(h, 1); | ||
for (const e of i.initCache){ | ||
callHook(e.instance, 'onInit', i.publicContext, e.configuration); | ||
} | ||
callHook(n, 'onInit', i.publicContext, s.configuration); | ||
i.initCache.length = 0; | ||
return n; | ||
} | ||
dispose() { | ||
for (const [e, t] of this.injectables){ | ||
t.dispose(); | ||
} | ||
clearInstance(this, Assembler); | ||
} | ||
register(e, t = false) { | ||
const r = t === true ? resolveInstanceInjectionTuple(e) : resolveInjectionTuple(e); | ||
if (this.has(r.identifier)) { | ||
throw new Error(`An assemblage is already registered with identifier '${r.identifier.name}'.`); | ||
} | ||
const h = Injectable.of(r, this.privateContext, this.publicContext); | ||
this.injectables.set(h.identifier, h); | ||
callHook(h.concrete, 'onRegister', this.publicContext, h.configuration); | ||
return h; | ||
} | ||
use(e, t) { | ||
if (this.has(e)) { | ||
throw new Error(`A value is already registered with identifier '${String(e)}'.`); | ||
} | ||
this.objects.set(e, t); | ||
return t; | ||
} | ||
prepareInitHook(e, t) { | ||
this.initCache.push({ | ||
instance: e, | ||
configuration: t | ||
}); | ||
return this.initCache; | ||
} | ||
has(e) { | ||
if (typeof e === 'string' || typeof e === 'symbol') { | ||
return this.objects.has(e); | ||
} | ||
return this.injectables.has(e); | ||
} | ||
require(e) { | ||
switch(typeof e){ | ||
case 'string': | ||
case 'symbol': | ||
{ | ||
if (!this.objects.has(e)) { | ||
throw new Error(`Injected object with identifier '${String(e)}' has not been registered.`); | ||
} | ||
return this.objects.get(e); | ||
} | ||
default: | ||
{ | ||
if (!this.injectables.has(e)) { | ||
throw new Error(`Class with identifier '${e.name}' has not been registered or is a circular dependency.`); | ||
} | ||
const t = this.injectables.get(e); | ||
return t.build(); | ||
} | ||
} | ||
} | ||
concrete(e) { | ||
const t = this.injectables.get(e); | ||
if (t) return t.concrete; | ||
return; | ||
} | ||
tagged(...e) { | ||
const t = []; | ||
for (const i of e){ | ||
for (const [e, s] of this.injectables){ | ||
if (s.tags.includes(i)) t.push(s.build()); | ||
} | ||
} | ||
return t; | ||
} | ||
get size() { | ||
return this.injectables.size; | ||
} | ||
constructor(){ | ||
super(); | ||
this.injectables = new Map(); | ||
this.objects = new Map(); | ||
this.initCache = []; | ||
this.publicContext = { | ||
has: this.has.bind(this), | ||
require: this.require.bind(this), | ||
concrete: this.concrete.bind(this), | ||
tagged: this.tagged.bind(this), | ||
dispose: this.dispose.bind(this), | ||
on: this.on.bind(this), | ||
once: this.once.bind(this), | ||
off: this.off.bind(this), | ||
events: this.channels | ||
}; | ||
this.privateContext = { | ||
...this.publicContext, | ||
register: this.register.bind(this), | ||
use: this.use.bind(this), | ||
prepareInitHook: this.prepareInitHook.bind(this), | ||
emit: this.emit.bind(this), | ||
addChannels: this.addChannels.bind(this), | ||
removeChannels: this.removeChannels.bind(this) | ||
}; | ||
} | ||
} | ||
class AbstractAssembler extends AbstractEventManager { | ||
} | ||
export { AbstractAssemblage, AbstractAssembler, AbstractEventManager, AbstractListenerCollection, Assemblage, Assembler, Await, r$1 as Configuration, ConstructorDecorator, s$1 as Context, c$1 as Definition, e$1 as Dispose, EventManager, ListenerCollection, ReflectParamIndex, ReflectParamValue, Use, createConstructorDecorator, decorateAssemblage, decorateUse, getDecoratedParametersIndexes, isAssemblage }; |
{ | ||
"name": "assemblerjs", | ||
"description": "A general purpose and zero-dependency Dependency Injection library for node and browser.", | ||
"version": "0.7.7", | ||
"version": "0.8.0", | ||
"author": "BenoƮt LAHOZ <info@benoitlahoz.io>", | ||
"bugs": "https://github.com/benoitlahoz/assemblerjs/issues", | ||
"devDependencies": { | ||
"@swc/core": "^1.9.3", | ||
"@types/node": "^22.5.5", | ||
"@vitest/coverage-istanbul": "^2.1.1", | ||
"assert": "^2.1.0", | ||
"istanbul": "^0.4.5", | ||
"istanbul-badges-readme": "^1.9.0", | ||
"reflect-metadata": ">=0.2.2", | ||
"rollup-plugin-swc": "^0.2.1", | ||
"terser": "^5.34.1", | ||
"vite": "6.0.2", | ||
"vite-plugin-dts": "^4.4.0", | ||
"vitepress": "^1.5.0", | ||
"vitest": "^2.1.1" | ||
"homepage": "https://github.com/benoitlahoz/assemblerjs#README", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/benoitlahoz/assemblerjs.git" | ||
}, | ||
"engines": { | ||
"node": ">= 18.12.0" | ||
}, | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"import": "./dist/index.mjs", | ||
"require": "./dist/index.js" | ||
} | ||
}, | ||
"files": [ | ||
"dist/**/*", | ||
"README.md" | ||
], | ||
"homepage": "https://github.com/benoitlahoz/assemblerjs#README", | ||
"keywords": [ | ||
@@ -56,16 +31,28 @@ "agencement", | ||
"license": "MIT", | ||
"main": "dist/index.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/benoitlahoz/assemblerjs.git" | ||
"type": "module", | ||
"main": "./dist/index.cjs", | ||
"module": "./dist/index.js", | ||
"types": "./dist/index.d.ts", | ||
"exports": { | ||
"./package.json": "./package.json", | ||
".": { | ||
"development": "./src/index.ts", | ||
"types": "./dist/index.d.ts", | ||
"import": "./dist/index.js", | ||
"require": "./dist/index.cjs", | ||
"default": "./dist/index.js" | ||
} | ||
}, | ||
"engines": { | ||
"node": ">= 18.12.0" | ||
}, | ||
"files": [ | ||
"dist", | ||
"!**/*.tsbuildinfo" | ||
], | ||
"scripts": { | ||
"build": "vite build", | ||
"coverage": "vitest run --coverage --passWithNoTests && istanbul-badges-readme", | ||
"docs:build": "vitepress build docs", | ||
"docs:dev": "vitepress dev docs --host", | ||
"docs:preview": "vitepress preview docs", | ||
"test": "vitest --coverage --passWithNoTests" | ||
"test": "vitest --coverage --passWithNoTests", | ||
"coverage": "vitest run --coverage --passWithNoTests && istanbul-badges-readme" | ||
}, | ||
"types": "dist/index.d.ts" | ||
"dependencies": {} | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
71997
4.15%0
-100%1531
3.73%Yes
NaN1
Infinity%