assemblerjs 0.0.97 → 0.0.98

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
@@ -5,18 +5,43 @@ declare interface Abstract<T> extends Function {
5
5
  prototype: T;
6
6
  }
7
7
 
8
+ /**
9
+ * Base abstract class to implement an assemblage.
10
+ */
8
11
  export declare abstract class AbstractAssemblage {
9
12
  [key: string]: any;
10
- abstract onInit?(): void | Promise<void>;
11
- abstract onDispose?(): void;
13
+ /**
14
+ * Called on concrete class registration by assembler.
15
+ *
16
+ * @param { AssemblerContext } context The assembler's context.
17
+ */
18
+ static onRegister(context: AssemblerContext): void;
19
+ /**
20
+ * Called when class is instantiated.
21
+ *
22
+ * @param { AssemblerContext } context The assembler's context.
23
+ */
24
+ abstract onInit?(context: AssemblerContext): void | Promise<void>;
25
+ /**
26
+ * Called when instance of class is disposed.
27
+ *
28
+ * @param { AssemblerContext } context The assembler's context.
29
+ */
30
+ abstract onDispose?(context: AssemblerContext): void;
31
+ /**
32
+ * Dispose the assemblage instance.
33
+ */
34
+ abstract dispose?(): void;
12
35
  }
13
36
 
14
37
  export declare abstract class AbstractAssembler {
15
38
  abstract context: AssemblerContext;
16
- abstract register<T>(injection: Injection<T>): void;
39
+ abstract size: number;
40
+ abstract register<T>(injection: Injection<T>): Injectable<T>;
17
41
  abstract has<T>(identifier: Identifier<T>): boolean;
18
42
  abstract require<T>(identifier: Identifier<T>): T;
19
43
  abstract tagged(...tags: string[]): any[];
44
+ abstract dispose(): void;
20
45
  }
21
46
 
22
47
  /**
@@ -46,6 +71,7 @@ export declare class Assembler implements AbstractAssembler {
46
71
  readonly context: AssemblerContext;
47
72
  static build(entry: Concrete<any>): Assembler;
48
73
  private constructor();
74
+ dispose(): void;
49
75
  /**
50
76
  * Recursively register an `Injection` tuple and its inner injected dependencies.
51
77
  *
@@ -74,33 +100,17 @@ export declare class Assembler implements AbstractAssembler {
74
100
  * identifier is not marked as 'singleton', will resolve in a new instance.
75
101
  */
76
102
  tagged(...tags: string[]): unknown[];
77
- }
78
-
79
- export declare class AssemblerContext {
80
103
  /**
81
- * User-defined data. Can be used to add properties to context after creation.
104
+ * Size of the assembler: number of registered dependencies.
82
105
  */
83
- readonly userData: Record<string, any>;
106
+ get size(): number;
107
+ }
108
+
109
+ export declare interface AssemblerContext {
84
110
  register: AbstractAssembler['register'];
85
111
  has: AbstractAssembler['has'];
86
112
  require: AbstractAssembler['require'];
87
113
  tagged: AbstractAssembler['tagged'];
88
- constructor(assembler: AbstractAssembler);
89
- /**
90
- * Add a value to user-defined data.
91
- *
92
- * @param { string } key The key to add.
93
- * @param { any } value The value to add.
94
- * @returns { this } This context.
95
- */
96
- set(key: string, value: any): this;
97
- /**
98
- * Get a value in user-defined data for given key.
99
- *
100
- * @param { string } key The key to get from user-defined data.
101
- * @returns { any } The result.
102
- */
103
- get(key: string): any;
104
114
  }
105
115
 
106
116
  /**
@@ -143,6 +153,8 @@ Record<string, any>
143
153
 
144
154
  export declare const Context: () => ParameterDecorator;
145
155
 
156
+ export declare const Definition: () => ParameterDecorator;
157
+
146
158
  /**
147
159
  * An identifier can be an abstract or a concrete class.
148
160
  */
@@ -154,25 +166,29 @@ declare class Injectable<T> {
154
166
  readonly concrete: Concrete<T>;
155
167
  readonly configuration: Record<string, any>;
156
168
  singleton: T | undefined;
169
+ private dependenciesIds;
157
170
  static of<TNew>(injection: Injection<TNew>, context: AssemblerContext): Injectable<TNew>;
158
171
  private constructor();
172
+ /**
173
+ * Dispose the injectable by deleting its singleton if exists.
174
+ */
175
+ dispose(): void;
159
176
  /**
160
177
  * Instantiate the assemblage or get its singleton instance.
161
178
  *
162
- * @param { ...any[] } args The arguments to be passed to asssemblage's constructor.
163
179
  * @returns { T } The assemblage instance.
164
180
  */
165
181
  build(): T;
166
182
  /**
167
- * Resolve dependencies passed as parameters in constructor.
168
- *
169
- * @returns { (Identifier<unknown> | any)[] } An array of parameters.
183
+ * Injectable assemblage's dependencies passed as 'constructor' parameters.
170
184
  */
171
- private resolveDependencies;
185
+ get dependencies(): (Identifier<unknown> | any)[];
186
+ /**
187
+ * Metadatas passed in assemblage's definition or in its parent definition.
188
+ */
189
+ get definition(): AssemblageDefinition;
172
190
  /**
173
191
  * `true` if assemblage is a singleton.
174
- *
175
- * @todo Change assembler to avoid checking instance.
176
192
  */
177
193
  get isSingleton(): boolean;
178
194
  /**
@@ -180,17 +196,13 @@ declare class Injectable<T> {
180
196
  */
181
197
  get injections(): Injection<unknown>[];
182
198
  /**
183
- * Injectable assemblage's dependencies passed as 'constructor' parameters.
184
- */
185
- get dependencies(): (Identifier<unknown> | any)[];
186
- /**
187
- * Tags passed in assemblage's definition or in its parent definition.
199
+ * Tags passed in assemblage's definition.
188
200
  */
189
201
  get tags(): string[];
190
202
  /**
191
- * Metadatas passed in assemblage's definition or in its parent definition.
203
+ * Event channels passed in assemblage's definition.
192
204
  */
193
- get metadata(): Record<string, any>;
205
+ get events(): string[];
194
206
  }
195
207
 
196
208
  /**
@@ -198,8 +210,6 @@ declare class Injectable<T> {
198
210
  */
199
211
  declare type Injection<T> = BaseInjection<T> | ConfiguredInjection<T> | ConcreteInjection<T> | ConcreteConfiguredInjection<T>;
200
212
 
201
- export declare const Metadata: () => ParameterDecorator;
202
-
203
213
  /**
204
214
  * An array of fixed length typed values.
205
215
  *
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="__",t="__",i="is_singleton",r="context_param_index",n="config_param_index",s="metadata_param_index",o=(i,r,n)=>{Reflect.defineMetadata(`${e}${i}${t}`,r,n)},a=(i,r)=>Reflect.getMetadata(`${e}${i}${t}`,r),c=(i,r)=>Reflect.getOwnMetadata(`${e}${i}${t}`,r);const h=e=>e&&"function"==typeof e&&void 0!==e.constructor,u=e=>t=>e.if(t)?e.then(t):e.else?e.else(t):void 0,l=e=>{const t=()=>h(e[0])&&(e=>"object"==typeof e&&!Array.isArray(e)&&!h(e))(e[1]);return((...e)=>t=>e.reduce(((e,t)=>t(e)),t))(u({if:()=>h(e[0])&&h(e[1]),then:()=>({identifier:e[0],concrete:e[1],configuration:{}})}),u({if:()=>t(),then:()=>({identifier:e[0],concrete:e[0],configuration:e[1]}),else:e=>e}))()},d=e=>((e,t)=>(i,...r)=>e[i]?e[i](...r):t?t(i,...r):void 0)({1:()=>(e=>({identifier:e[0],concrete:e[0],configuration:{}}))(e),2:()=>l(e),3:()=>(e=>({identifier:e[0],concrete:e[1],configuration:e[2]}))(e)},(()=>{throw new Error("Injection tuple must be of length 1, 2 or 3.")}))(e.length);function f(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}class g{static of(e,t){return new g(e,t)}build(){if(this.singleton)return this.singleton;const e=this.resolveDependencies(),t=new this.concrete(...e);return this.isSingleton&&(this.singleton=t),t}resolveDependencies(){const e=[],t=c(r,this.concrete)||[],i=c(n,this.concrete)||[],o=a(s,this.concrete)||[];let h=0;for(const r of this.dependencies)t.includes(h)?(e.push(this.context),h++):i.includes(h)?(e.push(this.configuration),h++):o.includes(h)?(e.push(this.metadata),h++):(e.push(this.context.require(r)),h++);return e}get isSingleton(){return c(i,this.concrete)||!1}get injections(){return c("inject",this.concrete)||[]}get dependencies(){return Reflect.getMetadata("design:paramtypes",this.concrete)||[]}get tags(){return a("tags",this.concrete)||[]}get metadata(){return a("metadata",this.concrete)||{}}constructor(e,t){f(this,"context",void 0),f(this,"identifier",void 0),f(this,"concrete",void 0),f(this,"configuration",void 0),f(this,"singleton",void 0),this.context=t;const i=d(e);this.identifier=i.identifier,this.concrete=i.concrete,this.configuration=i.configuration;for(const r of this.injections)this.context.register(r)}}function b(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}class p{set(e,t){if(this.userData[e])throw new Error(`Key '${e}' is already defined in context's user data.`);return this.userData[e]=t,this}get(e){return this.userData[e]}constructor(e){b(this,"userData",{}),b(this,"register",void 0),b(this,"has",void 0),b(this,"require",void 0),b(this,"tagged",void 0),this.register=e.register.bind(e),this.has=e.has.bind(e),this.require=e.require.bind(e),this.tagged=e.tagged.bind(e)}}function m(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}class w{static build(e){return new w(e)}register(e){const t=g.of(e,this.context);if(this.has(t.identifier))throw new Error(`An assemblage is already registered with identifier '${t.identifier.name}'.`);return this.injectables.set(t.identifier,t),t}has(e){return this.injectables.has(e)}require(e){if(!this.injectables.has(e))throw new Error(`Assemblage with identifier '${e.name}' has not been registered.`);return this.injectables.get(e).build()}tagged(...e){const t=[];for(const i of e)for(const[e,r]of this.injectables)r.tags.includes(i)&&t.push(r.build());return t}constructor(e){m(this,"injectables",new Map),m(this,"context",void 0),this.context=new p(this),o(i,!0,e);return this.register([e]).build()}}const y=e=>()=>(t,i,r)=>{const n=c(e,t)||[];n.push(r),o(e,n,t)},x=y(r),j=y(n),A=y(s);exports.AbstractAssemblage=class{},exports.AbstractAssembler=class{},exports.Assemblage=e=>{const t=e||{};return e=>{o("is_assemblage",!0,e),o(i,!0,e);for(const r in t)if(t.hasOwnProperty(r))switch(r){case"singleton":!1===t.singleton&&o(i,!1,e);break;case"controller":if(!0===t.controller){if("string"!=typeof t.path)throw new Error(`Controller assemblage '${e.name}' must define a path.`);o("is_controller",!0,e)}break;case"tags":if(void 0!==t.tags)if("string"==typeof t.tags)o("tags",[t.tags],e);else{if(!Array.isArray(t.tags))throw new Error("Assemblage's 'tags' must be o type 'string' or 'Array'.");o("tags",t.tags,e)}break;case"inject":if(!Array.isArray(t.inject))throw new Error("Assemblage's definition 'inject' property must be an array of 'Injection' tuples.");for(const e of t.inject)if(!Array.isArray(e))throw new Error("'Injection' must be an 'Array'.");default:o(r,t[r],e)}return e}},exports.Assembler=w,exports.AssemblerContext=p,exports.Configuration=j,exports.Context=x,exports.Metadata=A;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="assemblage_definition",t="context_param_index",n="config_param_index",r="definition_param_index",i=(e,t,n)=>{Reflect.defineMetadata(`__${e}__`,t,n)},s=(e,t)=>Reflect.getOwnMetadata(`__${e}__`,t),o=e=>Reflect.getMetadata("design:paramtypes",e)||[],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},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},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},controller:{test:e=>"boolean"==typeof e||void 0===e,throw:()=>{throw new Error("'controller' property must be of type 'boolean' or 'undefined'.")},transform:e=>e},path:{test:e=>"string"==typeof e||void 0===e,throw:()=>{throw new Error("'path' property must be of type 'string' or 'undefined'.")},transform:e=>{if(e){let t=e.replace(/\/+/g,"/").replace(/\s/g,"");if(t.startsWith("/")||(t=`/${t}`),t.endsWith("/")){const e=t.length-1;t=t.split("").splice(0,e).join("")}return t}return 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.`);const e=c[n].test,r=c[n].throw,i=c[n].transform;if(e(t[n])||r(),"controller"===n&&!Object.keys(t).includes("path"))throw new Error("Assemblage marked as 'controller' must define a 'path'.");if("path"===n&&!Object.keys(t).includes("controller"))throw new Error("Assemblage that defines a 'path' must be marked as 'controller'.");t[n]=i(t[n])}return t},a=t=>s(e,t),h=(e,t)=>a(t)[e],u=e=>()=>(t,n,r)=>{const o=s(e,t)||[];o.push(r),i(e,o,t)},f=u(t),d=u(n),g=u(r),p=e=>{const i=(e=>s(t,e)||[])(e),o=(e=>s(r,e)||[])(e),c=(e=>s(n,e)||[])(e);return{context:i,definition:o,configuration:c}};const b=(...e)=>{},y=(...e)=>t=>{if(e.includes(typeof t))return typeof t},m=e=>!(e=>void 0===e)(e)&&!(e=>null===e)(e),w=e=>e&&"function"==typeof e&&void 0!==e.constructor,v=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,j=(e,...t)=>{t.map(((e,n)=>{const r=/\S/.test(e);return r&&(t[n]=t[n].trim()),r?-1:n})).filter((e=>e>=0)).every((e=>{t[e]=" ",((e,t,n)=>{const r=e[t];e.splice(t,1),e.splice(n,0,r)})(t,e,t.length-1)})),t=(e=>Array.from(new Set(e)))(t);const n=new RegExp(`[^A-Za-zÀ-ÖØ-öø-ÿ0-9${t.join("")}]`,"gi");return e.replace(n,"")},O=(...e)=>t=>e.reduce(((e,t)=>t(e)),t),x=e=>t=>e.if(t)?e.then(t):e.else?e.else(t):void 0,A=e=>t=>{const n=Array.isArray(e)?e=>parseInt(e):b;for(const[r,i]of Object.entries(e))t(i,n(r))},E=(e,t)=>{const n=new Proxy(e,{get:function(n,r){return r===Symbol.iterator?n[Symbol.iterator].bind(n):((e,t)=>[...Object.getOwnPropertyNames(t.prototype),...Object.getOwnPropertyNames(Object.getPrototypeOf(e)),...Object.getOwnPropertyNames(e)])(e,t).includes(r)?n[r]:n.collection[r]},set:function(e,t,n){return Reflect.set(e,t,n)}});return n},P=(e,t)=>{const n=e;for(const r of((e,t)=>[...Object.getOwnPropertyNames(t.prototype),...Object.getOwnPropertyNames(Object.getPrototypeOf(e)),...Object.getOwnPropertyNames(e)])(e,t))delete n[r]},C=(e,t,n)=>new Promise((r=>{const i=e[t];if(i){if(v(i))return void i.bind(e)(n).then((()=>{r()}));r(i.bind(e)(n))}})),_=e=>{const t=()=>w(e[0])&&(e=>"object"==typeof e&&!Array.isArray(e)&&!w(e))(e[1]);return O(x({if:()=>w(e[0])&&w(e[1]),then:()=>({identifier:e[0],concrete:e[1],configuration:{}})}),x({if:()=>t(),then:()=>({identifier:e[0],concrete:e[0],configuration:e[1]}),else:e=>e}))()},S=e=>((e,t)=>(n,...r)=>e[n]?e[n](...r):t?t(n,...r):void 0)({1:()=>(e=>({identifier:e[0],concrete:e[0],configuration:{}}))(e),2:()=>_(e),3:()=>(e=>({identifier:e[0],concrete:e[1],configuration:e[2]}))(e)},(()=>{throw new Error("Injection tuple must be of length 1, 2 or 3.")}))(e.length);let $=Symbol.iterator;class k{dispose(){P(this,k)}add(...e){const t=e=>this.collection[e.channel].push(e.listener),n=x({if:()=>2===e.length,then:()=>({channel:e[0],listener:e[1]}),else:()=>{const t=e[0];return{channel:t[0],listener:t[1]}}}),r=x({if:e=>!m(this.collection[e.channel]),then:e=>{this.collection[e.channel]=[],t(e)},else:e=>{t(e)}});return O(n,r)(),this}remove(e,t){const n=t=>this.collection[e].splice(t,1),r=x({if:()=>this.collection[e]&&0===this.collection[e].length,then:()=>delete this.collection[e]}),i=x({if:()=>m(t),then:()=>n(this.collection[e].indexOf(t)),else:()=>delete this.collection[e]}),s=x({if:e=>this.has(e),then:e=>this.collection[e]});return O(s,i,r)(),this}has(...e){return y("string")(e[0])?Object.keys(this.collection).includes(e[0]):!!y("function")(e[0])&&Object.values(this.collection).flat().includes(e[0])}get(...e){return y("string")(e[0])?this.collection[e[0]]:y("function")(e[0])?Object.values(this.collection).flat().filter((t=>t===e[0])):[]}clear(){const e=(e=>t=>{const n=Array.isArray(e)?e=>parseInt(e):e=>e;for(const r in e)t(n(r))})(this.collection),t=e=>A(this.collection[e])((t=>this.remove(e,t)));return e((e=>t(e))),this}get listeners(){return Object.values(this.collection).flat()}get channels(){return Object.keys(this.collection)}get length(){return Object.values(this.collection).flat().length}[$](){let e=-1;const t=this.collection?Object.keys(this.collection):[];return{next:()=>({value:t[++e],done:!(e in t)})}}constructor(){!function(e,t,n){t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}(this,"collection",{});return E(this,k)}}function I(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class L{dispose(){this.listeners.dispose(),this.channels.clear(),P(this,L)}addChannels(...e){return A(e)((e=>{const t=this.cleanChannel(e);if(this.channels.has(t))throw new Error(`Channel '${t}' already exists.`);this.channels.add(t)})),this}removeChannels(...e){return A(e)((e=>{const t=this.cleanChannel(e);"*"!==t&&this.channels.has(t)&&(this.channels.delete(t),this.listeners.remove(t),this.onceListeners.remove(t))})),this}on(e,t){const n=this.cleanChannel(e);if(!this.channels.has(n))throw new Error(`Channel '${n}' was not registered.`);return this.listeners.add(n,t),this}once(e,t){const n=this.cleanChannel(e);if(!this.channels.has(n))throw new Error(`Channel '${n}' was not registered.`);return this.onceListeners.add(n,t),this}off(e,t){const n=this.cleanChannel(e);return this.listeners.remove(n,t),this}emit(e,...t){const n=this.cleanChannel(e);if(this.channels.has(n)){const e=this.onceListeners.get("*")||[],r=this.listeners.get("*")||[],i=this.onceListeners.get(n)||[],s=this.listeners.get(n)||[],o=A(e),c=A(r),l=A(i),a=A(s);o((e=>{this.run(e,...t),this.onceListeners.remove("*",e)})),c((e=>{this.run(e,...t)})),l((e=>{this.run(e,...t),this.onceListeners.remove(n,e)})),a((e=>{this.run(e,...t)}))}return this}run(e,...t){if(v(e)){return e(...t).then((()=>Promise.resolve()))}e(...t)}cleanChannel(e){return j(e,"*")}constructor(...e){I(this,"listeners",new k),I(this,"onceListeners",new k),I(this,"channels",new Set(["*"])),this.addChannels(...e)}}function R(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class N{static of(e,t){return new N(e,t)}dispose(){this.singleton&&C(this.singleton,"onDispose",this.context),P(this,N)}build(){if(this.singleton)return this.singleton;const e=((e,t,n,r)=>{const i=[],s=o(e),c=p(e);let l=0;for(const o of s)c.context.includes(l)?(i.push(t),l++):c.configuration.includes(l)?(i.push(r),l++):c.definition.includes(l)?(i.push(n),l++):(i.push(t.require(o)),l++);return i})(this.concrete,this.context,this.definition,this.configuration),t=new this.concrete(...e);return this.concrete.prototype instanceof L&&t.addChannels(...this.events),C(t,"onInit",this.context),this.isSingleton&&(this.singleton=t),t}get dependencies(){return this.dependenciesIds}get definition(){return a(this.concrete)||{}}get isSingleton(){return h("singleton",this.concrete)||!0}get injections(){return h("inject",this.concrete)||[]}get tags(){return h("tags",this.concrete)||[]}get events(){return h("events",this.concrete)||[]}constructor(e,t){R(this,"context",void 0),R(this,"identifier",void 0),R(this,"concrete",void 0),R(this,"configuration",void 0),R(this,"singleton",void 0),R(this,"dependenciesIds",void 0),this.context=t,this.dependenciesIds=[];const n=S(e);this.identifier=n.identifier,this.concrete=n.concrete,this.configuration=n.configuration;for(const r of this.injections)this.context.register(r);this.dependenciesIds=(e=>{const t=[],n=o(e),r=p(e);let i=0;for(const s of n)r.context.includes(i)||r.configuration.includes(i)||r.definition.includes(i)||t.push(s),i++;return t})(this.concrete),this.isSingleton&&this.build()}}function q(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class M{static build(e){return new M(e)}dispose(){for(const[e,t]of this.injectables)t.dispose();P(this,M)}register(e){const t=N.of(e,this.context);if(this.has(t.identifier))throw new Error(`An assemblage is already registered with identifier '${t.identifier.name}'.`);return this.injectables.set(t.identifier,t),C(t.concrete,"onRegister",this.context),t}has(e){return this.injectables.has(e)}require(e){if(!this.injectables.has(e))throw new Error(`Assemblage with identifier '${e.name}' has not been registered.`);return this.injectables.get(e).build()}tagged(...e){const t=[];for(const n of e)for(const[e,r]of this.injectables)r.tags.includes(n)&&t.push(r.build());return t}get size(){return this.injectables.size}constructor(e){q(this,"injectables",new Map),q(this,"context",void 0),this.context={register:this.register.bind(this),has:this.has.bind(this),require:this.require.bind(this),tagged:this.tagged.bind(this)},((e,t,n)=>{const r=a(n);r[e]=t,l(r)})("singleton",!0,e);const t=this.register([e]);return this.require(t.identifier)}}exports.AbstractAssemblage=class{static onRegister(e){}},exports.AbstractAssembler=class{},exports.Assemblage=t=>{const n=t?l(t):{};return t=>(i("is_assemblage",!0,t),i(e,n,t),t)},exports.Assembler=M,exports.Configuration=d,exports.Context=f,exports.Definition=g;
package/dist/index.mjs CHANGED
@@ -1,101 +1,272 @@
1
1
  class AbstractAssemblage {
2
+ static onRegister(s) {}
2
3
  }
3
4
 
4
- const ReflectCustomPrefix = '__';
5
- const ReflectCustomSuffix = '__';
6
5
  const ReflectParamTypes = 'design:paramtypes';
6
+ const ReflectPrefix = '__';
7
+ const ReflectSuffix = '__';
7
8
  const ReflectIsAssemblageFlag = `is_assemblage`;
8
- const ReflectIsSingletonFlag = `is_singleton`;
9
- const ReflectIsControllerFlag = `is_controller`;
9
+ const ReflectDefinition = 'assemblage_definition';
10
10
  const ReflectContextParamIndex = `context_param_index`;
11
11
  const ReflectConfigurationParamIndex = `config_param_index`;
12
- const ReflectMetadataParamIndex = `metadata_param_index`;
12
+ const ReflectDefinitionParamIndex = `definition_param_index`;
13
+ const defineCustomMetadata = (e, t, a)=>{
14
+ Reflect.defineMetadata(`${ReflectPrefix}${e}${ReflectSuffix}`, t, a);
15
+ };
16
+ const getOwnCustomMetadata = (e, t)=>{
17
+ return Reflect.getOwnMetadata(`${ReflectPrefix}${e}${ReflectSuffix}`, t);
18
+ };
19
+ const getParamTypes = (e)=>{
20
+ return Reflect.getMetadata(ReflectParamTypes, e) || [];
21
+ };
13
22
 
14
- const defineCustomMetadata = (a, o, n)=>{
15
- Reflect.defineMetadata(`${ReflectCustomPrefix}${a}${ReflectCustomSuffix}`, o, n);
23
+ const r = {
24
+ singleton: {
25
+ test: (t)=>typeof t === 'boolean' || typeof t === 'undefined',
26
+ throw: ()=>{
27
+ throw new Error(`'singleton' property must be of type 'boolean' or 'undefined'.`);
28
+ },
29
+ transform: (t)=>typeof t === 'undefined' ? true : false
30
+ },
31
+ events: {
32
+ test: (t)=>typeof t === 'undefined' || Array.isArray(t) && t.every((t)=>typeof t === 'string'),
33
+ throw: ()=>{
34
+ throw new Error(`'events' property must be an array of strings or 'undefined'.`);
35
+ },
36
+ transform: (t)=>t
37
+ },
38
+ inject: {
39
+ test: (t)=>typeof t === 'undefined' || Array.isArray(t) && t.every((t)=>Array.isArray(t) && t.length >= 1 && t.length <= 3),
40
+ throw: ()=>{
41
+ throw new Error(`'inject' property must be an array of tuples of length 1, 2 or 3.`);
42
+ },
43
+ transform: (t)=>t
44
+ },
45
+ tags: {
46
+ test: (t)=>typeof t === 'undefined' || typeof t === 'string' || Array.isArray(t) && t.every((t)=>typeof t === 'string'),
47
+ throw: ()=>{
48
+ throw new Error(`'tags' property must be a string or an array of strings.`);
49
+ },
50
+ transform: (t)=>typeof t === 'string' ? [
51
+ t
52
+ ] : t
53
+ },
54
+ controller: {
55
+ test: (t)=>typeof t === 'boolean' || typeof t === 'undefined',
56
+ throw: ()=>{
57
+ throw new Error(`'controller' property must be of type 'boolean' or 'undefined'.`);
58
+ },
59
+ transform: (t)=>t
60
+ },
61
+ path: {
62
+ test: (t)=>typeof t === 'string' || typeof t === 'undefined',
63
+ throw: ()=>{
64
+ throw new Error(`'path' property must be of type 'string' or 'undefined'.`);
65
+ },
66
+ transform: (t)=>{
67
+ if (t) {
68
+ let e = t.replace(/\/+/g, '/').replace(/\s/g, '');
69
+ if (!e.startsWith('/')) {
70
+ e = `/${e}`;
71
+ }
72
+ if (e.endsWith('/')) {
73
+ const t = e.length - 1;
74
+ e = e.split('').splice(0, t).join('');
75
+ }
76
+ return e;
77
+ }
78
+ return t;
79
+ }
80
+ },
81
+ metadata: {
82
+ test: (t)=>(typeof t === 'object' || typeof t === 'undefined') && !Array.isArray(t),
83
+ throw: ()=>{
84
+ throw new Error(`'metadata' property must be of type 'object' or 'undefined'.`);
85
+ },
86
+ transform: (t)=>t
87
+ }
16
88
  };
17
- const getCustomMetadata = (a, o)=>{
18
- return Reflect.getMetadata(`${ReflectCustomPrefix}${a}${ReflectCustomSuffix}`, o);
89
+ const validateDefinition = (t)=>{
90
+ const e = {
91
+ ...t
92
+ };
93
+ for(const t in e){
94
+ if (!Object.keys(r).includes(t)) {
95
+ throw new Error(`Property '${t}' is not a valid assemblage definition property.`);
96
+ }
97
+ const o = r[t].test;
98
+ const n = r[t].throw;
99
+ const s = r[t].transform;
100
+ if (!o(e[t])) {
101
+ n();
102
+ }
103
+ if (t === 'controller' && !Object.keys(e).includes('path')) {
104
+ throw new Error(`Assemblage marked as 'controller' must define a 'path'.`);
105
+ }
106
+ if (t === 'path' && !Object.keys(e).includes('controller')) {
107
+ throw new Error(`Assemblage that defines a 'path' must be marked as 'controller'.`);
108
+ }
109
+ e[t] = s(e[t]);
110
+ }
111
+ return e;
19
112
  };
20
- const getOwnCustomMetadata = (a, o)=>{
21
- return Reflect.getOwnMetadata(`${ReflectCustomPrefix}${a}${ReflectCustomSuffix}`, o);
113
+ const getDefinition = (r)=>{
114
+ return getOwnCustomMetadata(ReflectDefinition, r);
115
+ };
116
+ const getDefinitionValue = (t, e)=>{
117
+ const r = getDefinition(e);
118
+ return r[t];
119
+ };
120
+ const setDefinitionValue = (t, e, r)=>{
121
+ const o = getDefinition(r);
122
+ o[t] = e;
123
+ const n = validateDefinition(o);
124
+ return n;
22
125
  };
23
126
 
24
127
  const Assemblage = (o)=>{
25
- const n = o || {};
128
+ const s = o ? validateDefinition(o) : {};
26
129
  return (o)=>{
27
130
  defineCustomMetadata(ReflectIsAssemblageFlag, true, o);
28
- defineCustomMetadata(ReflectIsSingletonFlag, true, o);
29
- for(const r in n){
30
- if (n.hasOwnProperty(r)) {
31
- switch(r){
32
- case 'singleton':
33
- {
34
- if (n.singleton === false) {
35
- defineCustomMetadata(ReflectIsSingletonFlag, false, o);
36
- }
37
- break;
38
- }
39
- case 'controller':
40
- {
41
- if (n.controller === true) {
42
- if (typeof n.path !== 'string') {
43
- throw new Error(`Controller assemblage '${o.name}' must define a path.`);
44
- }
45
- defineCustomMetadata(ReflectIsControllerFlag, true, o);
46
- }
47
- break;
48
- }
49
- case 'tags':
50
- {
51
- if (typeof n.tags !== 'undefined') {
52
- if (typeof n.tags === 'string') {
53
- defineCustomMetadata('tags', [
54
- n.tags
55
- ], o);
56
- } else if (Array.isArray(n.tags)) {
57
- defineCustomMetadata('tags', n.tags, o);
58
- } else {
59
- throw new Error(`Assemblage's 'tags' must be o type 'string' or 'Array'.`);
60
- }
61
- }
62
- break;
63
- }
64
- case 'inject':
65
- {
66
- if (!Array.isArray(n.inject)) {
67
- throw new Error(`Assemblage's definition 'inject' property must be an array of 'Injection' tuples.`);
68
- }
69
- for (const r of n.inject){
70
- if (!Array.isArray(r)) {
71
- throw new Error(`'Injection' must be an 'Array'.`);
72
- }
73
- }
74
- }
75
- default:
76
- {
77
- defineCustomMetadata(r, n[r], o);
78
- }
79
- }
80
- }
81
- }
131
+ defineCustomMetadata(ReflectDefinition, s, o);
82
132
  return o;
83
133
  };
84
134
  };
85
135
 
136
+ const i$1 = (t)=>()=>{
137
+ return (n, e, i)=>{
138
+ const s = getOwnCustomMetadata(t, n) || [];
139
+ s.push(i);
140
+ defineCustomMetadata(t, s, n);
141
+ };
142
+ };
143
+ const s = i$1(ReflectContextParamIndex);
144
+ const x = i$1(ReflectConfigurationParamIndex);
145
+ const c$1 = i$1(ReflectDefinitionParamIndex);
146
+ const getContextIndex = (t)=>{
147
+ return getOwnCustomMetadata(ReflectContextParamIndex, t) || [];
148
+ };
149
+ const getConfigurationIndex = (n)=>{
150
+ return getOwnCustomMetadata(ReflectConfigurationParamIndex, n) || [];
151
+ };
152
+ const getDefinitionIndex = (t)=>{
153
+ return getOwnCustomMetadata(ReflectDefinitionParamIndex, t) || [];
154
+ };
155
+ const getDecoratedParametersIndexes = (t)=>{
156
+ const n = getContextIndex(t);
157
+ const e = getDefinitionIndex(t);
158
+ const o = getConfigurationIndex(t);
159
+ return {
160
+ context: n,
161
+ definition: e,
162
+ configuration: o
163
+ };
164
+ };
165
+
86
166
  class AbstractAssembler {
87
167
  }
88
168
 
89
169
  const NoOp = (...e)=>{};
170
+ const isOfType = (...e)=>(t)=>{
171
+ if (!e.includes(typeof t)) return undefined;
172
+ return typeof t;
173
+ };
174
+ const isUndefined = (e)=>typeof e === 'undefined';
175
+ const isNull = (e)=>e === null;
176
+ const isDefined = (e)=>!isUndefined(e) && !isNull(e);
90
177
  const isClass = (e)=>{
91
178
  return e && typeof e === 'function' && typeof e.constructor !== 'undefined';
92
179
  };
93
180
  const isObject = (e)=>typeof e === 'object' && !Array.isArray(e) && !isClass(e);
94
- const switchCase = (e, t)=>(o, ...s)=>e[o] ? e[o](...s) : t ? t(o, ...s) : NoOp();
181
+ const isAsync = (e)=>typeof e === 'function' && e.constructor.name === 'AsyncFunction';
182
+ const moveArrayItem = (e, t, r)=>{
183
+ const o = e[t];
184
+ e.splice(t, 1);
185
+ e.splice(r, 0, o);
186
+ return e;
187
+ };
188
+ const dedupeArray = (e)=>Array.from(new Set(e));
189
+ const onlyAlphanumeric = (e, ...t)=>{
190
+ t.map((e, r)=>{
191
+ const o = /\S/.test(e);
192
+ if (o) t[r] = t[r].trim();
193
+ return !o ? r : -1;
194
+ }).filter((e)=>e >= 0).every((e)=>{
195
+ t[e] = ' ';
196
+ moveArrayItem(t, e, t.length - 1);
197
+ });
198
+ t = dedupeArray(t);
199
+ const r = new RegExp(`[^A-Za-zÀ-ÖØ-öø-ÿ0-9${t.join('')}]`, 'gi');
200
+ return e.replace(r, '');
201
+ };
202
+ const switchCase = (e, t)=>(r, ...o)=>e[r] ? e[r](...o) : t ? t(r, ...o) : NoOp();
95
203
  const pipe = (...e)=>(t)=>e.reduce((e, t)=>t(e), t);
96
204
  const conditionally = (e)=>(t)=>{
97
205
  return e.if(t) ? e.then(t) : e.else ? e.else(t) : undefined;
98
206
  };
207
+ const forOf = (e)=>(t)=>{
208
+ const r = Array.isArray(e) ? (e)=>parseInt(e) : NoOp;
209
+ for (const [o, n] of Object.entries(e)){
210
+ t(n, r(o));
211
+ }
212
+ };
213
+ const forIn = (e)=>(t)=>{
214
+ const r = Array.isArray(e) ? (e)=>parseInt(e) : (e)=>e;
215
+ for(const o in e){
216
+ t(r(o));
217
+ }
218
+ };
219
+ const e$3 = (e, t)=>{
220
+ return [
221
+ ...Object.getOwnPropertyNames(t.prototype),
222
+ ...Object.getOwnPropertyNames(Object.getPrototypeOf(e)),
223
+ ...Object.getOwnPropertyNames(e)
224
+ ];
225
+ };
226
+ const proxifyIterable = (t, r)=>{
227
+ const o = new Proxy(t, {
228
+ get: function(o, n) {
229
+ if (n === Symbol.iterator) {
230
+ return o[Symbol.iterator].bind(o);
231
+ } else if (!e$3(t, r).includes(n)) {
232
+ return o.collection[n];
233
+ }
234
+ return o[n];
235
+ },
236
+ set: function(e, t, r) {
237
+ return Reflect.set(e, t, r);
238
+ }
239
+ });
240
+ return o;
241
+ };
242
+ const clearInstance = (e, t)=>{
243
+ const r = (e, t)=>{
244
+ return [
245
+ ...Object.getOwnPropertyNames(t.prototype),
246
+ ...Object.getOwnPropertyNames(Object.getPrototypeOf(e)),
247
+ ...Object.getOwnPropertyNames(e)
248
+ ];
249
+ };
250
+ const o = e;
251
+ for (const n of r(e, t)){
252
+ delete o[n];
253
+ }
254
+ };
255
+
256
+ const callHook = (n, r, t)=>{
257
+ return new Promise((i)=>{
258
+ const e = n[r];
259
+ if (e) {
260
+ if (isAsync(e)) {
261
+ e.bind(n)(t).then(()=>{
262
+ i();
263
+ });
264
+ return;
265
+ }
266
+ i(e.bind(n)(t));
267
+ }
268
+ });
269
+ };
99
270
 
100
271
  const i = (n)=>{
101
272
  return {
@@ -144,16 +315,284 @@ const resolveInjectionTuple = (n)=>switchCase({
144
315
  throw new Error(`Injection tuple must be of length 1, 2 or 3.`);
145
316
  })(n.length);
146
317
 
147
- function t(t, e, n) {
318
+ const resolveParameters = (o, t, i, s)=>{
319
+ const c = [];
320
+ const r = getParamTypes(o);
321
+ const u = getDecoratedParametersIndexes(o);
322
+ let f = 0;
323
+ for (const n of r){
324
+ if (u.context.includes(f)) {
325
+ c.push(t);
326
+ f++;
327
+ continue;
328
+ }
329
+ if (u.configuration.includes(f)) {
330
+ c.push(s);
331
+ f++;
332
+ continue;
333
+ }
334
+ if (u.definition.includes(f)) {
335
+ c.push(i);
336
+ f++;
337
+ continue;
338
+ }
339
+ c.push(t.require(n));
340
+ f++;
341
+ }
342
+ return c;
343
+ };
344
+ const resolveDependencies = (o)=>{
345
+ const t = [];
346
+ const i = getParamTypes(o);
347
+ const s = getDecoratedParametersIndexes(o);
348
+ let c = 0;
349
+ for (const n of i){
350
+ if (s.context.includes(c) || s.configuration.includes(c) || s.definition.includes(c)) {
351
+ c++;
352
+ continue;
353
+ }
354
+ t.push(n);
355
+ c++;
356
+ }
357
+ return t;
358
+ };
359
+
360
+ function e$2(e, t, n) {
361
+ if (t in e) {
362
+ Object.defineProperty(e, t, {
363
+ value: n,
364
+ enumerable: true,
365
+ configurable: true,
366
+ writable: true
367
+ });
368
+ } else {
369
+ e[t] = n;
370
+ }
371
+ return e;
372
+ }
373
+ let h = Symbol.iterator;
374
+ class ListenerCollection {
375
+ dispose() {
376
+ clearInstance(this, ListenerCollection);
377
+ }
378
+ add(...e) {
379
+ const n = (e)=>this.collection[e.channel].push(e.listener);
380
+ const c = conditionally({
381
+ if: ()=>e.length === 2,
382
+ then: ()=>{
383
+ return {
384
+ channel: e[0],
385
+ listener: e[1]
386
+ };
387
+ },
388
+ else: ()=>{
389
+ const t = e[0];
390
+ return {
391
+ channel: t[0],
392
+ listener: t[1]
393
+ };
394
+ }
395
+ });
396
+ const o = conditionally({
397
+ if: (e)=>!isDefined(this.collection[e.channel]),
398
+ then: (e)=>{
399
+ this.collection[e.channel] = [];
400
+ n(e);
401
+ },
402
+ else: (e)=>{
403
+ n(e);
404
+ }
405
+ });
406
+ pipe(c, o)();
407
+ return this;
408
+ }
409
+ remove(e, n) {
410
+ const c = (t)=>this.collection[e].splice(t, 1);
411
+ const o = conditionally({
412
+ if: ()=>this.collection[e] && this.collection[e].length === 0,
413
+ then: ()=>delete this.collection[e]
414
+ });
415
+ const s = conditionally({
416
+ if: ()=>isDefined(n),
417
+ then: ()=>c(this.collection[e].indexOf(n)),
418
+ else: ()=>delete this.collection[e]
419
+ });
420
+ const r = conditionally({
421
+ if: (e)=>this.has(e),
422
+ then: (e)=>this.collection[e]
423
+ });
424
+ pipe(r, s, o)();
425
+ return this;
426
+ }
427
+ has(...e) {
428
+ if (isOfType('string')(e[0])) {
429
+ return Object.keys(this.collection).includes(e[0]);
430
+ } else if (isOfType('function')(e[0])) {
431
+ return Object.values(this.collection).flat().includes(e[0]);
432
+ }
433
+ return false;
434
+ }
435
+ get(...e) {
436
+ if (isOfType('string')(e[0])) {
437
+ return this.collection[e[0]];
438
+ } else if (isOfType('function')(e[0])) {
439
+ return Object.values(this.collection).flat().filter((t)=>t === e[0]);
440
+ }
441
+ return [];
442
+ }
443
+ clear() {
444
+ const e = forIn(this.collection);
445
+ const t = (e)=>forOf(this.collection[e])((t)=>this.remove(e, t));
446
+ e((e)=>t(e));
447
+ return this;
448
+ }
449
+ get listeners() {
450
+ return Object.values(this.collection).flat();
451
+ }
452
+ get channels() {
453
+ return Object.keys(this.collection);
454
+ }
455
+ get length() {
456
+ return Object.values(this.collection).flat().length;
457
+ }
458
+ [h]() {
459
+ let e = -1;
460
+ const t = this.collection ? Object.keys(this.collection) : [];
461
+ return {
462
+ next: ()=>({
463
+ value: t[++e],
464
+ done: !(e in t)
465
+ })
466
+ };
467
+ }
468
+ constructor(){
469
+ e$2(this, "collection", {});
470
+ const t = proxifyIterable(this, ListenerCollection);
471
+ return t;
472
+ }
473
+ }
474
+
475
+ function e$1(e, n, s) {
476
+ if (n in e) {
477
+ Object.defineProperty(e, n, {
478
+ value: s,
479
+ enumerable: true,
480
+ configurable: true,
481
+ writable: true
482
+ });
483
+ } else {
484
+ e[n] = s;
485
+ }
486
+ return e;
487
+ }
488
+ class EventManager {
489
+ dispose() {
490
+ this.listeners.dispose();
491
+ this.channels.clear();
492
+ clearInstance(this, EventManager);
493
+ }
494
+ addChannels(...e) {
495
+ const n = forOf(e);
496
+ n((e)=>{
497
+ const n = this.cleanChannel(e);
498
+ if (this.channels.has(n)) {
499
+ throw new Error(`Channel '${n}' already exists.`);
500
+ }
501
+ this.channels.add(n);
502
+ });
503
+ return this;
504
+ }
505
+ removeChannels(...e) {
506
+ const n = forOf(e);
507
+ n((e)=>{
508
+ const n = this.cleanChannel(e);
509
+ if (n !== '*' && this.channels.has(n)) {
510
+ this.channels.delete(n);
511
+ this.listeners.remove(n);
512
+ this.onceListeners.remove(n);
513
+ }
514
+ });
515
+ return this;
516
+ }
517
+ on(e, n) {
518
+ const s = this.cleanChannel(e);
519
+ if (!this.channels.has(s)) {
520
+ throw new Error(`Channel '${s}' was not registered.`);
521
+ }
522
+ this.listeners.add(s, n);
523
+ return this;
524
+ }
525
+ once(e, n) {
526
+ const s = this.cleanChannel(e);
527
+ if (!this.channels.has(s)) {
528
+ throw new Error(`Channel '${s}' was not registered.`);
529
+ }
530
+ this.onceListeners.add(s, n);
531
+ return this;
532
+ }
533
+ off(e, n) {
534
+ const s = this.cleanChannel(e);
535
+ this.listeners.remove(s, n);
536
+ return this;
537
+ }
538
+ emit(e, ...n) {
539
+ const t = this.cleanChannel(e);
540
+ if (this.channels.has(t)) {
541
+ const e = this.onceListeners.get('*') || [];
542
+ const r = this.listeners.get('*') || [];
543
+ const i = this.onceListeners.get(t) || [];
544
+ const h = this.listeners.get(t) || [];
545
+ const o = forOf(e);
546
+ const a = forOf(r);
547
+ const c = forOf(i);
548
+ const l = forOf(h);
549
+ o((e)=>{
550
+ this.run(e, ...n);
551
+ this.onceListeners.remove('*', e);
552
+ });
553
+ a((e)=>{
554
+ this.run(e, ...n);
555
+ });
556
+ c((e)=>{
557
+ this.run(e, ...n);
558
+ this.onceListeners.remove(t, e);
559
+ });
560
+ l((e)=>{
561
+ this.run(e, ...n);
562
+ });
563
+ }
564
+ return this;
565
+ }
566
+ run(e, ...n) {
567
+ if (isAsync(e)) {
568
+ const s = e;
569
+ return s(...n).then(()=>Promise.resolve());
570
+ }
571
+ e(...n);
572
+ }
573
+ cleanChannel(e) {
574
+ return onlyAlphanumeric(e, '*');
575
+ }
576
+ constructor(...n){
577
+ e$1(this, "listeners", new ListenerCollection());
578
+ e$1(this, "onceListeners", new ListenerCollection());
579
+ e$1(this, "channels", new Set([
580
+ '*'
581
+ ]));
582
+ this.addChannels(...n);
583
+ }
584
+ }
585
+
586
+ function t(t, e, i) {
148
587
  if (e in t) {
149
588
  Object.defineProperty(t, e, {
150
- value: n,
589
+ value: i,
151
590
  enumerable: true,
152
591
  configurable: true,
153
592
  writable: true
154
593
  });
155
594
  } else {
156
- t[e] = n;
595
+ t[e] = i;
157
596
  }
158
597
  return t;
159
598
  }
@@ -161,112 +600,68 @@ class Injectable {
161
600
  static of(t, e) {
162
601
  return new Injectable(t, e);
163
602
  }
603
+ dispose() {
604
+ if (this.singleton) {
605
+ callHook(this.singleton, 'onDispose', this.context);
606
+ }
607
+ clearInstance(this, Injectable);
608
+ }
164
609
  build() {
165
610
  if (this.singleton) return this.singleton;
166
- const t = this.resolveDependencies();
611
+ const t = resolveParameters(this.concrete, this.context, this.definition, this.configuration);
167
612
  const e = new this.concrete(...t);
613
+ const i = this.concrete.prototype instanceof EventManager;
614
+ if (i) {
615
+ e.addChannels(...this.events);
616
+ }
617
+ callHook(e, 'onInit', this.context);
168
618
  if (this.isSingleton) {
169
619
  this.singleton = e;
170
620
  }
171
621
  return e;
172
622
  }
173
- resolveDependencies() {
174
- const t = [];
175
- const i = getOwnCustomMetadata(ReflectContextParamIndex, this.concrete) || [];
176
- const s = getOwnCustomMetadata(ReflectConfigurationParamIndex, this.concrete) || [];
177
- const h = getCustomMetadata(ReflectMetadataParamIndex, this.concrete) || [];
178
- let u = 0;
179
- for (const e of this.dependencies){
180
- if (i.includes(u)) {
181
- t.push(this.context);
182
- u++;
183
- continue;
184
- }
185
- if (s.includes(u)) {
186
- t.push(this.configuration);
187
- u++;
188
- continue;
189
- }
190
- if (h.includes(u)) {
191
- t.push(this.metadata);
192
- u++;
193
- continue;
194
- }
195
- t.push(this.context.require(e));
196
- u++;
197
- }
198
- return t;
623
+ get dependencies() {
624
+ return this.dependenciesIds;
625
+ }
626
+ get definition() {
627
+ return getDefinition(this.concrete) || {};
199
628
  }
200
629
  get isSingleton() {
201
- return getOwnCustomMetadata(ReflectIsSingletonFlag, this.concrete) || false;
630
+ return getDefinitionValue('singleton', this.concrete) || true;
202
631
  }
203
632
  get injections() {
204
- return getOwnCustomMetadata('inject', this.concrete) || [];
205
- }
206
- get dependencies() {
207
- return Reflect.getMetadata(ReflectParamTypes, this.concrete) || [];
633
+ return getDefinitionValue('inject', this.concrete) || [];
208
634
  }
209
635
  get tags() {
210
- return getCustomMetadata('tags', this.concrete) || [];
636
+ return getDefinitionValue('tags', this.concrete) || [];
211
637
  }
212
- get metadata() {
213
- return getCustomMetadata('metadata', this.concrete) || {};
638
+ get events() {
639
+ return getDefinitionValue('events', this.concrete) || [];
214
640
  }
215
- constructor(e, n){
641
+ constructor(e, i){
216
642
  t(this, "context", undefined);
217
643
  t(this, "identifier", undefined);
218
644
  t(this, "concrete", undefined);
219
645
  t(this, "configuration", undefined);
220
646
  t(this, "singleton", undefined);
221
- this.context = n;
222
- const i = resolveInjectionTuple(e);
223
- this.identifier = i.identifier;
224
- this.concrete = i.concrete;
225
- this.configuration = i.configuration;
647
+ t(this, "dependenciesIds", undefined);
648
+ this.context = i;
649
+ this.dependenciesIds = [];
650
+ const n = resolveInjectionTuple(e);
651
+ this.identifier = n.identifier;
652
+ this.concrete = n.concrete;
653
+ this.configuration = n.configuration;
226
654
  for (const t of this.injections){
227
655
  this.context.register(t);
228
656
  }
229
- }
230
- }
231
-
232
- function e$2(e, t, r) {
233
- if (t in e) {
234
- Object.defineProperty(e, t, {
235
- value: r,
236
- enumerable: true,
237
- configurable: true,
238
- writable: true
239
- });
240
- } else {
241
- e[t] = r;
242
- }
243
- return e;
244
- }
245
- class AssemblerContext {
246
- set(e, t) {
247
- if (this.userData[e]) {
248
- throw new Error(`Key '${e}' is already defined in context's user data.`);
657
+ this.dependenciesIds = resolveDependencies(this.concrete);
658
+ if (this.isSingleton) {
659
+ this.build();
249
660
  }
250
- this.userData[e] = t;
251
- return this;
252
- }
253
- get(e) {
254
- return this.userData[e];
255
- }
256
- constructor(t){
257
- e$2(this, "userData", {});
258
- e$2(this, "register", undefined);
259
- e$2(this, "has", undefined);
260
- e$2(this, "require", undefined);
261
- e$2(this, "tagged", undefined);
262
- this.register = t.register.bind(t);
263
- this.has = t.has.bind(t);
264
- this.require = t.require.bind(t);
265
- this.tagged = t.tagged.bind(t);
266
661
  }
267
662
  }
268
663
 
269
- function e$1(e, t, i) {
664
+ function e(e, t, i) {
270
665
  if (t in e) {
271
666
  Object.defineProperty(e, t, {
272
667
  value: i,
@@ -283,12 +678,19 @@ class Assembler {
283
678
  static build(e) {
284
679
  return new Assembler(e);
285
680
  }
681
+ dispose() {
682
+ for (const [e, t] of this.injectables){
683
+ t.dispose();
684
+ }
685
+ clearInstance(this, Assembler);
686
+ }
286
687
  register(e) {
287
688
  const t = Injectable.of(e, this.context);
288
689
  if (this.has(t.identifier)) {
289
690
  throw new Error(`An assemblage is already registered with identifier '${t.identifier.name}'.`);
290
691
  }
291
692
  this.injectables.set(t.identifier, t);
693
+ callHook(t.concrete, 'onRegister', this.context);
292
694
  return t;
293
695
  }
294
696
  has(e) {
@@ -304,33 +706,30 @@ class Assembler {
304
706
  tagged(...e) {
305
707
  const t = [];
306
708
  for (const i of e){
307
- for (const [e, r] of this.injectables){
308
- if (r.tags.includes(i)) t.push(r.build());
709
+ for (const [e, s] of this.injectables){
710
+ if (s.tags.includes(i)) t.push(s.build());
309
711
  }
310
712
  }
311
713
  return t;
312
714
  }
313
- constructor(r){
314
- e$1(this, "injectables", new Map());
315
- e$1(this, "context", undefined);
316
- this.context = new AssemblerContext(this);
317
- defineCustomMetadata(ReflectIsSingletonFlag, true, r);
318
- const s = this.register([
319
- r
715
+ get size() {
716
+ return this.injectables.size;
717
+ }
718
+ constructor(t){
719
+ e(this, "injectables", new Map());
720
+ e(this, "context", undefined);
721
+ this.context = {
722
+ register: this.register.bind(this),
723
+ has: this.has.bind(this),
724
+ require: this.require.bind(this),
725
+ tagged: this.tagged.bind(this)
726
+ };
727
+ setDefinitionValue('singleton', true, t);
728
+ const i = this.register([
729
+ t
320
730
  ]);
321
- return s.build();
731
+ return this.require(i.identifier);
322
732
  }
323
733
  }
324
734
 
325
- const m = (o)=>()=>{
326
- return (t, n, m)=>{
327
- const s = getOwnCustomMetadata(o, t) || [];
328
- s.push(m);
329
- defineCustomMetadata(o, s, t);
330
- };
331
- };
332
- const s = m(ReflectContextParamIndex);
333
- const e = m(ReflectConfigurationParamIndex);
334
- const a = m(ReflectMetadataParamIndex);
335
-
336
- export { AbstractAssemblage, AbstractAssembler, Assemblage, Assembler, AssemblerContext, e as Configuration, s as Context, a as Metadata };
735
+ export { AbstractAssemblage, AbstractAssembler, Assemblage, Assembler, x as Configuration, s as Context, c$1 as Definition };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "assemblerjs",
3
3
  "description": "A simple and zero-dependency DI package written in typescript.",
4
- "version": "0.0.97",
4
+ "version": "0.0.98",
5
5
  "author": "Benoît LAHOZ <info@benoitlahoz.io>",
6
6
  "bugs": "https://github.com/benoitlahoz/assemblerjs/issues",
7
7
  "devDependencies": {