assemblerjs 0.8.6 → 0.8.8

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.d.ts CHANGED
@@ -16,12 +16,20 @@ export declare abstract class AbstractAssemblage {
16
16
  */
17
17
  static onRegister(context: AssemblerContext, configuration?: Record<string, any>): void;
18
18
  /**
19
- * Called on instantiated class after the dependency tree is fully resolved.
19
+ * Called on instantiated class in less dependent to more dependent order after the dependency tree is fully resolved.
20
20
  *
21
21
  * @param { AssemblerContext } context The assembler's context.
22
22
  * @param { Reord<string, any> } configuration The configuration object.
23
23
  */
24
24
  abstract onInit?(context: AssemblerContext, configuration?: Record<string, any>): void | Promise<void>;
25
+ /**
26
+ * Called by the `Assembler` when all classes have been inited with `onInit`, including the entry point,
27
+ * in more dependent to less dependent order.
28
+ *
29
+ * @param { AssemblerContext } context The assembler's context.
30
+ * @param { Reord<string, any> } configuration The configuration object.
31
+ */
32
+ abstract onInited?(context: AssemblerContext, configuration?: Record<string, any>): void | Promise<void>;
25
33
  /**
26
34
  * Called when instance of class is disposed.
27
35
  *
@@ -182,7 +190,7 @@ export declare class Assembler extends EventManager implements AbstractAssembler
182
190
  */
183
191
  use<T>(identifier: string | symbol, object: T): T;
184
192
  /**
185
- * Cache an instaance to be inited with `onInit` hook
193
+ * Cache an instance to be inited with `onInit` hook
186
194
  * when the dependency tree will be fully resolved.
187
195
  *
188
196
  * @param { T = AbstractAssemblage } instance The built instance.
@@ -320,13 +328,14 @@ export declare class Assembler extends EventManager implements AbstractAssembler
320
328
  * A custom decorator that adds a function called after the original constructor
321
329
  * and that can wrap an `Assemblage` with its own parameters decorator (e.g. @Use, @Context, ...).
322
330
  * Note that it must be placed before the `Assemnblage` decorator.
331
+ * The `definition` optional parameter allows passing a configuration object to the decorator.
323
332
  *
324
- * @param { function(): void | undefined } fn A function to execute after `super`.
333
+ * @param { function(definition?: ObjectLiteral): void | undefined } fn A function to execute after `super`.
325
334
  * Do not use arrow function here if access to `this` is required.
326
335
  * @param { boolean | undefined } asAssemblage If `true` decorate the class as an assemblage (defaults to `true`).
327
336
  * @returns A new decorator.
328
337
  */
329
- export declare const ConstructorDecorator: (fn?: () => void, asAssemblage?: boolean) => any;
338
+ export declare const ConstructorDecorator: <T extends ObjectLiteral>(fn?: (definition?: T) => void, definition?: T) => any;
330
339
 
331
340
  /**
332
341
  * Injects the Assembler's context.
@@ -337,12 +346,13 @@ export declare class Assembler extends EventManager implements AbstractAssembler
337
346
  * Create a custom decorator that adds a function called after the original constructor
338
347
  * and that can wrap an `Assemblage` with its own parameters decorator (e.g. @Use, @Context, ...).
339
348
  * Note that it must be placed before the `Assemblage` decorator.
349
+ * The `definition` optional parameter allows passing a configuration object to the decorator.
340
350
  *
341
- * @param { function(): void | undefined } fn A function to execute after `super`.
351
+ * @param { function(definition?: ObjectLiteral): void | undefined } fn A function to execute after `super`.
342
352
  * Do not use arrow function here if access to `this` is required.
343
353
  * @returns A new decorator.
344
354
  */
345
- export declare const createConstructorDecorator: (fn?: () => void) => any;
355
+ export declare const createConstructorDecorator: <T extends ObjectLiteral>(fn?: (definition?: T) => void) => any;
346
356
 
347
357
  /**
348
358
  * Manually decorate a class to be an `Assemblage`.
@@ -394,12 +404,14 @@ export declare class Assembler extends EventManager implements AbstractAssembler
394
404
  private cleanChannel;
395
405
  }
396
406
 
407
+ export declare const getAssemblageDefinition: <T>(target: Concrete<T>) => AssemblageDefinition;
408
+
397
409
  export declare const getDecoratedParametersIndexes: <T>(target: Concrete<T>) => ParametersDecoratorsIndexes;
398
410
 
399
411
  /**
400
412
  * An identifier can be an abstract or a concrete class.
401
413
  */
402
- declare type Identifier<T> = Class<T>;
414
+ export declare type Identifier<T> = Class<T>;
403
415
 
404
416
  declare class Injectable<T> implements AbstractInjectable<T> {
405
417
  readonly privateContext: AssemblerPrivateContext;
@@ -568,6 +580,10 @@ export declare class Assembler extends EventManager implements AbstractAssembler
568
580
  [Symbol.iterator](): Iterator<EventChannel>;
569
581
  }
570
582
 
583
+ export declare interface ObjectLiteral {
584
+ [key: string]: any;
585
+ }
586
+
571
587
  declare interface ParametersDecoratorsIndexes {
572
588
  Context: number[];
573
589
  Definition: number[];
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@assemblerjs/core");const t="design:paramtypes";var n,s;(n||(n={})).IsAssemblage="is_assemblage",(s||(s={})).AssemblageDefinition="assemblage:definition.value";const i=(e,t,n)=>{Reflect.defineMetadata(`__${e}__`,t,n)},r=(e,t)=>Reflect.getOwnMetadata(`__${e}__`,t),o=e=>Reflect.getMetadata(t,e)||[],a=e=>r(n.IsAssemblage,e)||!1,c={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}},l=e=>{const t={...e};for(const n in t)if(!Object.keys(c).includes(n))throw new Error(`Property '${n}' is not a valid assemblage definition property.`);for(const n in c){const e=c[n].test,s=c[n].throw,i=c[n].transform;e(t[n])||s(),t[n]=i(t[n])}return t},h=e=>{if(!a(e))throw new Error(`Class '${e.name}' is not an assemblage.`);return r(s.AssemblageDefinition,e)},f=(e,t)=>h(t)[e],d=t=>e.pipe(e.conditionally({if:()=>e.isClass(t[0])&&e.isClass(t[1]),then:()=>({identifier:t[0],concrete:t[1],configuration:{}})}),e.conditionally({if:()=>e.isClass(t[0])&&e.isObject(t[1]),then:()=>({identifier:t[0],concrete:t[0],configuration:t[1]}),else:e=>e}))(),u=(e,t)=>{const r=l(t||{});return i(n.IsAssemblage,!0,e),i(s.AssemblageDefinition,r,e),e};class p{dispose(){e.clearInstance(this,p)}add(...t){const n=e=>this.collection[e.channel].push(e.listener),s=e.conditionally({if:()=>2===t.length,then:()=>({channel:t[0],listener:t[1]}),else:()=>{const e=t[0];return{channel:e[0],listener:e[1]}}}),i=e.conditionally({if:t=>!e.isDefined(this.collection[t.channel]),then:e=>{this.collection[e.channel]=[],n(e)},else:e=>{n(e)}});return e.pipe(s,i)(),this}remove(t,n){const s=e=>this.collection[t].splice(e,1),i=e.conditionally({if:()=>this.collection[t]&&0===this.collection[t].length,then:()=>delete this.collection[t]}),r=e.conditionally({if:()=>e.isDefined(n),then:()=>s(this.collection[t].indexOf(n)),else:()=>delete this.collection[t]}),o=e.conditionally({if:e=>this.has(e),then:e=>this.collection[e]});return e.pipe(o,r,i)(),this}has(...t){return e.isOfType("string")(t[0])?Object.keys(this.collection).includes(t[0]):!!e.isOfType("function")(t[0])&&Object.values(this.collection).flat().includes(t[0])}get(...t){return e.isOfType("string")(t[0])?this.collection[t[0]]:e.isOfType("function")(t[0])?Object.values(this.collection).flat().filter((e=>e===t[0])):[]}clear(){const t=e.forIn(this.collection),n=t=>e.forOf(this.collection[t])((e=>this.remove(t,e)));return t((e=>n(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 e.proxifyIterable(this,p)}}class g{}class x{dispose(){this.listeners.dispose(),this.channels.clear(),e.clearInstance(this,x)}addChannels(...t){return e.forOf(t)((e=>{const t=this.cleanChannel(e);if(this.channels.has(t))throw new Error(`Channel '${t}' already exists.`);this.channels.add(t)})),this}removeChannels(...t){return e.forOf(t)((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(t,...n){const s=this.cleanChannel(t);if(this.channels.has(s)){const t=this.onceListeners.get("*")||[],i=this.listeners.get("*")||[],r=this.onceListeners.get(s)||[],o=this.listeners.get(s)||[],a=e.forOf(t),c=e.forOf(i),l=e.forOf(r),h=e.forOf(o);a((e=>{this.run(e,...n),this.onceListeners.remove("*",e)})),c((e=>{this.run(e,...n)})),l((e=>{this.run(e,...n),this.onceListeners.remove(s,e)})),h((e=>{this.run(e,...n)}))}return this}run(t,...n){if(e.isAsync(t)){return t(...n).then((()=>Promise.resolve()))}t(...n)}cleanChannel(t){return e.onlyAlphanumeric(t,"*")}constructor(...e){this.listeners=new p,this.onceListeners=new p,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 m=e=>()=>(t,n,s)=>{const o=r(e,t)||[];o.push(s),i(e,o,t)},b=m(exports.ReflectParamIndex.Context),C=m(exports.ReflectParamIndex.Configuration),y=m(exports.ReflectParamIndex.Definition),v=m(exports.ReflectParamIndex.Dispose),w=(e,t,n)=>{const s=r(exports.ReflectParamIndex.Use,t)||[];s.push(n),i(exports.ReflectParamIndex.Use,s,t);const o=r(exports.ReflectParamValue.UseIdentifier,t)||{};o[n]=e,i(exports.ReflectParamValue.UseIdentifier,o,t)},I=e=>{const t=(e=>r(exports.ReflectParamIndex.Context,e)||[])(e)||[],n=(e=>r(exports.ReflectParamIndex.Definition,e)||[])(e)||[],s=(e=>r(exports.ReflectParamIndex.Configuration,e)||[])(e)||[],i=(e=>r(exports.ReflectParamIndex.Dispose,e)||[])(e)||[],o=(e=>r(exports.ReflectParamIndex.Use,e)||[])(e)||[];return{Context:t,Definition:n,Configuration:s,Dispose:i,Use:o}},A=(e,n=!0)=>o=>{const a=class extends o{constructor(...t){super(...t),e&&e.call(this)}};if(Object.defineProperty(a,"name",{value:o.name}),!n)return a;const c=Reflect.getOwnMetadata(t,o)||[],l=I(o),h=[];for(let e=0;e<c.length;e++)if(l.Context.includes(e)){const t=r(exports.ReflectParamIndex.Context,o)||[];t.push(e),i(exports.ReflectParamIndex.Context,t,a)}else if(l.Definition.includes(e)){const t=r(exports.ReflectParamIndex.Definition,o)||[];t.push(e),i(exports.ReflectParamIndex.Definition,t,a)}else if(l.Configuration.includes(e)){const t=r(exports.ReflectParamIndex.Configuration,o)||[];t.push(e),i(exports.ReflectParamIndex.Configuration,t,a)}else if(l.Dispose.includes(e)){const t=r(exports.ReflectParamIndex.Dispose,o)||[];t.push(e),i(exports.ReflectParamIndex.Dispose,t,a),h.push(c[e])}else if(l.Use.includes(e)){const t=r(exports.ReflectParamValue.UseIdentifier,o);w(t[e],a,e)}else;return u(a,r(s.AssemblageDefinition,o))};class j{static of(e,t,n){return new j(e,t,n)}dispose(){this.singletonInstance&&(((e,t)=>{if(e.concrete.prototype instanceof x){const n=t;for(const t of e.events)n.off(t);n.removeChannels(...e.events),e.privateContext.removeChannels(...e.events)}})(this,this.singletonInstance),P(this.singletonInstance,"onDispose",this.publicContext,this.configuration),e.clearInstance(this.singletonInstance,this.concrete)),e.clearInstance(this,j)}build(){if(this.singletonInstance)return this.singletonInstance;const e=(e=>{const t=[],n=o(e.concrete),s=I(e.concrete);let i=0;for(const o 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=r(exports.ReflectParamValue.UseIdentifier,e.concrete)[i];t.push(e.privateContext.require(n)),i++}else t.push(e.privateContext.require(o)),i++;return t})(this),t=new this.concrete(...e);return((e,t)=>{if(e.concrete.prototype instanceof x){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):(P(t,"onInit",this.publicContext),t)}get dependencies(){return this.dependenciesIds}get definition(){return h(this.concrete)||{}}get isSingleton(){return f("singleton",this.concrete)}get singleton(){return this.singletonInstance}get injections(){return f("inject",this.concrete)||[]}get objects(){return f("use",this.concrete)||[]}get tags(){return f("tags",this.concrete)||[]}get events(){return f("events",this.concrete)||[]}constructor(t,n,s){if(this.privateContext=n,this.publicContext=s,this.dependenciesIds=[],this.identifier=t.identifier,this.concrete=t.concrete,this.configuration=t.configuration,!a(this.concrete))throw new Error(`Class '${this.concrete.name}' is not an Assemblage.`);const i=e.forOf(this.injections),r=e.forOf(this.objects);i((e=>this.privateContext.register(e))),r((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=o(e),s=I(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),t.instance?this.singletonInstance=t.instance:this.isSingleton}}const P=(t,n,s,i)=>new Promise((r=>{const o=t[n];if(o){if(e.isAsync(o))return void o.bind(t)(s,i).then((()=>{r()}));r(o.bind(t)(s,i))}}));class R extends x{static build(e){const t=new R;((e,t,n)=>{const r=h(n);r[e]=t;const o=l(r);i(s.AssemblageDefinition,o,n)})("singleton",!0,e);const n=t.register([e]),r=t.require(n.identifier),o=t.initCache.find((e=>e.instance===r));if(!o)throw new Error("Root instance not found in assemblages cache.");const a=t.initCache.indexOf(o);t.initCache.splice(a,1);for(const s of t.initCache)P(s.instance,"onInit",t.publicContext,s.configuration);return P(r,"onInit",t.publicContext,n.configuration),t.initCache.length=0,r}dispose(){for(const[e,t]of this.injectables)t.dispose();e.clearInstance(this,R)}register(t,n=!1){const s=!0===n?(e=>({identifier:e[0],concrete:e[0],instance:e[1],configuration:{}}))(t):(t=>e.switchCase({1:()=>(e=>({identifier:e[0],concrete:e[0],configuration:{}}))(t),2:()=>d(t),3:()=>(e=>({identifier:e[0],concrete:e[1],configuration:e[2]}))(t)},(()=>{throw new Error("Injection tuple must be of length 1, 2 or 3.")}))(t.length))(t);if(this.has(s.identifier))throw new Error(`An assemblage is already registered with identifier '${s.identifier.name}'.`);const i=j.of(s,this.privateContext,this.publicContext);return this.injectables.set(i.identifier,i),P(i.concrete,"onRegister",this.publicContext,i.configuration),i}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 g{},exports.AbstractEventManager=g,exports.AbstractListenerCollection=class{},exports.Assemblage=e=>t=>u(t,e),exports.Assembler=R,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=C,exports.ConstructorDecorator=A,exports.Context=b,exports.Definition=y,exports.Dispose=v,exports.EventManager=x,exports.ListenerCollection=p,exports.Use=e=>(t,n,s)=>{w(e,t,s)},exports.createConstructorDecorator=e=>(t=!0)=>A(e,t),exports.decorateAssemblage=u,exports.decorateUse=w,exports.getDecoratedParametersIndexes=I,exports.isAssemblage=a;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@assemblerjs/core");const t="design:paramtypes";var n,s;(n||(n={})).IsAssemblage="is_assemblage",(s||(s={})).AssemblageDefinition="assemblage:definition.value";const i=(e,t,n)=>{Reflect.defineMetadata(`__${e}__`,t,n)},r=(e,t)=>Reflect.getOwnMetadata(`__${e}__`,t),o=e=>Reflect.getMetadata(t,e)||[],a=e=>r(n.IsAssemblage,e)||!1,c={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}},l=e=>{const t={...e};for(const n in t)if(!Object.keys(c).includes(n))throw new Error(`Property '${n}' is not a valid assemblage definition property.`);for(const n in c){const e=c[n].test,s=c[n].throw,i=c[n].transform;e(t[n])||s(),t[n]=i(t[n])}return t},h=e=>{if(!a(e))throw new Error(`Class '${e.name}' is not an assemblage.`);return r(s.AssemblageDefinition,e)},f=(e,t)=>h(t)[e],d=t=>e.pipe(e.conditionally({if:()=>e.isClass(t[0])&&e.isClass(t[1]),then:()=>({identifier:t[0],concrete:t[1],configuration:{}})}),e.conditionally({if:()=>e.isClass(t[0])&&e.isObject(t[1]),then:()=>({identifier:t[0],concrete:t[0],configuration:t[1]}),else:e=>e}))(),u=(e,t)=>{const r=l(t||{});return i(n.IsAssemblage,!0,e),i(s.AssemblageDefinition,r,e),e};class p{dispose(){e.clearInstance(this,p)}add(...t){const n=e=>this.collection[e.channel].push(e.listener),s=e.conditionally({if:()=>2===t.length,then:()=>({channel:t[0],listener:t[1]}),else:()=>{const e=t[0];return{channel:e[0],listener:e[1]}}}),i=e.conditionally({if:t=>!e.isDefined(this.collection[t.channel]),then:e=>{this.collection[e.channel]=[],n(e)},else:e=>{n(e)}});return e.pipe(s,i)(),this}remove(t,n){const s=e=>this.collection[t].splice(e,1),i=e.conditionally({if:()=>this.collection[t]&&0===this.collection[t].length,then:()=>delete this.collection[t]}),r=e.conditionally({if:()=>e.isDefined(n),then:()=>s(this.collection[t].indexOf(n)),else:()=>delete this.collection[t]}),o=e.conditionally({if:e=>this.has(e),then:e=>this.collection[e]});return e.pipe(o,r,i)(),this}has(...t){return e.isOfType("string")(t[0])?Object.keys(this.collection).includes(t[0]):!!e.isOfType("function")(t[0])&&Object.values(this.collection).flat().includes(t[0])}get(...t){return e.isOfType("string")(t[0])?this.collection[t[0]]:e.isOfType("function")(t[0])?Object.values(this.collection).flat().filter((e=>e===t[0])):[]}clear(){const t=e.forIn(this.collection),n=t=>e.forOf(this.collection[t])((e=>this.remove(t,e)));return t((e=>n(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 e.proxifyIterable(this,p)}}class g{}class x{dispose(){this.listeners.dispose(),this.channels.clear(),e.clearInstance(this,x)}addChannels(...t){return e.forOf(t)((e=>{const t=this.cleanChannel(e);if(this.channels.has(t))throw new Error(`Channel '${t}' already exists.`);this.channels.add(t)})),this}removeChannels(...t){return e.forOf(t)((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(t,...n){const s=this.cleanChannel(t);if(this.channels.has(s)){const t=this.onceListeners.get("*")||[],i=this.listeners.get("*")||[],r=this.onceListeners.get(s)||[],o=this.listeners.get(s)||[],a=e.forOf(t),c=e.forOf(i),l=e.forOf(r),h=e.forOf(o);a((e=>{this.run(e,...n),this.onceListeners.remove("*",e)})),c((e=>{this.run(e,...n)})),l((e=>{this.run(e,...n),this.onceListeners.remove(s,e)})),h((e=>{this.run(e,...n)}))}return this}run(t,...n){if(e.isAsync(t)){return t(...n).then((()=>Promise.resolve()))}t(...n)}cleanChannel(t){return e.onlyAlphanumeric(t,"*",":",".","-","_")}constructor(...e){this.listeners=new p,this.onceListeners=new p,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 m=e=>()=>(t,n,s)=>{const o=r(e,t)||[];o.push(s),i(e,o,t)},b=m(exports.ReflectParamIndex.Context),C=m(exports.ReflectParamIndex.Configuration),v=m(exports.ReflectParamIndex.Definition),y=m(exports.ReflectParamIndex.Dispose),w=(e,t,n)=>{const s=r(exports.ReflectParamIndex.Use,t)||[];s.push(n),i(exports.ReflectParamIndex.Use,s,t);const o=r(exports.ReflectParamValue.UseIdentifier,t)||{};o[n]=e,i(exports.ReflectParamValue.UseIdentifier,o,t)},I=e=>{const t=(e=>r(exports.ReflectParamIndex.Context,e)||[])(e)||[],n=(e=>r(exports.ReflectParamIndex.Definition,e)||[])(e)||[],s=(e=>r(exports.ReflectParamIndex.Configuration,e)||[])(e)||[],i=(e=>r(exports.ReflectParamIndex.Dispose,e)||[])(e)||[],o=(e=>r(exports.ReflectParamIndex.Use,e)||[])(e)||[];return{Context:t,Definition:n,Configuration:s,Dispose:i,Use:o}},A=(e,n)=>o=>{const a=class extends o{constructor(...t){super(...t),e&&e.call(this,n)}};Object.defineProperty(a,"name",{value:o.name});const c=Reflect.getOwnMetadata(t,o)||[],l=I(o),h=[];for(let e=0;e<c.length;e++)if(l.Context.includes(e)){const t=r(exports.ReflectParamIndex.Context,o)||[];t.push(e),i(exports.ReflectParamIndex.Context,t,a)}else if(l.Definition.includes(e)){const t=r(exports.ReflectParamIndex.Definition,o)||[];t.push(e),i(exports.ReflectParamIndex.Definition,t,a)}else if(l.Configuration.includes(e)){const t=r(exports.ReflectParamIndex.Configuration,o)||[];t.push(e),i(exports.ReflectParamIndex.Configuration,t,a)}else if(l.Dispose.includes(e)){const t=r(exports.ReflectParamIndex.Dispose,o)||[];t.push(e),i(exports.ReflectParamIndex.Dispose,t,a),h.push(c[e])}else if(l.Use.includes(e)){const t=r(exports.ReflectParamValue.UseIdentifier,o);w(t[e],a,e)}else;return u(a,r(s.AssemblageDefinition,o))};class j{static of(e,t,n){return new j(e,t,n)}dispose(){this.singletonInstance&&(((e,t)=>{if(e.concrete.prototype instanceof x){const n=t;for(const t of e.events)n.off(t);n.removeChannels(...e.events),e.privateContext.removeChannels(...e.events)}else for(const n of e.events)e.privateContext.events.has(n)&&e.privateContext.removeChannels(n)})(this,this.singletonInstance),P(this.singletonInstance,"onDispose",this.publicContext,this.configuration),e.clearInstance(this.singletonInstance,this.concrete)),e.clearInstance(this,j)}build(){if(this.singletonInstance)return this.singletonInstance;const e=(e=>{const t=[],n=o(e.concrete),s=I(e.concrete);let i=0;for(const o 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=r(exports.ReflectParamValue.UseIdentifier,e.concrete)[i];t.push(e.privateContext.require(n)),i++}else t.push(e.privateContext.require(o)),i++;return t})(this),t=new this.concrete(...e);return((e,t)=>{if(e.concrete.prototype instanceof x){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)}))}else for(const n of e.events)e.privateContext.events.has(n)||e.privateContext.addChannels(n)})(this,t),this.isSingleton?(this.singletonInstance=t,this.privateContext.prepareInitHook(t,this.configuration),this.singletonInstance):(P(t,"onInit",this.publicContext),t)}get dependencies(){return this.dependenciesIds}get definition(){return h(this.concrete)||{}}get isSingleton(){return f("singleton",this.concrete)}get singleton(){return this.singletonInstance}get injections(){return f("inject",this.concrete)||[]}get objects(){return f("use",this.concrete)||[]}get tags(){return f("tags",this.concrete)||[]}get events(){return f("events",this.concrete)||[]}constructor(t,n,s){if(this.privateContext=n,this.publicContext=s,this.dependenciesIds=[],this.identifier=t.identifier,this.concrete=t.concrete,this.configuration=t.configuration,!a(this.concrete))throw new Error(`Class '${this.concrete.name}' is not an Assemblage.`);const i=e.forOf(this.injections),r=e.forOf(this.objects);i((e=>this.privateContext.register(e))),r((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=o(e),s=I(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),t.instance?this.singletonInstance=t.instance:this.isSingleton}}const P=(t,n,s,i)=>new Promise((r=>{const o=t[n];if(o){if(e.isAsync(o))return void o.bind(t)(s,i).then((()=>{r()}));r(o.bind(t)(s,i))}}));class R extends x{static build(e){const t=new R;((e,t,n)=>{const r=h(n);r[e]=t;const o=l(r);i(s.AssemblageDefinition,o,n)})("singleton",!0,e);const n=t.register([e]),r=t.require(n.identifier),o=t.initCache.find((e=>e.instance===r));if(!o)throw new Error("Root instance not found in assemblages cache.");const a=t.initCache.indexOf(o);t.initCache.splice(a,1);for(const s of t.initCache)P(s.instance,"onInit",t.publicContext,s.configuration);P(r,"onInit",t.publicContext,n.configuration);for(const s of t.initCache.reverse())P(s.instance,"onInited",t.publicContext,s.configuration);return P(r,"onInited",t.publicContext,n.configuration),t.initCache.length=0,r}dispose(){for(const[e,t]of this.injectables)t.dispose();e.clearInstance(this,R)}register(t,n=!1){const s=!0===n?(e=>({identifier:e[0],concrete:e[0],instance:e[1],configuration:{}}))(t):(t=>e.switchCase({1:()=>(e=>({identifier:e[0],concrete:e[0],configuration:{}}))(t),2:()=>d(t),3:()=>(e=>({identifier:e[0],concrete:e[1],configuration:e[2]}))(t)},(()=>{throw new Error("Injection tuple must be of length 1, 2 or 3.")}))(t.length))(t);if(this.has(s.identifier))throw new Error(`An assemblage is already registered with identifier '${s.identifier.name}'.`);const i=j.of(s,this.privateContext,this.publicContext);return this.injectables.set(i.identifier,i),P(i.concrete,"onRegister",this.publicContext,i.configuration),i}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 g{},exports.AbstractEventManager=g,exports.AbstractListenerCollection=class{},exports.Assemblage=e=>t=>u(t,e),exports.Assembler=R,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=C,exports.ConstructorDecorator=A,exports.Context=b,exports.Definition=v,exports.Dispose=y,exports.EventManager=x,exports.ListenerCollection=p,exports.Use=e=>(t,n,s)=>{w(e,t,s)},exports.createConstructorDecorator=e=>t=>A(e,t),exports.decorateAssemblage=u,exports.decorateUse=w,exports.getAssemblageDefinition=e=>r(s.AssemblageDefinition,e),exports.getDecoratedParametersIndexes=I,exports.isAssemblage=a;
package/dist/index.mjs CHANGED
@@ -26,8 +26,11 @@ const getParamTypes = (e)=>{
26
26
  return Reflect.getMetadata(ReflectParamTypes, e) || [];
27
27
  };
28
28
 
29
- const isAssemblage = (m)=>{
30
- return getOwnCustomMetadata(ReflectFlags.IsAssemblage, m) || false;
29
+ const isAssemblage = (s)=>{
30
+ return getOwnCustomMetadata(ReflectFlags.IsAssemblage, s) || false;
31
+ };
32
+ const getAssemblageDefinition = (e)=>{
33
+ return getOwnCustomMetadata(ReflectValue.AssemblageDefinition, e);
31
34
  };
32
35
 
33
36
  const n = {
@@ -377,7 +380,7 @@ class EventManager {
377
380
  e(...s);
378
381
  }
379
382
  cleanChannel(e) {
380
- return onlyAlphanumeric(e, '*');
383
+ return onlyAlphanumeric(e, '*', ':', '.', '-', '_');
381
384
  }
382
385
  constructor(...e){
383
386
  this.listeners = new ListenerCollection();
@@ -403,6 +406,10 @@ const registerEvents = (t, n)=>{
403
406
  t.privateContext.emit(e, ...n);
404
407
  });
405
408
  }
409
+ } else {
410
+ for (const e of t.events){
411
+ if (!t.privateContext.events.has(e)) t.privateContext.addChannels(e);
412
+ }
406
413
  }
407
414
  };
408
415
  const unregisterEvents = (t, n)=>{
@@ -414,6 +421,12 @@ const unregisterEvents = (t, n)=>{
414
421
  }
415
422
  e.removeChannels(...t.events);
416
423
  t.privateContext.removeChannels(...t.events);
424
+ } else {
425
+ for (const e of t.events){
426
+ if (t.privateContext.events.has(e)) {
427
+ t.privateContext.removeChannels(e);
428
+ }
429
+ }
417
430
  }
418
431
  };
419
432
 
@@ -509,53 +522,50 @@ const getDecoratedParametersIndexes = (t)=>{
509
522
  };
510
523
 
511
524
  const createConstructorDecorator = (t)=>{
512
- return (e = true)=>ConstructorDecorator(t, e);
525
+ return (o)=>ConstructorDecorator(t, o);
513
526
  };
514
- const ConstructorDecorator = (a, f = true)=>(p)=>{
527
+ const ConstructorDecorator = (a, f)=>(p)=>{
515
528
  const m = class extends p {
516
529
  constructor(...t){
517
530
  super(...t);
518
- if (a) a.call(this);
531
+ if (a) a.call(this, f);
519
532
  }
520
533
  };
521
534
  Object.defineProperty(m, 'name', {
522
535
  value: p.name
523
536
  });
524
- if (!f) {
525
- return m;
526
- }
527
537
  const l = Reflect.getOwnMetadata(ReflectParamTypes, p) || [];
528
538
  const D = getDecoratedParametersIndexes(p);
529
539
  const d = [];
530
- for(let o = 0; o < l.length; o++){
531
- if (D.Context.includes(o)) {
540
+ for(let e = 0; e < l.length; e++){
541
+ if (D.Context.includes(e)) {
532
542
  const n = getOwnCustomMetadata(ReflectParamIndex.Context, p) || [];
533
- n.push(o);
543
+ n.push(e);
534
544
  defineCustomMetadata(ReflectParamIndex.Context, n, m);
535
545
  continue;
536
546
  }
537
- if (D.Definition.includes(o)) {
547
+ if (D.Definition.includes(e)) {
538
548
  const n = getOwnCustomMetadata(ReflectParamIndex.Definition, p) || [];
539
- n.push(o);
549
+ n.push(e);
540
550
  defineCustomMetadata(ReflectParamIndex.Definition, n, m);
541
551
  continue;
542
552
  }
543
- if (D.Configuration.includes(o)) {
553
+ if (D.Configuration.includes(e)) {
544
554
  const n = getOwnCustomMetadata(ReflectParamIndex.Configuration, p) || [];
545
- n.push(o);
555
+ n.push(e);
546
556
  defineCustomMetadata(ReflectParamIndex.Configuration, n, m);
547
557
  continue;
548
558
  }
549
- if (D.Dispose.includes(o)) {
559
+ if (D.Dispose.includes(e)) {
550
560
  const n = getOwnCustomMetadata(ReflectParamIndex.Dispose, p) || [];
551
- n.push(o);
561
+ n.push(e);
552
562
  defineCustomMetadata(ReflectParamIndex.Dispose, n, m);
553
- d.push(l[o]);
563
+ d.push(l[e]);
554
564
  continue;
555
565
  }
556
- if (D.Use.includes(o)) {
566
+ if (D.Use.includes(e)) {
557
567
  const t = getOwnCustomMetadata(ReflectParamValue.UseIdentifier, p);
558
- decorateUse(t[o], m, o);
568
+ decorateUse(t[e], m, e);
559
569
  continue;
560
570
  }
561
571
  }
@@ -725,6 +735,10 @@ class Assembler extends EventManager {
725
735
  callHook(e.instance, 'onInit', i.publicContext, e.configuration);
726
736
  }
727
737
  callHook(n, 'onInit', i.publicContext, s.configuration);
738
+ for (const e of i.initCache.reverse()){
739
+ callHook(e.instance, 'onInited', i.publicContext, e.configuration);
740
+ }
741
+ callHook(n, 'onInited', i.publicContext, s.configuration);
728
742
  i.initCache.length = 0;
729
743
  return n;
730
744
  }
@@ -832,4 +846,4 @@ class Assembler extends EventManager {
832
846
  class AbstractAssembler extends AbstractEventManager {
833
847
  }
834
848
 
835
- 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 };
849
+ 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, getAssemblageDefinition, getDecoratedParametersIndexes, isAssemblage };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "assemblerjs",
3
3
  "description": "A general purpose Dependency Injection library for node and browser.",
4
- "version": "0.8.6",
4
+ "version": "0.8.8",
5
5
  "author": "Benoît LAHOZ <info@benoitlahoz.io>",
6
6
  "bugs": "https://github.com/benoitlahoz/assemblerjs/issues",
7
7
  "homepage": "https://github.com/benoitlahoz/assemblerjs#README",