assemblerjs 0.0.99 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -32,10 +32,14 @@ export declare abstract class AbstractAssemblage {
32
32
  * Dispose the assemblage instance.
33
33
  */
34
34
  abstract dispose?(): void;
35
+ /**
36
+ * When decorated with '@Waitable', waits for a specific property to be truthy before resolving.
37
+ */
38
+ abstract whenReady?(): Promise<void>;
35
39
  }
36
40
 
37
- export declare abstract class AbstractAssembler {
38
- abstract context: AssemblerContext;
41
+ export declare abstract class AbstractAssembler extends AbstractEventManager {
42
+ abstract privateContext: AssemblerContext;
39
43
  abstract size: number;
40
44
  abstract register<T>(injection: Injection<T>): Injectable<T>;
41
45
  abstract has<T>(identifier: Identifier<T>): boolean;
@@ -44,6 +48,17 @@ export declare abstract class AbstractAssembler {
44
48
  abstract dispose(): void;
45
49
  }
46
50
 
51
+ export declare abstract class AbstractEventManager {
52
+ abstract channels: Set<string>;
53
+ abstract dispose(): void;
54
+ abstract addChannels(...channels: string[]): AbstractEventManager;
55
+ abstract removeChannels(...channels: string[]): AbstractEventManager;
56
+ abstract on(channel: string, callback: Listener): AbstractEventManager;
57
+ abstract once(channel: string, callback: Listener): AbstractEventManager;
58
+ abstract off(channel: string, callback?: Listener): AbstractEventManager;
59
+ abstract emit(channel: string, ...args: any[]): AbstractEventManager;
60
+ }
61
+
47
62
  /**
48
63
  * Generic `Array` items.
49
64
  */
@@ -59,17 +74,24 @@ export declare const Assemblage: (definition?: AssemblageDefinition) => ClassDec
59
74
  declare interface AssemblageDefinition {
60
75
  singleton?: false;
61
76
  events?: string[];
62
- inject?: Injection<unknown>[][];
77
+ inject?: Injection<unknown>[];
63
78
  tags?: string | string[];
64
79
  controller?: true;
65
80
  path?: string;
66
81
  metadata?: Record<string, any>;
67
82
  }
68
83
 
69
- export declare class Assembler implements AbstractAssembler {
84
+ export declare class Assembler extends EventManager implements AbstractAssembler {
70
85
  protected injectables: Map<Identifier<unknown>, Injectable<unknown>>;
71
- readonly context: AssemblerContext;
72
- static build(entry: Concrete<any>): Assembler;
86
+ /**
87
+ * Context passed to internal classes.
88
+ */
89
+ readonly privateContext: AssemblerPrivateContext;
90
+ /**
91
+ * Context passed to assemblages.
92
+ */
93
+ readonly publicContext: AssemblerContext;
94
+ static build<T>(entry: Concrete<T>): T;
73
95
  private constructor();
74
96
  dispose(): void;
75
97
  /**
@@ -111,13 +133,37 @@ export declare interface AssemblerContext {
111
133
  has: AbstractAssembler['has'];
112
134
  require: AbstractAssembler['require'];
113
135
  tagged: AbstractAssembler['tagged'];
136
+ on: AbstractAssembler['on'];
137
+ once: AbstractAssembler['once'];
138
+ off: AbstractAssembler['off'];
139
+ events: AbstractAssembler['channels'];
140
+ }
141
+
142
+ export declare type AssemblerDispose = AbstractAssembler['dispose'];
143
+
144
+ declare interface AssemblerPrivateContext extends AssemblerContext {
145
+ dispose: AssemblerDispose;
146
+ emit: AbstractAssembler['emit'];
147
+ addChannels: AbstractAssembler['addChannels'];
148
+ removeChannels: AbstractAssembler['removeChannels'];
114
149
  }
115
150
 
151
+ export declare const Awaitable: (property: string, millis?: number) => (_target: any, _propertyKey: string, descriptor: TypedPropertyDescriptor<(...params: any[]) => Promise<any>>) => void;
152
+
116
153
  /**
117
154
  * Injectable binds a concrete class to an abstract class as identifier without configuration.
118
155
  */
119
156
  declare type BaseInjection<T> = Tuple<[Abstract<T>, Concrete<T>]>;
120
157
 
158
+ /**
159
+ * Describes a buildable object.
160
+ */
161
+ declare interface Buildable<T> {
162
+ identifier: Identifier<T>;
163
+ concrete: Concrete<T>;
164
+ configuration: Record<string, any>;
165
+ }
166
+
121
167
  /**
122
168
  * A concrete (newable) class.
123
169
  */
@@ -155,22 +201,42 @@ export declare const Context: () => ParameterDecorator;
155
201
 
156
202
  export declare const Definition: () => ParameterDecorator;
157
203
 
204
+ export declare const Dispose: () => ParameterDecorator;
205
+
206
+ export declare class EventManager implements AbstractEventManager {
207
+ private readonly listeners;
208
+ private readonly onceListeners;
209
+ readonly channels: Set<string>;
210
+ constructor(...allowedChannels: string[]);
211
+ dispose(): void;
212
+ addChannels(...channels: string[]): EventManager;
213
+ removeChannels(...channels: string[]): EventManager;
214
+ on(channel: string, callback: Listener): EventManager;
215
+ once(channel: string, callback: Listener): EventManager;
216
+ off(channel: string, callback?: Listener): EventManager;
217
+ emit(channel: string, ...args: any[]): EventManager;
218
+ private run;
219
+ private cleanChannel;
220
+ }
221
+
158
222
  /**
159
223
  * An identifier can be an abstract or a concrete class.
160
224
  */
161
225
  declare type Identifier<T> = Concrete<T> | Abstract<T>;
162
226
 
163
227
  declare class Injectable<T> {
164
- readonly context: AssemblerContext;
228
+ readonly privateContext: AssemblerPrivateContext;
229
+ readonly publicContext: AssemblerContext;
165
230
  readonly identifier: Identifier<T>;
166
231
  readonly concrete: Concrete<T>;
167
232
  readonly configuration: Record<string, any>;
168
233
  private dependenciesIds;
169
234
  private singletonInstance;
170
- static of<TNew>(injection: Injection<TNew>, context: AssemblerContext): Injectable<TNew>;
235
+ static of<TNew>(buildable: Buildable<TNew>, privateContext: AssemblerPrivateContext, publicContext: AssemblerContext): Injectable<TNew>;
171
236
  private constructor();
172
237
  /**
173
- * Dispose the injectable by deleting its singleton if exists.
238
+ * Dispose the injectable by deleting its singleton if exists
239
+ * and deleting all injectable's properties.
174
240
  */
175
241
  dispose(): void;
176
242
  /**
@@ -214,6 +280,11 @@ declare class Injectable<T> {
214
280
  */
215
281
  declare type Injection<T> = BaseInjection<T> | ConfiguredInjection<T> | ConcreteInjection<T> | ConcreteConfiguredInjection<T>;
216
282
 
283
+ /**
284
+ * Describes a listener type as a function taking any number of arguments and returning `void`.
285
+ */
286
+ declare type Listener = (...args: any[]) => void | Promise<void>;
287
+
217
288
  /**
218
289
  * An array of fixed length typed values.
219
290
  *
package/dist/index.js CHANGED
@@ -1 +1 @@
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",s=(e,t,n)=>{Reflect.defineMetadata(`__${e}__`,t,n)},i=(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}},a=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,s=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]=s(t[n])}return t},l=t=>i(e,t),h=(e,t)=>l(t)[e],u=e=>()=>(t,n,r)=>{const o=i(e,t)||[];o.push(r),s(e,o,t)},f=u(t),d=u(n),g=u(r),p=e=>{const s=(e=>i(t,e)||[])(e),o=(e=>i(r,e)||[])(e),c=(e=>i(n,e)||[])(e);return{context:s,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,s]of Object.entries(e))t(s,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 s=e[t];if(s){if(v(s))return void s.bind(e)(n).then((()=>{r()}));r(s.bind(e)(n))}}));let _=Symbol.iterator;class I{dispose(){P(this,I)}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]}),s=x({if:()=>m(t),then:()=>n(this.collection[e].indexOf(t)),else:()=>delete this.collection[e]}),i=x({if:e=>this.has(e),then:e=>this.collection[e]});return O(i,s,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,I)}}function S(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class ${dispose(){this.listeners.dispose(),this.channels.clear(),P(this,$)}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("*")||[],s=this.onceListeners.get(n)||[],i=this.listeners.get(n)||[],o=A(e),c=A(r),a=A(s),l=A(i);o((e=>{this.run(e,...t),this.onceListeners.remove("*",e)})),c((e=>{this.run(e,...t)})),a((e=>{this.run(e,...t),this.onceListeners.remove(n,e)})),l((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){S(this,"listeners",new I),S(this,"onceListeners",new I),S(this,"channels",new Set(["*"])),this.addChannels(...e)}}const k=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}))()},L=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:()=>k(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 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.singletonInstance&&C(this.singletonInstance,"onDispose",this.context),P(this,N)}build(){if(this.singletonInstance)return this.singletonInstance;const e=(e=>{const t=[],n=o(e.concrete),r=p(e.concrete);let s=0;for(const i of n)r.context.includes(s)?(t.push(e.context),s++):r.configuration.includes(s)?(t.push(e.configuration),s++):r.definition.includes(s)?(t.push(e.definition),s++):(t.push(e.context.require(i)),s++);return t})(this),t=new this.concrete(...e);return this.concrete.prototype instanceof $&&t.addChannels(...this.events),C(t,"onInit",this.context),this.isSingleton&&(this.singletonInstance=t),t}get dependencies(){return this.dependenciesIds}get definition(){return l(this.concrete)||{}}get isSingleton(){return h("singleton",this.concrete)||!0}get singleton(){return this.singletonInstance}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,"dependenciesIds",void 0),R(this,"singletonInstance",void 0),this.context=t,this.dependenciesIds=[];const n=L(e);this.identifier=n.identifier,this.concrete=n.concrete,this.configuration=n.configuration;A(this.injections)((e=>this.context.register(e))),this.dependenciesIds=(e=>{const t=[],n=o(e),r=p(e);let s=0;for(const i of n)r.context.includes(s)||r.configuration.includes(s)||r.definition.includes(s)||t.push(i),s++;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=l(n);r[e]=t,a(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?a(t):{};return t=>(s("is_assemblage",!0,t),s(e,n,t),t)},exports.Assembler=M,exports.Configuration=d,exports.Context=f,exports.Definition=g;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=(...e)=>{},t=(...e)=>t=>{if(e.includes(typeof t))return typeof t},n=e=>!(e=>void 0===e)(e)&&!(e=>null===e)(e),s=e=>e&&"function"==typeof e&&void 0!==e.constructor,i=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,r=(e,...t)=>{t.map(((e,n)=>{const s=/\S/.test(e);return s&&(t[n]=t[n].trim()),s?-1:n})).filter((e=>e>=0)).every((e=>{t[e]=" ",((e,t,n)=>{const s=e[t];e.splice(t,1),e.splice(n,0,s)})(t,e,t.length-1)})),t=(e=>Array.from(new Set(e)))(t);const n=new RegExp(`[^A-Za-zÀ-ÖØ-öø-ÿ0-9${t.join("")}]`,"gi");return e.replace(n,"")},o=(...e)=>t=>e.reduce(((e,t)=>t(e)),t),c=e=>t=>e.if(t)?e.then(t):e.else?e.else(t):void 0,a=t=>n=>{const s=Array.isArray(t)?e=>parseInt(e):e;for(const[e,i]of Object.entries(t))n(i,s(e))},l=(e,t)=>{const n=new Proxy(e,{get:function(n,s){return s===Symbol.iterator?n[Symbol.iterator].bind(n):((e,t)=>[...Object.getOwnPropertyNames(t.prototype),...Object.getOwnPropertyNames(Object.getPrototypeOf(e)),...Object.getOwnPropertyNames(e)])(e,t).includes(s)?n[s]:n.collection[s]},set:function(e,t,n){return Reflect.set(e,t,n)}});return n},h=(e,t)=>{const n=e;for(const s of((e,t)=>[...Object.getOwnPropertyNames(t.prototype),...Object.getOwnPropertyNames(Object.getPrototypeOf(e)),...Object.getOwnPropertyNames(e)])(e,t))delete n[s]};let d=Symbol.iterator;class u{dispose(){h(this,u)}add(...e){const t=e=>this.collection[e.channel].push(e.listener),s=c({if:()=>2===e.length,then:()=>({channel:e[0],listener:e[1]}),else:()=>{const t=e[0];return{channel:t[0],listener:t[1]}}}),i=c({if:e=>!n(this.collection[e.channel]),then:e=>{this.collection[e.channel]=[],t(e)},else:e=>{t(e)}});return o(s,i)(),this}remove(e,t){const s=t=>this.collection[e].splice(t,1),i=c({if:()=>this.collection[e]&&0===this.collection[e].length,then:()=>delete this.collection[e]}),r=c({if:()=>n(t),then:()=>s(this.collection[e].indexOf(t)),else:()=>delete this.collection[e]}),a=c({if:e=>this.has(e),then:e=>this.collection[e]});return o(a,r,i)(),this}has(...e){return t("string")(e[0])?Object.keys(this.collection).includes(e[0]):!!t("function")(e[0])&&Object.values(this.collection).flat().includes(e[0])}get(...e){return t("string")(e[0])?this.collection[e[0]]:t("function")(e[0])?Object.values(this.collection).flat().filter((t=>t===e[0])):[]}clear(){const e=(e=>t=>{const n=Array.isArray(e)?e=>parseInt(e):e=>e;for(const s in e)t(n(s))})(this.collection),t=e=>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}[d](){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 l(this,u)}}function f(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class p{dispose(){this.listeners.dispose(),this.channels.clear(),h(this,p)}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("*")||[],s=this.listeners.get("*")||[],i=this.onceListeners.get(n)||[],r=this.listeners.get(n)||[],o=a(e),c=a(s),l=a(i),h=a(r);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)})),h((e=>{this.run(e,...t)}))}return this}run(e,...t){if(i(e)){return e(...t).then((()=>Promise.resolve()))}e(...t)}cleanChannel(e){return r(e,"*")}constructor(...e){f(this,"listeners",new u),f(this,"onceListeners",new u),f(this,"channels",new Set(["*"])),this.addChannels(...e)}}const g="is_assemblage",b="assemblage_definition",y="context_param_index",v="config_param_index",m="definition_param_index",w="dispose_param_index",x=(e,t,n)=>{Reflect.defineMetadata(`__${e}__`,t,n)},C=(e,t)=>Reflect.getOwnMetadata(`__${e}__`,t),j=e=>Reflect.getMetadata("design:paramtypes",e)||[],O={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}},A=e=>{const t={...e};for(const n in t){if(!Object.keys(O).includes(n))throw new Error(`Property '${n}' is not a valid assemblage definition property.`);const e=O[n].test,s=O[n].throw,i=O[n].transform;if(e(t[n])||s(),"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},E=e=>C(b,e),I=(e,t)=>E(t)[e],P=(e,t,n)=>new Promise((s=>{const r=e[t];if(r){if(i(r))return void r.bind(e)(n).then((()=>{s()}));s(r.bind(e)(n))}})),_=e=>{const t=(e=>C(y,e)||[])(e),n=(e=>C(m,e)||[])(e),s=(e=>C(v,e)||[])(e),i=(e=>C(w,e)||[])(e);return{context:t,definition:n,configuration:s,dispose:i}};function S(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class ${static of(e,t,n){return new $(e,t,n)}dispose(){this.singletonInstance&&(((e,t)=>{if(e.concrete.prototype instanceof p){const n=t;for(const t of e.events)n.off(t);n.removeChannels(...e.events),e.privateContext.removeChannels(...e.events)}})(this,this.singletonInstance),P(this.singletonInstance,"onDispose",this.publicContext),h(this.singletonInstance,this.concrete)),h(this,$)}build(){if(this.singletonInstance)return this.singletonInstance;if(!(e=>C(g,e)||!1)(this.concrete))throw new Error(`Class '${this.concrete}' is not an Assemblage.`);const e=(e=>{const t=[],n=j(e.concrete),s=_(e.concrete);let i=0;for(const r of n)s.context.includes(i)?(t.push(e.publicContext),i++):s.configuration.includes(i)?(t.push(e.configuration),i++):s.definition.includes(i)?(t.push(e.definition),i++):s.dispose.includes(i)?(t.push(e.privateContext.dispose),i++):(t.push(e.privateContext.require(r)),i++);return t})(this),t=new this.concrete(...e);return((e,t)=>{if(e.concrete.prototype instanceof p){const n=t,s=n.channels;for(const t of e.events)s.has(t)||n.addChannels(t),e.privateContext.events.has(t)||e.privateContext.addChannels(t);for(const i of e.events)t.on(i,((...t)=>{e.privateContext.emit(i,...t)}))}})(this,t),P(t,"onInit",this.publicContext),this.isSingleton&&(this.singletonInstance=t),t}get dependencies(){return this.dependenciesIds}get definition(){return E(this.concrete)||{}}get isSingleton(){return I("singleton",this.concrete)||!0}get singleton(){return this.singletonInstance}get injections(){return I("inject",this.concrete)||[]}get tags(){return I("tags",this.concrete)||[]}get events(){return I("events",this.concrete)||[]}constructor(e,t,n){S(this,"privateContext",void 0),S(this,"publicContext",void 0),S(this,"identifier",void 0),S(this,"concrete",void 0),S(this,"configuration",void 0),S(this,"dependenciesIds",void 0),S(this,"singletonInstance",void 0),this.privateContext=t,this.publicContext=n,this.dependenciesIds=[],this.identifier=e.identifier,this.concrete=e.concrete,this.configuration=e.configuration;a(this.injections)((e=>this.privateContext.register(e))),this.dependenciesIds=(e=>{const t=[],n=j(e),s=_(e);let i=0;for(const r of n)s.context.includes(i)||s.configuration.includes(i)||s.definition.includes(i)||s.dispose.includes(i)||t.push(r),i++;return t})(this.concrete),this.isSingleton&&this.build()}}const k=e=>{const t=()=>s(e[0])&&(e=>"object"==typeof e&&!Array.isArray(e)&&!s(e))(e[1]);return o(c({if:()=>s(e[0])&&s(e[1]),then:()=>({identifier:e[0],concrete:e[1],configuration:{}})}),c({if:()=>t(),then:()=>({identifier:e[0],concrete:e[0],configuration:e[1]}),else:e=>e}))()};function L(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 extends p{static build(e){const t=new M;((e,t,n)=>{const s=E(n);s[e]=t,A(s)})("singleton",!0,e);const n=t.register([e]);return t.require(n.identifier)}dispose(){for(const[e,t]of this.injectables)t.dispose();h(this,M)}register(e){const t=(n=e,((e,t)=>(n,...s)=>e[n]?e[n](...s):t?t(n,...s):void 0)({1:()=>(e=>({identifier:e[0],concrete:e[0],configuration:{}}))(n),2:()=>k(n),3:()=>(e=>({identifier:e[0],concrete:e[1],configuration:e[2]}))(n)},(()=>{throw new Error("Injection tuple must be of length 1, 2 or 3.")}))(n.length));var n;if(this.has(t.identifier))throw new Error(`An assemblage is already registered with identifier '${t.identifier.name}'.`);const s=$.of(t,this.privateContext,this.publicContext);return this.injectables.set(s.identifier,s),P(s.concrete,"onRegister",this.publicContext),s}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,s]of this.injectables)s.tags.includes(n)&&t.push(s.build());return t}get size(){return this.injectables.size}constructor(){super(),L(this,"injectables",new Map),L(this,"privateContext",void 0),L(this,"publicContext",void 0),this.publicContext={register:this.register.bind(this),has:this.has.bind(this),require:this.require.bind(this),tagged:this.tagged.bind(this),on:this.on.bind(this),once:this.once.bind(this),off:this.off.bind(this),events:this.channels},this.privateContext={...this.publicContext,emit:this.emit.bind(this),addChannels:this.addChannels.bind(this),removeChannels:this.removeChannels.bind(this),dispose:this.dispose.bind(this)}}}const R=e=>()=>(t,n,s)=>{const i=C(e,t)||[];i.push(s),x(e,i,t)},N=R(y),q=R(v),z=R(m),D=R(w);class W{}exports.AbstractAssemblage=class{static onRegister(e){}},exports.AbstractAssembler=class extends W{},exports.AbstractEventManager=W,exports.Assemblage=e=>{const t=e?A(e):{};return e=>(x(g,!0,e),x(b,t,e),e)},exports.Assembler=M,exports.Awaitable=(e,t=25)=>(n,s,i)=>{let 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=q,exports.Context=N,exports.Definition=z,exports.Dispose=D,exports.EventManager=p;
package/dist/index.mjs CHANGED
@@ -1,171 +1,3 @@
1
- class AbstractAssemblage {
2
- static onRegister(s) {}
3
- }
4
-
5
- const ReflectParamTypes = 'design:paramtypes';
6
- const ReflectPrefix = '__';
7
- const ReflectSuffix = '__';
8
- const ReflectIsAssemblageFlag = `is_assemblage`;
9
- const ReflectDefinition = 'assemblage_definition';
10
- const ReflectContextParamIndex = `context_param_index`;
11
- const ReflectConfigurationParamIndex = `config_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
- };
22
-
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
- }
88
- };
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;
112
- };
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;
125
- };
126
-
127
- const Assemblage = (o)=>{
128
- const s = o ? validateDefinition(o) : {};
129
- return (o)=>{
130
- defineCustomMetadata(ReflectIsAssemblageFlag, true, o);
131
- defineCustomMetadata(ReflectDefinition, s, o);
132
- return o;
133
- };
134
- };
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
-
166
- class AbstractAssembler {
167
- }
168
-
169
1
  const NoOp = (...e)=>{};
170
2
  const isOfType = (...e)=>(t)=>{
171
3
  if (!e.includes(typeof t)) return undefined;
@@ -253,21 +85,6 @@ const clearInstance = (e, t)=>{
253
85
  }
254
86
  };
255
87
 
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
- };
270
-
271
88
  function e$3(e, t, n) {
272
89
  if (t in e) {
273
90
  Object.defineProperty(e, t, {
@@ -494,127 +311,291 @@ class EventManager {
494
311
  }
495
312
  }
496
313
 
497
- const i = (n)=>{
498
- return {
499
- identifier: n[0],
500
- concrete: n[0],
501
- configuration: {}
314
+ const ReflectParamTypes = 'design:paramtypes';
315
+ const ReflectPrefix = '__';
316
+ const ReflectSuffix = '__';
317
+ const ReflectIsAssemblageFlag = `is_assemblage`;
318
+ const ReflectDefinition = 'assemblage_definition';
319
+ const ReflectContextParamIndex = `context_param_index`;
320
+ const ReflectConfigurationParamIndex = `config_param_index`;
321
+ const ReflectDefinitionParamIndex = `definition_param_index`;
322
+ const ReflectDisposeParamIndex = `dispose_param_index`;
323
+
324
+ const defineCustomMetadata = (t, o, n)=>{
325
+ Reflect.defineMetadata(`${ReflectPrefix}${t}${ReflectSuffix}`, o, n);
326
+ };
327
+ const getOwnCustomMetadata = (t, o)=>{
328
+ return Reflect.getOwnMetadata(`${ReflectPrefix}${t}${ReflectSuffix}`, o);
329
+ };
330
+ const getParamTypes = (e)=>{
331
+ return Reflect.getMetadata(ReflectParamTypes, e) || [];
332
+ };
333
+
334
+ const r = {
335
+ singleton: {
336
+ test: (t)=>typeof t === 'boolean' || typeof t === 'undefined',
337
+ throw: ()=>{
338
+ throw new Error(`'singleton' property must be of type 'boolean' or 'undefined'.`);
339
+ },
340
+ transform: (t)=>typeof t === 'undefined' ? true : false
341
+ },
342
+ events: {
343
+ test: (t)=>typeof t === 'undefined' || Array.isArray(t) && t.every((t)=>typeof t === 'string'),
344
+ throw: ()=>{
345
+ throw new Error(`'events' property must be an array of strings or 'undefined'.`);
346
+ },
347
+ transform: (t)=>t
348
+ },
349
+ inject: {
350
+ test: (t)=>typeof t === 'undefined' || Array.isArray(t) && t.every((t)=>Array.isArray(t) && t.length >= 1 && t.length <= 3),
351
+ throw: ()=>{
352
+ throw new Error(`'inject' property must be an array of tuples of length 1, 2 or 3.`);
353
+ },
354
+ transform: (t)=>t
355
+ },
356
+ tags: {
357
+ test: (t)=>typeof t === 'undefined' || typeof t === 'string' || Array.isArray(t) && t.every((t)=>typeof t === 'string'),
358
+ throw: ()=>{
359
+ throw new Error(`'tags' property must be a string or an array of strings.`);
360
+ },
361
+ transform: (t)=>typeof t === 'string' ? [
362
+ t
363
+ ] : t
364
+ },
365
+ controller: {
366
+ test: (t)=>typeof t === 'boolean' || typeof t === 'undefined',
367
+ throw: ()=>{
368
+ throw new Error(`'controller' property must be of type 'boolean' or 'undefined'.`);
369
+ },
370
+ transform: (t)=>t
371
+ },
372
+ path: {
373
+ test: (t)=>typeof t === 'string' || typeof t === 'undefined',
374
+ throw: ()=>{
375
+ throw new Error(`'path' property must be of type 'string' or 'undefined'.`);
376
+ },
377
+ transform: (t)=>{
378
+ if (t) {
379
+ let e = t.replace(/\/+/g, '/').replace(/\s/g, '');
380
+ if (!e.startsWith('/')) {
381
+ e = `/${e}`;
382
+ }
383
+ if (e.endsWith('/')) {
384
+ const t = e.length - 1;
385
+ e = e.split('').splice(0, t).join('');
386
+ }
387
+ return e;
388
+ }
389
+ return t;
390
+ }
391
+ },
392
+ metadata: {
393
+ test: (t)=>(typeof t === 'object' || typeof t === 'undefined') && !Array.isArray(t),
394
+ throw: ()=>{
395
+ throw new Error(`'metadata' property must be of type 'object' or 'undefined'.`);
396
+ },
397
+ transform: (t)=>t
398
+ }
399
+ };
400
+ const validateDefinition = (t)=>{
401
+ const e = {
402
+ ...t
403
+ };
404
+ for(const t in e){
405
+ if (!Object.keys(r).includes(t)) {
406
+ throw new Error(`Property '${t}' is not a valid assemblage definition property.`);
407
+ }
408
+ const o = r[t].test;
409
+ const n = r[t].throw;
410
+ const s = r[t].transform;
411
+ if (!o(e[t])) {
412
+ n();
413
+ }
414
+ if (t === 'controller' && !Object.keys(e).includes('path')) {
415
+ throw new Error(`Assemblage marked as 'controller' must define a 'path'.`);
416
+ }
417
+ if (t === 'path' && !Object.keys(e).includes('controller')) {
418
+ throw new Error(`Assemblage that defines a 'path' must be marked as 'controller'.`);
419
+ }
420
+ e[t] = s(e[t]);
421
+ }
422
+ return e;
423
+ };
424
+ const getDefinition = (r)=>{
425
+ return getOwnCustomMetadata(ReflectDefinition, r);
426
+ };
427
+ const getDefinitionValue = (t, e)=>{
428
+ const r = getDefinition(e);
429
+ return r[t];
430
+ };
431
+ const setDefinitionValue = (t, e, r)=>{
432
+ const o = getDefinition(r);
433
+ o[t] = e;
434
+ const n = validateDefinition(o);
435
+ return n;
436
+ };
437
+
438
+ const Assemblage = (r)=>{
439
+ const n = r ? validateDefinition(r) : {};
440
+ return (r)=>{
441
+ defineCustomMetadata(ReflectIsAssemblageFlag, true, r);
442
+ defineCustomMetadata(ReflectDefinition, n, r);
443
+ return r;
502
444
  };
503
445
  };
504
- const c = (r)=>{
505
- const i = ()=>isClass(r[0]) && isClass(r[1]);
506
- const c = ()=>isClass(r[0]) && isObject(r[1]);
507
- const u = ()=>pipe(conditionally({
508
- if: ()=>i(),
509
- then: ()=>{
510
- return {
511
- identifier: r[0],
512
- concrete: r[1],
513
- configuration: {}
514
- };
446
+ const isAssemblage = (e)=>{
447
+ return getOwnCustomMetadata(ReflectIsAssemblageFlag, e) || false;
448
+ };
449
+
450
+ const callHook = (o, r, t)=>{
451
+ return new Promise((i)=>{
452
+ const e = o[r];
453
+ if (e) {
454
+ if (isAsync(e)) {
455
+ e.bind(o)(t).then(()=>{
456
+ i();
457
+ });
458
+ return;
515
459
  }
516
- }), conditionally({
517
- if: ()=>c(),
518
- then: ()=>{
519
- return {
520
- identifier: r[0],
521
- concrete: r[0],
522
- configuration: r[1]
523
- };
524
- },
525
- else: (n)=>n
526
- }))();
527
- return u();
460
+ i(e.bind(o)(t));
461
+ }
462
+ });
528
463
  };
529
- const u = (n)=>{
464
+
465
+ const getContextIndex = (e)=>{
466
+ return getOwnCustomMetadata(ReflectContextParamIndex, e) || [];
467
+ };
468
+ const getConfigurationIndex = (t)=>{
469
+ return getOwnCustomMetadata(ReflectConfigurationParamIndex, t) || [];
470
+ };
471
+ const getDefinitionIndex = (e)=>{
472
+ return getOwnCustomMetadata(ReflectDefinitionParamIndex, e) || [];
473
+ };
474
+ const getDisposeIndex = (e)=>{
475
+ return getOwnCustomMetadata(ReflectDisposeParamIndex, e) || [];
476
+ };
477
+ const getDecoratedParametersIndexes = (e)=>{
478
+ const t = getContextIndex(e);
479
+ const n = getDefinitionIndex(e);
480
+ const o = getConfigurationIndex(e);
481
+ const r = getDisposeIndex(e);
530
482
  return {
531
- identifier: n[0],
532
- concrete: n[1],
533
- configuration: n[2]
483
+ context: t,
484
+ definition: n,
485
+ configuration: o,
486
+ dispose: r
534
487
  };
535
488
  };
536
- const resolveInjectionTuple = (n)=>switchCase({
537
- 1: ()=>i(n),
538
- 2: ()=>c(n),
539
- 3: ()=>u(n)
540
- }, ()=>{
541
- throw new Error(`Injection tuple must be of length 1, 2 or 3.`);
542
- })(n.length);
543
489
 
544
490
  const resolveParameters = (o)=>{
545
491
  const t = [];
546
- const c = getParamTypes(o.concrete);
547
- const i = getDecoratedParametersIndexes(o.concrete);
548
- let s = 0;
549
- for (const n of c){
550
- if (i.context.includes(s)) {
551
- t.push(o.context);
552
- s++;
492
+ const i = getParamTypes(o.concrete);
493
+ const s = getDecoratedParametersIndexes(o.concrete);
494
+ let c = 0;
495
+ for (const e of i){
496
+ if (s.context.includes(c)) {
497
+ t.push(o.publicContext);
498
+ c++;
553
499
  continue;
554
500
  }
555
- if (i.configuration.includes(s)) {
501
+ if (s.configuration.includes(c)) {
556
502
  t.push(o.configuration);
557
- s++;
503
+ c++;
558
504
  continue;
559
505
  }
560
- if (i.definition.includes(s)) {
506
+ if (s.definition.includes(c)) {
561
507
  t.push(o.definition);
562
- s++;
508
+ c++;
563
509
  continue;
564
510
  }
565
- t.push(o.context.require(n));
566
- s++;
511
+ if (s.dispose.includes(c)) {
512
+ t.push(o.privateContext.dispose);
513
+ c++;
514
+ continue;
515
+ }
516
+ t.push(o.privateContext.require(e));
517
+ c++;
567
518
  }
568
519
  return t;
569
520
  };
570
521
  const resolveDependencies = (o)=>{
571
522
  const t = [];
572
- const c = getParamTypes(o);
573
- const i = getDecoratedParametersIndexes(o);
574
- let s = 0;
575
- for (const n of c){
576
- if (i.context.includes(s) || i.configuration.includes(s) || i.definition.includes(s)) {
577
- s++;
523
+ const i = getParamTypes(o);
524
+ const s = getDecoratedParametersIndexes(o);
525
+ let c = 0;
526
+ for (const e of i){
527
+ if (s.context.includes(c) || s.configuration.includes(c) || s.definition.includes(c) || s.dispose.includes(c)) {
528
+ c++;
578
529
  continue;
579
530
  }
580
- t.push(n);
581
- s++;
531
+ t.push(e);
532
+ c++;
582
533
  }
583
534
  return t;
584
535
  };
585
536
 
586
- function e$1(e, t, n) {
537
+ const registerEvents = (t, n)=>{
538
+ const o = t.concrete.prototype instanceof EventManager;
539
+ if (o) {
540
+ const e = n;
541
+ const o = e.channels;
542
+ for (const n of t.events){
543
+ if (!o.has(n)) e.addChannels(n);
544
+ if (!t.privateContext.events.has(n)) t.privateContext.addChannels(n);
545
+ }
546
+ for (const e of t.events){
547
+ n.on(e, (...n)=>{
548
+ t.privateContext.emit(e, ...n);
549
+ });
550
+ }
551
+ }
552
+ };
553
+ const unregisterEvents = (t, n)=>{
554
+ const o = t.concrete.prototype instanceof EventManager;
555
+ if (o) {
556
+ const e = n;
557
+ for (const n of t.events){
558
+ e.off(n);
559
+ }
560
+ e.removeChannels(...t.events);
561
+ t.privateContext.removeChannels(...t.events);
562
+ }
563
+ };
564
+
565
+ function e$1(e, t, i) {
587
566
  if (t in e) {
588
567
  Object.defineProperty(e, t, {
589
- value: n,
568
+ value: i,
590
569
  enumerable: true,
591
570
  configurable: true,
592
571
  writable: true
593
572
  });
594
573
  } else {
595
- e[t] = n;
574
+ e[t] = i;
596
575
  }
597
576
  return e;
598
577
  }
599
578
  class Injectable {
600
- static of(e, t) {
601
- return new Injectable(e, t);
579
+ static of(e, t, i) {
580
+ return new Injectable(e, t, i);
602
581
  }
603
582
  dispose() {
604
583
  if (this.singletonInstance) {
605
- callHook(this.singletonInstance, 'onDispose', this.context);
584
+ unregisterEvents(this, this.singletonInstance);
585
+ callHook(this.singletonInstance, 'onDispose', this.publicContext);
586
+ clearInstance(this.singletonInstance, this.concrete);
606
587
  }
607
588
  clearInstance(this, Injectable);
608
589
  }
609
590
  build() {
610
591
  if (this.singletonInstance) return this.singletonInstance;
592
+ if (!isAssemblage(this.concrete)) {
593
+ throw new Error(`Class '${this.concrete}' is not an Assemblage.`);
594
+ }
611
595
  const e = resolveParameters(this);
612
596
  const t = new this.concrete(...e);
613
- const n = this.concrete.prototype instanceof EventManager;
614
- if (n) {
615
- t.addChannels(...this.events);
616
- }
617
- callHook(t, 'onInit', this.context);
597
+ registerEvents(this, t);
598
+ callHook(t, 'onInit', this.publicContext);
618
599
  if (this.isSingleton) {
619
600
  this.singletonInstance = t;
620
601
  }
@@ -641,21 +622,22 @@ class Injectable {
641
622
  get events() {
642
623
  return getDefinitionValue('events', this.concrete) || [];
643
624
  }
644
- constructor(t, i){
645
- e$1(this, "context", undefined);
625
+ constructor(t, n, s){
626
+ e$1(this, "privateContext", undefined);
627
+ e$1(this, "publicContext", undefined);
646
628
  e$1(this, "identifier", undefined);
647
629
  e$1(this, "concrete", undefined);
648
630
  e$1(this, "configuration", undefined);
649
631
  e$1(this, "dependenciesIds", undefined);
650
632
  e$1(this, "singletonInstance", undefined);
651
- this.context = i;
633
+ this.privateContext = n;
634
+ this.publicContext = s;
652
635
  this.dependenciesIds = [];
653
- const s = resolveInjectionTuple(t);
654
- this.identifier = s.identifier;
655
- this.concrete = s.concrete;
656
- this.configuration = s.configuration;
636
+ this.identifier = t.identifier;
637
+ this.concrete = t.concrete;
638
+ this.configuration = t.configuration;
657
639
  const o = forOf(this.injections);
658
- o((e)=>this.context.register(e));
640
+ o((e)=>this.privateContext.register(e));
659
641
  this.dependenciesIds = resolveDependencies(this.concrete);
660
642
  if (this.isSingleton) {
661
643
  this.build();
@@ -663,6 +645,53 @@ class Injectable {
663
645
  }
664
646
  }
665
647
 
648
+ const i$1 = (n)=>{
649
+ return {
650
+ identifier: n[0],
651
+ concrete: n[0],
652
+ configuration: {}
653
+ };
654
+ };
655
+ const c$1 = (o)=>{
656
+ const i = ()=>isClass(o[0]) && isClass(o[1]);
657
+ const c = ()=>isClass(o[0]) && isObject(o[1]);
658
+ const u = ()=>pipe(conditionally({
659
+ if: ()=>i(),
660
+ then: ()=>{
661
+ return {
662
+ identifier: o[0],
663
+ concrete: o[1],
664
+ configuration: {}
665
+ };
666
+ }
667
+ }), conditionally({
668
+ if: ()=>c(),
669
+ then: ()=>{
670
+ return {
671
+ identifier: o[0],
672
+ concrete: o[0],
673
+ configuration: o[1]
674
+ };
675
+ },
676
+ else: (n)=>n
677
+ }))();
678
+ return u();
679
+ };
680
+ const u = (n)=>{
681
+ return {
682
+ identifier: n[0],
683
+ concrete: n[1],
684
+ configuration: n[2]
685
+ };
686
+ };
687
+ const resolveInjectionTuple = (n)=>switchCase({
688
+ 1: ()=>i$1(n),
689
+ 2: ()=>c$1(n),
690
+ 3: ()=>u(n)
691
+ }, ()=>{
692
+ throw new Error(`Injection tuple must be of length 1, 2 or 3.`);
693
+ })(n.length);
694
+
666
695
  function e(e, t, i) {
667
696
  if (t in e) {
668
697
  Object.defineProperty(e, t, {
@@ -676,9 +705,14 @@ function e(e, t, i) {
676
705
  }
677
706
  return e;
678
707
  }
679
- class Assembler {
708
+ class Assembler extends EventManager {
680
709
  static build(e) {
681
- return new Assembler(e);
710
+ const t = new Assembler();
711
+ setDefinitionValue('singleton', true, e);
712
+ const i = t.register([
713
+ e
714
+ ]);
715
+ return t.require(i.identifier);
682
716
  }
683
717
  dispose() {
684
718
  for (const [e, t] of this.injectables){
@@ -687,13 +721,14 @@ class Assembler {
687
721
  clearInstance(this, Assembler);
688
722
  }
689
723
  register(e) {
690
- const t = Injectable.of(e, this.context);
724
+ const t = resolveInjectionTuple(e);
691
725
  if (this.has(t.identifier)) {
692
726
  throw new Error(`An assemblage is already registered with identifier '${t.identifier.name}'.`);
693
727
  }
694
- this.injectables.set(t.identifier, t);
695
- callHook(t.concrete, 'onRegister', this.context);
696
- return t;
728
+ const i = Injectable.of(t, this.privateContext, this.publicContext);
729
+ this.injectables.set(i.identifier, i);
730
+ callHook(i.concrete, 'onRegister', this.publicContext);
731
+ return i;
697
732
  }
698
733
  has(e) {
699
734
  return this.injectables.has(e);
@@ -717,21 +752,70 @@ class Assembler {
717
752
  get size() {
718
753
  return this.injectables.size;
719
754
  }
720
- constructor(t){
721
- e(this, "injectables", new Map());
722
- e(this, "context", undefined);
723
- this.context = {
755
+ constructor(){
756
+ super(), e(this, "injectables", new Map()), e(this, "privateContext", undefined), e(this, "publicContext", undefined);
757
+ this.publicContext = {
724
758
  register: this.register.bind(this),
725
759
  has: this.has.bind(this),
726
760
  require: this.require.bind(this),
727
- tagged: this.tagged.bind(this)
761
+ tagged: this.tagged.bind(this),
762
+ on: this.on.bind(this),
763
+ once: this.once.bind(this),
764
+ off: this.off.bind(this),
765
+ events: this.channels
766
+ };
767
+ this.privateContext = {
768
+ ...this.publicContext,
769
+ emit: this.emit.bind(this),
770
+ addChannels: this.addChannels.bind(this),
771
+ removeChannels: this.removeChannels.bind(this),
772
+ dispose: this.dispose.bind(this)
728
773
  };
729
- setDefinitionValue('singleton', true, t);
730
- const i = this.register([
731
- t
732
- ]);
733
- return this.require(i.identifier);
734
774
  }
735
775
  }
736
776
 
737
- export { AbstractAssemblage, AbstractAssembler, Assemblage, Assembler, x as Configuration, s as Context, c$1 as Definition };
777
+ const c = (o)=>()=>{
778
+ return (t, n, e)=>{
779
+ const c = getOwnCustomMetadata(o, t) || [];
780
+ c.push(e);
781
+ defineCustomMetadata(o, c, t);
782
+ };
783
+ };
784
+ const i = c(ReflectContextParamIndex);
785
+ const f = c(ReflectConfigurationParamIndex);
786
+ const p = c(ReflectDefinitionParamIndex);
787
+ const m = c(ReflectDisposeParamIndex);
788
+
789
+ const Awaitable = (e, t = 25)=>{
790
+ return (a, l, n)=>{
791
+ let s = n.value;
792
+ n.value = async function() {
793
+ return new Promise((a)=>{
794
+ if (this[e]) {
795
+ s.apply(this);
796
+ a();
797
+ } else {
798
+ const l = setInterval(()=>{
799
+ if (this[e]) {
800
+ clearInterval(l);
801
+ s.apply(this);
802
+ a();
803
+ }
804
+ }, t);
805
+ }
806
+ });
807
+ };
808
+ };
809
+ };
810
+
811
+ class AbstractAssemblage {
812
+ static onRegister(s) {}
813
+ }
814
+
815
+ class AbstractEventManager {
816
+ }
817
+
818
+ class AbstractAssembler extends AbstractEventManager {
819
+ }
820
+
821
+ export { AbstractAssemblage, AbstractAssembler, AbstractEventManager, Assemblage, Assembler, Awaitable, f as Configuration, i as Context, p as Definition, m as Dispose, EventManager };
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.99",
4
+ "version": "0.2.0",
5
5
  "author": "Benoît LAHOZ <info@benoitlahoz.io>",
6
6
  "bugs": "https://github.com/benoitlahoz/assemblerjs/issues",
7
7
  "devDependencies": {