assemblerjs 0.9.2 → 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
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,7 +125,7 @@ export declare interface AssemblageDefinition {
123
125
  use?: InstanceInjection<unknown>[];
124
126
  tags?: string | string[];
125
127
  metadata?: Record<string, any>;
126
- [key: string]: any;
128
+ global?: Record<string, any>;
127
129
  }
128
130
 
129
131
  /**
@@ -139,6 +141,7 @@ export declare class Assembler extends EventManager implements AbstractAssembler
139
141
  static build<T>(entry: Concrete<T>): T;
140
142
  protected injectables: Map<Identifier<unknown>, Injectable<unknown>>;
141
143
  protected objects: Map<string | symbol, unknown>;
144
+ protected globals: Map<string, any>;
142
145
  private initCache;
143
146
  /**
144
147
  * Context passed to internal classes.
@@ -231,6 +234,14 @@ export declare class Assembler extends EventManager implements AbstractAssembler
231
234
  * identifier is not marked as 'singleton', will resolve in a new instance.
232
235
  */
233
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;
234
245
  /**
235
246
  * Size of the assembler: number of registered dependencies.
236
247
  */
@@ -246,6 +257,7 @@ export declare class Assembler extends EventManager implements AbstractAssembler
246
257
  require: AbstractAssembler['require'];
247
258
  concrete: AbstractAssembler['concrete'];
248
259
  tagged: AbstractAssembler['tagged'];
260
+ global: AbstractAssembler['global'];
249
261
  dispose: AssemblerDispose;
250
262
  on: AbstractAssembler['on'];
251
263
  once: AbstractAssembler['once'];
@@ -267,6 +279,7 @@ export declare class Assembler extends EventManager implements AbstractAssembler
267
279
  register: AbstractAssembler['register'];
268
280
  use: AbstractAssembler['use'];
269
281
  prepareInitHook: AbstractAssembler['prepareInitHook'];
282
+ addGlobal: AbstractAssembler['addGlobal'];
270
283
  emit: AbstractAssembler['emit'];
271
284
  addChannels: AbstractAssembler['addChannels'];
272
285
  removeChannels: AbstractAssembler['removeChannels'];
@@ -469,6 +482,12 @@ export declare class Assembler extends EventManager implements AbstractAssembler
469
482
  * Tags passed in assemblage's definition.
470
483
  */
471
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;
472
491
  /**
473
492
  * Event channels passed in assemblage's definition.
474
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) ;
@@ -817,6 +832,15 @@ class Assembler extends EventManager {
817
832
  }
818
833
  return t;
819
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
+ }
820
844
  get size() {
821
845
  return this.injectables.size;
822
846
  }
@@ -824,6 +848,7 @@ class Assembler extends EventManager {
824
848
  super();
825
849
  this.injectables = new Map();
826
850
  this.objects = new Map();
851
+ this.globals = new Map();
827
852
  this.initCache = [];
828
853
  this.publicContext = {
829
854
  has: this.has.bind(this),
@@ -831,6 +856,7 @@ class Assembler extends EventManager {
831
856
  concrete: this.concrete.bind(this),
832
857
  tagged: this.tagged.bind(this),
833
858
  dispose: this.dispose.bind(this),
859
+ global: this.global.bind(this),
834
860
  on: this.on.bind(this),
835
861
  once: this.once.bind(this),
836
862
  off: this.off.bind(this),
@@ -840,6 +866,7 @@ class Assembler extends EventManager {
840
866
  ...this.publicContext,
841
867
  register: this.register.bind(this),
842
868
  use: this.use.bind(this),
869
+ addGlobal: this.addGlobal.bind(this),
843
870
  prepareInitHook: this.prepareInitHook.bind(this),
844
871
  emit: this.emit.bind(this),
845
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.2",
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",