assemblerjs 0.9.1 → 0.9.3

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
@@ -56,10 +56,12 @@ export declare abstract class AbstractAssembler extends AbstractEventManager {
56
56
  abstract register<T>(injection: Injection<T>, instance?: boolean): Injectable<T>;
57
57
  abstract use<T>(identifier: string | symbol, object: T): T;
58
58
  abstract prepareInitHook<T = AbstractAssemblage>(instance: T, configuration?: Record<string, any>): unknown[];
59
+ abstract addGlobal(key: string, value: any): void;
59
60
  abstract has<T>(identifier: Identifier<T>): boolean;
60
- abstract require<T>(identifier: Identifier<T> | string | symbol): T;
61
+ abstract require<T>(identifier: Identifier<T> | string | symbol, configuration?: Record<string, any>): T;
61
62
  abstract concrete<T>(identifier: Identifier<T>): Concrete<T> | undefined;
62
63
  abstract tagged(...tags: string[]): any[];
64
+ abstract global(key: string): any | undefined;
63
65
  abstract dispose(): void;
64
66
  }
65
67
 
@@ -123,6 +125,7 @@ export declare interface AssemblageDefinition {
123
125
  use?: InstanceInjection<unknown>[];
124
126
  tags?: string | string[];
125
127
  metadata?: Record<string, any>;
128
+ global?: Record<string, any>;
126
129
  }
127
130
 
128
131
  /**
@@ -138,6 +141,7 @@ export declare class Assembler extends EventManager implements AbstractAssembler
138
141
  static build<T>(entry: Concrete<T>): T;
139
142
  protected injectables: Map<Identifier<unknown>, Injectable<unknown>>;
140
143
  protected objects: Map<string | symbol, unknown>;
144
+ protected globals: Map<string, any>;
141
145
  private initCache;
142
146
  /**
143
147
  * Context passed to internal classes.
@@ -230,6 +234,14 @@ export declare class Assembler extends EventManager implements AbstractAssembler
230
234
  * identifier is not marked as 'singleton', will resolve in a new instance.
231
235
  */
232
236
  tagged(...tags: string[]): unknown[];
237
+ addGlobal(key: string, value: any): void;
238
+ /**
239
+ * Get a global value by key.
240
+ *
241
+ * @param { string } key The key to get global value.
242
+ * @returns { any | undefined } The global value or `undefined` if not set.
243
+ */
244
+ global(key: string): any | undefined;
233
245
  /**
234
246
  * Size of the assembler: number of registered dependencies.
235
247
  */
@@ -245,6 +257,7 @@ export declare class Assembler extends EventManager implements AbstractAssembler
245
257
  require: AbstractAssembler['require'];
246
258
  concrete: AbstractAssembler['concrete'];
247
259
  tagged: AbstractAssembler['tagged'];
260
+ global: AbstractAssembler['global'];
248
261
  dispose: AssemblerDispose;
249
262
  on: AbstractAssembler['on'];
250
263
  once: AbstractAssembler['once'];
@@ -266,6 +279,7 @@ export declare class Assembler extends EventManager implements AbstractAssembler
266
279
  register: AbstractAssembler['register'];
267
280
  use: AbstractAssembler['use'];
268
281
  prepareInitHook: AbstractAssembler['prepareInitHook'];
282
+ addGlobal: AbstractAssembler['addGlobal'];
269
283
  emit: AbstractAssembler['emit'];
270
284
  addChannels: AbstractAssembler['addChannels'];
271
285
  removeChannels: AbstractAssembler['removeChannels'];
@@ -468,6 +482,12 @@ export declare class Assembler extends EventManager implements AbstractAssembler
468
482
  * Tags passed in assemblage's definition.
469
483
  */
470
484
  get tags(): string[];
485
+ /**
486
+ * Global injections passed in assemblage's definition.
487
+ * These injections are available in all assemblages and can be used
488
+ * to provide global services or utilities.
489
+ */
490
+ get globals(): Record<string, any> | undefined;
471
491
  /**
472
492
  * Event channels passed in assemblage's definition.
473
493
  */
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],u=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}))(),d=(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);return this.listeners.add(n,t),this}once(e,t){const n=this.cleanChannel(e);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),I=(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)},w=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=w(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);I(t[e],a,e)}else;return d(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(e){if(this.singletonInstance)return this.singletonInstance;const t=(e=>{const t=[],n=o(e.concrete),s=w(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),n=new this.concrete(...t);if(((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,n),this.isSingleton)return this.singletonInstance=n,this.privateContext.prepareInitHook(n,this.configuration),this.singletonInstance;let s={};return this.configuration&&(s=this.configuration),e&&(s={...s,...e}),P(n,"onInit",this.publicContext,s),n}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=w(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:()=>u(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,t){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(t)}}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=>d(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)=>{I(e,t,s)},exports.createConstructorDecorator=e=>t=>A(e,t),exports.decorateAssemblage=d,exports.decorateUse=I,exports.getAssemblageDefinition=e=>r(s.AssemblageDefinition,e),exports.getDecoratedParametersIndexes=w,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)},o=(e,t)=>Reflect.getOwnMetadata(`__${e}__`,t),r=e=>Reflect.getMetadata(t,e)||[],a=e=>o(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},global:{test:e=>("object"==typeof e||void 0===e)&&!Array.isArray(e),throw:()=>{throw new Error("'global' 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 o(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 o=l(t||{});return i(n.IsAssemblage,!0,e),i(s.AssemblageDefinition,o,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]}),o=e.conditionally({if:()=>e.isDefined(n),then:()=>s(this.collection[t].indexOf(n)),else:()=>delete this.collection[t]}),r=e.conditionally({if:e=>this.has(e),then:e=>this.collection[e]});return e.pipe(r,o,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 b{dispose(){this.listeners.dispose(),this.channels.clear(),e.clearInstance(this,b)}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);return this.listeners.add(n,t),this}once(e,t){const n=this.cleanChannel(e);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("*")||[],o=this.onceListeners.get(s)||[],r=this.listeners.get(s)||[],a=e.forOf(t),c=e.forOf(i),l=e.forOf(o),h=e.forOf(r);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 x=e=>()=>(t,n,s)=>{const r=o(e,t)||[];r.push(s),i(e,r,t)},m=x(exports.ReflectParamIndex.Context),C=x(exports.ReflectParamIndex.Configuration),y=x(exports.ReflectParamIndex.Definition),v=x(exports.ReflectParamIndex.Dispose),w=(e,t,n)=>{const s=o(exports.ReflectParamIndex.Use,t)||[];s.push(n),i(exports.ReflectParamIndex.Use,s,t);const r=o(exports.ReflectParamValue.UseIdentifier,t)||{};r[n]=e,i(exports.ReflectParamValue.UseIdentifier,r,t)},I=e=>{const t=(e=>o(exports.ReflectParamIndex.Context,e)||[])(e)||[],n=(e=>o(exports.ReflectParamIndex.Definition,e)||[])(e)||[],s=(e=>o(exports.ReflectParamIndex.Configuration,e)||[])(e)||[],i=(e=>o(exports.ReflectParamIndex.Dispose,e)||[])(e)||[],r=(e=>o(exports.ReflectParamIndex.Use,e)||[])(e)||[];return{Context:t,Definition:n,Configuration:s,Dispose:i,Use:r}},A=(e,n)=>r=>{const a=class extends r{constructor(...t){super(...t),e&&e.call(this,n)}};Object.defineProperty(a,"name",{value:r.name});const c=Reflect.getOwnMetadata(t,r)||[],l=I(r),h=[];for(let e=0;e<c.length;e++)if(l.Context.includes(e)){const t=o(exports.ReflectParamIndex.Context,r)||[];t.push(e),i(exports.ReflectParamIndex.Context,t,a)}else if(l.Definition.includes(e)){const t=o(exports.ReflectParamIndex.Definition,r)||[];t.push(e),i(exports.ReflectParamIndex.Definition,t,a)}else if(l.Configuration.includes(e)){const t=o(exports.ReflectParamIndex.Configuration,r)||[];t.push(e),i(exports.ReflectParamIndex.Configuration,t,a)}else if(l.Dispose.includes(e)){const t=o(exports.ReflectParamIndex.Dispose,r)||[];t.push(e),i(exports.ReflectParamIndex.Dispose,t,a),h.push(c[e])}else if(l.Use.includes(e)){const t=o(exports.ReflectParamValue.UseIdentifier,r);w(t[e],a,e)}else;return u(a,o(s.AssemblageDefinition,r))};class j{static of(e,t,n){return new j(e,t,n)}dispose(){this.singletonInstance&&(((e,t)=>{if(e.concrete.prototype instanceof b){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(e){if(this.singletonInstance)return this.singletonInstance;const t=(e=>{const t=[],n=r(e.concrete),s=I(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=o(exports.ReflectParamValue.UseIdentifier,e.concrete)[i];t.push(e.privateContext.require(n)),i++}else t.push(e.privateContext.require(r)),i++;return t})(this),n=new this.concrete(...t);if(((e,t)=>{if(e.concrete.prototype instanceof b){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,n),this.isSingleton)return this.singletonInstance=n,this.privateContext.prepareInitHook(n,this.configuration),this.singletonInstance;let s={};return this.configuration&&(s=this.configuration),e&&(s={...s,...e}),P(n,"onInit",this.publicContext,s),n}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 globals(){return f("global",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),o=e.forOf(this.objects);if(i((e=>this.privateContext.register(e))),o((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=r(e),s=I(e);let i=0;for(const o of n)s.Context.includes(i)||s.Configuration.includes(i)||s.Definition.includes(i)||s.Dispose.includes(i)||s.Use.includes(i)||t.push(o),i++;return t})(this.concrete),this.globals)for(const e in this.globals)this.privateContext.addGlobal(e,this.globals[e]);t.instance?this.singletonInstance=t.instance:this.isSingleton}}const P=(t,n,s,i)=>new Promise((o=>{const r=t[n];if(r){if(e.isAsync(r))return void r.bind(t)(s,i).then((()=>{o()}));o(r.bind(t)(s,i))}}));class R extends b{static build(e){const t=new R;((e,t,n)=>{const o=h(n);o[e]=t;const r=l(o);i(s.AssemblageDefinition,r,n)})("singleton",!0,e);const n=t.register([e]),o=t.require(n.identifier),r=t.initCache.find((e=>e.instance===o));if(!r)throw new Error("Root instance not found in assemblages cache.");const a=t.initCache.indexOf(r);t.initCache.splice(a,1);for(const s of t.initCache)P(s.instance,"onInit",t.publicContext,s.configuration);P(o,"onInit",t.publicContext,n.configuration);for(const s of t.initCache.reverse())P(s.instance,"onInited",t.publicContext,s.configuration);return P(o,"onInited",t.publicContext,n.configuration),t.initCache.length=0,o}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,t){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(t)}}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}addGlobal(e,t){if(this.globals.has(e))throw new Error(`Global value with key '${e}' has already been registered.`);this.globals.set(e,t)}global(e){return this.globals.get(e)}get size(){return this.injectables.size}constructor(){super(),this.injectables=new Map,this.objects=new Map,this.globals=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),global:this.global.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),addGlobal:this.addGlobal.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 o=i.value;i.value=async function(){return new Promise((n=>{if(this[e])o.apply(this),n();else{const s=setInterval((()=>{this[e]&&(clearInterval(s),o.apply(this),n())}),t)}}))}},exports.Configuration=C,exports.ConstructorDecorator=A,exports.Context=m,exports.Definition=y,exports.Dispose=v,exports.EventManager=b,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=>o(s.AssemblageDefinition,e),exports.getDecoratedParametersIndexes=I,exports.isAssemblage=a;
package/dist/index.mjs CHANGED
@@ -79,6 +79,13 @@ const n = {
79
79
  throw new Error(`'metadata' property must be of type 'object' or 'undefined'.`);
80
80
  },
81
81
  transform: (r)=>r
82
+ },
83
+ global: {
84
+ test: (r)=>(typeof r === 'object' || typeof r === 'undefined') && !Array.isArray(r),
85
+ throw: ()=>{
86
+ throw new Error(`'global' property must be of type 'object' or 'undefined'.`);
87
+ },
88
+ transform: (r)=>r
82
89
  }
83
90
  };
84
91
  const validateDefinition = (r)=>{
@@ -676,6 +683,9 @@ class Injectable {
676
683
  get tags() {
677
684
  return getDefinitionValue('tags', this.concrete) || [];
678
685
  }
686
+ get globals() {
687
+ return getDefinitionValue('global', this.concrete);
688
+ }
679
689
  get events() {
680
690
  return getDefinitionValue('events', this.concrete) || [];
681
691
  }
@@ -700,6 +710,11 @@ class Injectable {
700
710
  }
701
711
  });
702
712
  this.dependenciesIds = resolveDependencies(this.concrete);
713
+ if (this.globals) {
714
+ for(const t in this.globals){
715
+ this.privateContext.addGlobal(t, this.globals[t]);
716
+ }
717
+ }
703
718
  if (t.instance) {
704
719
  this.singletonInstance = t.instance;
705
720
  } else if (this.isSingleton) ;
@@ -798,7 +813,8 @@ class Assembler extends EventManager {
798
813
  throw new Error(`Class with identifier '${e.name}' has not been registered or is a circular dependency.`);
799
814
  }
800
815
  const i = this.injectables.get(e);
801
- return i.build(t);
816
+ const s = i.build(t);
817
+ return s;
802
818
  }
803
819
  }
804
820
  }
@@ -816,6 +832,15 @@ class Assembler extends EventManager {
816
832
  }
817
833
  return t;
818
834
  }
835
+ addGlobal(e, t) {
836
+ if (this.globals.has(e)) {
837
+ throw new Error(`Global value with key '${e}' has already been registered.`);
838
+ }
839
+ this.globals.set(e, t);
840
+ }
841
+ global(e) {
842
+ return this.globals.get(e);
843
+ }
819
844
  get size() {
820
845
  return this.injectables.size;
821
846
  }
@@ -823,6 +848,7 @@ class Assembler extends EventManager {
823
848
  super();
824
849
  this.injectables = new Map();
825
850
  this.objects = new Map();
851
+ this.globals = new Map();
826
852
  this.initCache = [];
827
853
  this.publicContext = {
828
854
  has: this.has.bind(this),
@@ -830,6 +856,7 @@ class Assembler extends EventManager {
830
856
  concrete: this.concrete.bind(this),
831
857
  tagged: this.tagged.bind(this),
832
858
  dispose: this.dispose.bind(this),
859
+ global: this.global.bind(this),
833
860
  on: this.on.bind(this),
834
861
  once: this.once.bind(this),
835
862
  off: this.off.bind(this),
@@ -839,6 +866,7 @@ class Assembler extends EventManager {
839
866
  ...this.publicContext,
840
867
  register: this.register.bind(this),
841
868
  use: this.use.bind(this),
869
+ addGlobal: this.addGlobal.bind(this),
842
870
  prepareInitHook: this.prepareInitHook.bind(this),
843
871
  emit: this.emit.bind(this),
844
872
  addChannels: this.addChannels.bind(this),
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.9.1",
4
+ "version": "0.9.3",
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",