assemblerjs 0.7.7 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="design:paramtypes";var t,n;(t||(t={})).IsAssemblage="is_assemblage",(n||(n={})).AssemblageDefinition="assemblage:definition.value";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,a=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,c=(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,f=e=>t=>{const n=Array.isArray(e)?e=>parseInt(e):s;for(const[s,i]of Object.entries(e))t(i,n(s))},u=(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},p=(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]},d=(e,t,n)=>{Reflect.defineMetadata(`__${e}__`,t,n)},g=(e,t)=>Reflect.getOwnMetadata(`__${e}__`,t),m=t=>Reflect.getMetadata(e,t)||[],x=e=>g(t.IsAssemblage,e)||!1,b={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}},y=e=>{const t={...e};for(const n in t)if(!Object.keys(b).includes(n))throw new Error(`Property '${n}' is not a valid assemblage definition property.`);for(const n in b){const e=b[n].test,s=b[n].throw,i=b[n].transform;e(t[n])||s(),t[n]=i(t[n])}return t},C=e=>{if(!x(e))throw new Error(`Class '${e.name}' is not an assemblage.`);return g(n.AssemblageDefinition,e)},v=(e,t)=>C(t)[e],w=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}))()},I=(e,s)=>{const i=y(s||{});return d(t.IsAssemblage,!0,e),d(n.AssemblageDefinition,i,e),e};class j{dispose(){p(this,j)}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=>f(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}[Symbol.iterator](){let e=-1;const t=this.collection?Object.keys(this.collection):[];return{next:()=>({value:t[++e],done:!(e in t)})}}constructor(){this.collection={};return u(this,j)}}class A{}class P{dispose(){this.listeners.dispose(),this.channels.clear(),p(this,P)}addChannels(...e){return f(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 f(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=f(e),a=f(s),c=f(i),l=f(r);o((e=>{this.run(e,...t),this.onceListeners.remove("*",e)})),a((e=>{this.run(e,...t)})),c((e=>{this.run(e,...t),this.onceListeners.remove(n,e)})),l((e=>{this.run(e,...t)}))}return this}run(e,...t){if(a(e)){return e(...t).then((()=>Promise.resolve()))}e(...t)}cleanChannel(e){return c(e,"*")}constructor(...e){this.listeners=new j,this.onceListeners=new j,this.channels=new Set(["*"]),this.addChannels(...e)}}exports.ReflectParamValue=void 0,(exports.ReflectParamValue||(exports.ReflectParamValue={})).UseIdentifier="assemblage:use.param.value",exports.ReflectParamIndex=void 0,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"}(exports.ReflectParamIndex||(exports.ReflectParamIndex={}));const R=e=>()=>(t,n,s)=>{const i=g(e,t)||[];i.push(s),d(e,i,t)},O=R(exports.ReflectParamIndex.Context),D=R(exports.ReflectParamIndex.Configuration),E=R(exports.ReflectParamIndex.Definition),U=R(exports.ReflectParamIndex.Dispose),S=(e,t,n)=>{const s=g(exports.ReflectParamIndex.Use,t)||[];s.push(n),d(exports.ReflectParamIndex.Use,s,t);const i=g(exports.ReflectParamValue.UseIdentifier,t)||{};i[n]=e,d(exports.ReflectParamValue.UseIdentifier,i,t)},$=e=>{const t=(e=>g(exports.ReflectParamIndex.Context,e)||[])(e)||[],n=(e=>g(exports.ReflectParamIndex.Definition,e)||[])(e)||[],s=(e=>g(exports.ReflectParamIndex.Configuration,e)||[])(e)||[],i=(e=>g(exports.ReflectParamIndex.Dispose,e)||[])(e)||[],r=(e=>g(exports.ReflectParamIndex.Use,e)||[])(e)||[];return{Context:t,Definition:n,Configuration:s,Dispose:i,Use:r}},L=(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)||[],a=$(i),c=[];for(let e=0;e<o.length;e++)if(a.Context.includes(e)){const t=g(exports.ReflectParamIndex.Context,i)||[];t.push(e),d(exports.ReflectParamIndex.Context,t,r)}else if(a.Definition.includes(e)){const t=g(exports.ReflectParamIndex.Definition,i)||[];t.push(e),d(exports.ReflectParamIndex.Definition,t,r)}else if(a.Configuration.includes(e)){const t=g(exports.ReflectParamIndex.Configuration,i)||[];t.push(e),d(exports.ReflectParamIndex.Configuration,t,r)}else if(a.Dispose.includes(e)){const t=g(exports.ReflectParamIndex.Dispose,i)||[];t.push(e),d(exports.ReflectParamIndex.Dispose,t,r),c.push(o[e])}else if(a.Use.includes(e)){const t=g(exports.ReflectParamValue.UseIdentifier,i);S(t[e],r,e)}else;return s?I(r,g(n.AssemblageDefinition,i)):r};class M{static of(e,t,n){return new M(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),_(this.singletonInstance,"onDispose",this.publicContext,this.configuration),p(this.singletonInstance,this.concrete)),p(this,M)}build(){if(this.singletonInstance)return this.singletonInstance;const e=(e=>{const t=[],n=m(e.concrete),s=$(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(exports.ReflectParamValue.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):(_(t,"onInit",this.publicContext),t)}get dependencies(){return this.dependenciesIds}get definition(){return C(this.concrete)||{}}get isSingleton(){return v("singleton",this.concrete)}get singleton(){return this.singletonInstance}get injections(){return v("inject",this.concrete)||[]}get objects(){return v("use",this.concrete)||[]}get tags(){return v("tags",this.concrete)||[]}get events(){return v("events",this.concrete)||[]}constructor(e,t,n){if(this.privateContext=t,this.publicContext=n,this.dependenciesIds=[],this.identifier=e.identifier,this.concrete=e.concrete,this.configuration=e.configuration,!x(this.concrete))throw new Error(`Class '${this.concrete.name}' is not an Assemblage.`);const s=f(this.injections),i=f(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=m(e),s=$(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 _=(e,t,n,s)=>new Promise((i=>{const r=e[t];if(r){if(a(r))return void r.bind(e)(n,s).then((()=>{i()}));i(r.bind(e)(n,s))}}));class k extends P{static build(e){const t=new k;((e,t,s)=>{const i=C(s);i[e]=t;const r=y(i);d(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)_(n.instance,"onInit",t.publicContext,n.configuration);return _(i,"onInit",t.publicContext,s.configuration),t.initCache.length=0,i}dispose(){for(const[e,t]of this.injectables)t.dispose();p(this,k)}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:()=>w(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=M.of(n,this.privateContext,this.publicContext);return this.injectables.set(s.identifier,s),_(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(),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)}}}exports.AbstractAssemblage=class{static onRegister(e,t){}},exports.AbstractAssembler=class extends A{},exports.AbstractEventManager=A,exports.AbstractListenerCollection=class{},exports.Assemblage=e=>t=>I(t,e),exports.Assembler=k,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=D,exports.ConstructorDecorator=L,exports.Context=O,exports.Definition=E,exports.Dispose=U,exports.EventManager=P,exports.ListenerCollection=j,exports.Use=e=>(t,n,s)=>{S(e,t,s)},exports.createConstructorDecorator=e=>(t=!0)=>L(e,t),exports.decorateAssemblage=I,exports.decorateUse=S,exports.getDecoratedParametersIndexes=$,exports.isAssemblage=x;
package/dist/index.d.ts CHANGED
@@ -48,10 +48,10 @@ export declare abstract class AbstractAssembler extends AbstractEventManager {
48
48
  abstract publicContext: AssemblerContext;
49
49
  abstract size: number;
50
50
  abstract register<T>(injection: Injection<T>, instance?: boolean): Injectable<T>;
51
- abstract use<T>(identifier: string | Symbol, object: T): T;
51
+ abstract use<T>(identifier: string | symbol, object: T): T;
52
52
  abstract prepareInitHook<T = AbstractAssemblage>(instance: T, configuration?: Record<string, any>): unknown[];
53
53
  abstract has<T>(identifier: Identifier<T>): boolean;
54
- abstract require<T>(identifier: Identifier<T> | string | Symbol): T;
54
+ abstract require<T>(identifier: Identifier<T> | string | symbol): T;
55
55
  abstract concrete<T>(identifier: Identifier<T>): Concrete<T> | undefined;
56
56
  abstract tagged(...tags: string[]): any[];
57
57
  abstract dispose(): void;
@@ -71,7 +71,7 @@ export declare abstract class AbstractEventManager {
71
71
  declare abstract class AbstractInjectable<T> {
72
72
  abstract readonly privateContext: AssemblerPrivateContext;
73
73
  abstract readonly publicContext: AssemblerContext;
74
- abstract readonly identifier: Identifier<T> | string | Symbol;
74
+ abstract readonly identifier: Identifier<T> | string | symbol;
75
75
  abstract readonly concrete: Concrete<T>;
76
76
  abstract readonly configuration: Record<string, any>;
77
77
  abstract dependencies: (Identifier<unknown> | any)[];
@@ -87,6 +87,21 @@ declare abstract class AbstractInjectable<T> {
87
87
  abstract build(): T;
88
88
  }
89
89
 
90
+ /**
91
+ * An abstract class for `ListenerCollection` implementation.
92
+ */
93
+ export declare abstract class AbstractListenerCollection {
94
+ [key: EventChannel]: any;
95
+ abstract listeners: Listener[];
96
+ abstract channels: EventChannel[];
97
+ abstract add(channel: EventChannel, listener: Listener): AbstractListenerCollection;
98
+ abstract remove(channel: EventChannel, listener?: Listener): AbstractListenerCollection;
99
+ abstract has(...args: (EventChannel | Listener)[]): boolean;
100
+ abstract get(...args: (EventChannel | Listener)[]): (EventChannel | Listener)[];
101
+ abstract clear(): AbstractListenerCollection;
102
+ abstract [Symbol.iterator](): Iterator<EventChannel>;
103
+ }
104
+
90
105
  /**
91
106
  * Generic `Array` items.
92
107
  */
@@ -126,7 +141,7 @@ export declare class Assembler extends EventManager implements AbstractAssembler
126
141
  */
127
142
  static build<T>(entry: Concrete<T>): T;
128
143
  protected injectables: Map<Identifier<unknown>, Injectable<unknown>>;
129
- protected objects: Map<string | Symbol, unknown>;
144
+ protected objects: Map<string | symbol, unknown>;
130
145
  private initCache;
131
146
  /**
132
147
  * Context passed to internal classes.
@@ -177,7 +192,7 @@ export declare class Assembler extends EventManager implements AbstractAssembler
177
192
  * }
178
193
  * ```
179
194
  */
180
- use<T>(identifier: string | Symbol, object: T): T;
195
+ use<T>(identifier: string | symbol, object: T): T;
181
196
  /**
182
197
  * Cache an instaance to be inited with `onInit` hook
183
198
  * when the dependency tree will be fully resolved.
@@ -191,17 +206,17 @@ export declare class Assembler extends EventManager implements AbstractAssembler
191
206
  * Check if `Assembler` has given identifier registered.
192
207
  *
193
208
  * @param { Identifier<T> | string | symbol } identifier An abstract or concrete class,
194
- * or a string or Symbol as identifier.
209
+ * or a string or symbol as identifier.
195
210
  * @returns { boolean } `true` if dependency has been registered.
196
211
  */
197
- has<T>(identifier: Identifier<T> | string | Symbol): boolean;
212
+ has<T>(identifier: Identifier<T> | string | symbol): boolean;
198
213
  /**
199
214
  * Get or instantiate an assemblage for given identifier.
200
215
  *
201
216
  * @param { Identifier<T> | string | symbol } identifier The identifier to get instance from.
202
217
  * @returns { T } An instance of Concrete<T>.
203
218
  */
204
- require<T>(identifier: Identifier<T> | string | Symbol): T;
219
+ require<T>(identifier: Identifier<T> | string | symbol): T;
205
220
  /**
206
221
  * Return a `Concrete` class for given identifier.
207
222
  *
@@ -351,7 +366,7 @@ export declare class Assembler extends EventManager implements AbstractAssembler
351
366
  /**
352
367
  * Decorator as a wrapper function.
353
368
  */
354
- export declare const decorateUse: (identifier: string | Symbol, target: any, index: number) => void;
369
+ export declare const decorateUse: (identifier: string | symbol, target: any, index: number) => void;
355
370
 
356
371
  /**
357
372
  * Injects the assemblage's definition object.
@@ -363,6 +378,16 @@ export declare class Assembler extends EventManager implements AbstractAssembler
363
378
  */
364
379
  export declare const Dispose: () => ParameterDecorator;
365
380
 
381
+ /**
382
+ * `EventChannel` extends `string`.
383
+ */
384
+ export declare type EventChannel = string;
385
+
386
+ /**
387
+ * Describes a list of event channels as Record<EventChannel, string>
388
+ */
389
+ export declare type EventChannelList = Record<EventChannel, string>;
390
+
366
391
  export declare class EventManager implements AbstractEventManager {
367
392
  private readonly listeners;
368
393
  private readonly onceListeners;
@@ -389,7 +414,7 @@ export declare class Assembler extends EventManager implements AbstractAssembler
389
414
  declare class Injectable<T> implements AbstractInjectable<T> {
390
415
  readonly privateContext: AssemblerPrivateContext;
391
416
  readonly publicContext: AssemblerContext;
392
- readonly identifier: Identifier<T> | string | Symbol;
417
+ readonly identifier: Identifier<T> | string | symbol;
393
418
  readonly concrete: Concrete<T>;
394
419
  readonly configuration: Record<string, any>;
395
420
  private dependenciesIds;
@@ -449,7 +474,7 @@ export declare class Assembler extends EventManager implements AbstractAssembler
449
474
  /**
450
475
  * Injectable binds an instance of a class to an identifier (abstract or concrete).
451
476
  */
452
- declare type InstanceInjection<T> = Tuple<[Identifier<T> | string | Symbol, T]>;
477
+ declare type InstanceInjection<T> = Tuple<[Identifier<T> | string | symbol, T]>;
453
478
 
454
479
  /**
455
480
  * Check if a given class is an `Assemblage`.
@@ -462,7 +487,96 @@ export declare class Assembler extends EventManager implements AbstractAssembler
462
487
  /**
463
488
  * Describes a listener type as a function taking any number of arguments and returning `void`.
464
489
  */
465
- declare type Listener = (...args: any[]) => void | Promise<void>;
490
+ export declare type Listener = (...args: any[]) => void | Promise<void>;
491
+
492
+ export declare class ListenerCollection implements AbstractListenerCollection {
493
+ /**
494
+ * Class is indexable by `EventChannel`.
495
+ */
496
+ [key: string]: Listener[] | any;
497
+ /**
498
+ * Internal listeners `Object`.
499
+ */
500
+ readonly collection: Record<EventChannel, Array<Listener>>;
501
+ constructor();
502
+ /**
503
+ * Clean up the collection by removing all listeners and channels
504
+ * and deleting listeners private property.
505
+ */
506
+ dispose(): void;
507
+ /**
508
+ * Add a listener to the collection.
509
+ *
510
+ * @param { EventChannel } channel The channel to add the listener to.
511
+ * @param { Listener } listener The callback function to run when the event is emitted.
512
+ * @returns { ListenerCollection } This collection.
513
+ */
514
+ add(channel: EventChannel, listener: Listener): ListenerCollection;
515
+ /**
516
+ * Add a listener to the collection.
517
+ *
518
+ * @param { Tuple<EventChannel, Listener> } tuple The channel and its listener in a tuple.
519
+ * @returns { ListenerCollection } This collection.
520
+ */
521
+ add(tuple: Tuple<[EventChannel, Listener]>): ListenerCollection;
522
+ /**
523
+ * Removes a listener or all listeners for a given channel.
524
+ * If the channel or the provided listener does not exist, fails silently.
525
+ *
526
+ * @param { EventChannel } channel The channel the listener is listening to.
527
+ * @param { Listener } listener The listener to remove. If not provided, remove all listeners for given channel.
528
+ * @returns { ListenerCollection } This collection.
529
+ */
530
+ remove(channel: string, listener?: Listener): ListenerCollection;
531
+ /**
532
+ * Checks if the collection includes a specific channel or listener.
533
+ *
534
+ * @param { EventChannel | Listener } value The channel or the listener to find in the collection.
535
+ * @returns { boolean } true if the collection includes this channel / this listener,
536
+ * false if not.
537
+ */
538
+ has(value: EventChannel): boolean;
539
+ has(value: Listener): boolean;
540
+ /**
541
+ * Get a specific channel listeners array or a specific listener channels array.
542
+ *
543
+ * @param { EventChannel | Listener } value The channel or the listener to find in the collection.
544
+ * @returns { EventChannel[] | Listener[] } An array of channels or listeners.
545
+ */
546
+ get(value: EventChannel): Listener[];
547
+ get(value: Listener): EventChannel[];
548
+ /**
549
+ * Clear the entire collction.
550
+ *
551
+ * @returns { ListenerCollection } This collection.
552
+ */
553
+ clear(): ListenerCollection;
554
+ /**
555
+ * The listeners of this collection flatten in a single array.
556
+ */
557
+ get listeners(): Listener[];
558
+ /**
559
+ * The listeners collection channels.
560
+ */
561
+ get channels(): EventChannel[];
562
+ /**
563
+ * Returns the total listeners length.
564
+ */
565
+ get length(): number;
566
+ /**
567
+ * Allows iterating over listeners in specific channel with 'for... of...' loop.
568
+ *
569
+ * @returns { Listener } A listener function.
570
+ *
571
+ * @example
572
+ * // Iterates listeners in a specific channel.
573
+ * for (const listener of myListenerCollection) {
574
+ * // Calls the registered listener.
575
+ * listener();
576
+ * }
577
+ */
578
+ [Symbol.iterator](): Iterator<EventChannel>;
579
+ }
466
580
 
467
581
  declare interface ParametersDecoratorsIndexes {
468
582
  Context: number[];
@@ -500,8 +614,8 @@ export declare class Assembler extends EventManager implements AbstractAssembler
500
614
  };
501
615
 
502
616
  /**
503
- * Injects an object passed with `string` or `Symbol` identifier.
617
+ * Injects an object passed with `string` or `symbol` identifier.
504
618
  */
505
- export declare const Use: (identifier: string | Symbol) => ParameterDecorator;
619
+ export declare const Use: (identifier: string | symbol) => ParameterDecorator;
506
620
 
507
621
  export { }