assemblerjs 0.0.98 → 0.1.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/README.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # assembler.js
2
2
 
3
+ ---
4
+
5
+ [![npm version](https://badge.fury.io/js/assemblerjs.svg)](https://badge.fury.io/js/assemblerjs)
6
+
7
+ ![Statements](https://img.shields.io/badge/statements-84.3%25-yellow.svg?style=flat) ![Branches](https://img.shields.io/badge/branches-74.58%25-red.svg?style=flat) ![Functions](https://img.shields.io/badge/functions-81.48%25-yellow.svg?style=flat) ![Lines](https://img.shields.io/badge/lines-83.9%25-yellow.svg?style=flat)
8
+
9
+ <br />
10
+
3
11
  `assembler.js` name is a tribute to Gilles Deleuze and Felix Guattari concept of [_Agencement_](<https://fr.wikipedia.org/wiki/Agencement_(philosophie)>) (in french) that can be translated into [Assemblage](<https://en.wikipedia.org/wiki/Assemblage_(philosophy)>).
4
12
 
5
13
  ## Install
package/dist/index.d.ts CHANGED
@@ -44,6 +44,16 @@ export declare abstract class AbstractAssembler {
44
44
  abstract dispose(): void;
45
45
  }
46
46
 
47
+ export declare abstract class AbstractEventManager {
48
+ abstract dispose(): void;
49
+ abstract addChannels(...channels: string[]): AbstractEventManager;
50
+ abstract removeChannels(...channels: string[]): AbstractEventManager;
51
+ abstract on(channel: string, callback: Listener): AbstractEventManager;
52
+ abstract once(channel: string, callback: Listener): AbstractEventManager;
53
+ abstract off(channel: string, callback?: Listener): AbstractEventManager;
54
+ abstract emit(channel: string, ...args: any[]): AbstractEventManager;
55
+ }
56
+
47
57
  /**
48
58
  * Generic `Array` items.
49
59
  */
@@ -59,7 +69,7 @@ export declare const Assemblage: (definition?: AssemblageDefinition) => ClassDec
59
69
  declare interface AssemblageDefinition {
60
70
  singleton?: false;
61
71
  events?: string[];
62
- inject?: Injection<unknown>[][];
72
+ inject?: Injection<unknown>[];
63
73
  tags?: string | string[];
64
74
  controller?: true;
65
75
  path?: string;
@@ -155,18 +165,34 @@ export declare const Context: () => ParameterDecorator;
155
165
 
156
166
  export declare const Definition: () => ParameterDecorator;
157
167
 
168
+ export declare class EventManager implements AbstractEventManager {
169
+ private readonly listeners;
170
+ private readonly onceListeners;
171
+ private readonly channels;
172
+ constructor(...allowedChannels: string[]);
173
+ dispose(): void;
174
+ addChannels(...channels: string[]): EventManager;
175
+ removeChannels(...channels: string[]): EventManager;
176
+ on(channel: string, callback: Listener): EventManager;
177
+ once(channel: string, callback: Listener): EventManager;
178
+ off(channel: string, callback?: Listener): EventManager;
179
+ emit(channel: string, ...args: any[]): EventManager;
180
+ private run;
181
+ private cleanChannel;
182
+ }
183
+
158
184
  /**
159
185
  * An identifier can be an abstract or a concrete class.
160
186
  */
161
187
  declare type Identifier<T> = Concrete<T> | Abstract<T>;
162
188
 
163
189
  declare class Injectable<T> {
164
- private context;
190
+ readonly context: AssemblerContext;
165
191
  readonly identifier: Identifier<T>;
166
192
  readonly concrete: Concrete<T>;
167
193
  readonly configuration: Record<string, any>;
168
- singleton: T | undefined;
169
194
  private dependenciesIds;
195
+ private singletonInstance;
170
196
  static of<TNew>(injection: Injection<TNew>, context: AssemblerContext): Injectable<TNew>;
171
197
  private constructor();
172
198
  /**
@@ -191,6 +217,10 @@ declare class Injectable<T> {
191
217
  * `true` if assemblage is a singleton.
192
218
  */
193
219
  get isSingleton(): boolean;
220
+ /**
221
+ * The singleton instance if this `Injectable` wraps a singleton assemblage.
222
+ */
223
+ get singleton(): T | undefined;
194
224
  /**
195
225
  * Injectable assemblage's own injections defined in its decorator's definition.
196
226
  */
@@ -210,6 +240,11 @@ declare class Injectable<T> {
210
240
  */
211
241
  declare type Injection<T> = BaseInjection<T> | ConfiguredInjection<T> | ConcreteInjection<T> | ConcreteConfiguredInjection<T>;
212
242
 
243
+ /**
244
+ * Describes a listener type as a function taking any number of arguments and returning `void`.
245
+ */
246
+ declare type Listener = (...args: any[]) => void | Promise<void>;
247
+
213
248
  /**
214
249
  * An array of fixed length typed values.
215
250
  *
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",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;
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,"")},x=(...e)=>t=>e.reduce(((e,t)=>t(e)),t),O=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=O({if:()=>2===e.length,then:()=>({channel:e[0],listener:e[1]}),else:()=>{const t=e[0];return{channel:t[0],listener:t[1]}}}),r=O({if:e=>!m(this.collection[e.channel]),then:e=>{this.collection[e.channel]=[],t(e)},else:e=>{t(e)}});return x(n,r)(),this}remove(e,t){const n=t=>this.collection[e].splice(t,1),r=O({if:()=>this.collection[e]&&0===this.collection[e].length,then:()=>delete this.collection[e]}),s=O({if:()=>m(t),then:()=>n(this.collection[e].indexOf(t)),else:()=>delete this.collection[e]}),i=O({if:e=>this.has(e),then:e=>this.collection[e]});return x(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 x(O({if:()=>w(e[0])&&w(e[1]),then:()=>({identifier:e[0],concrete:e[1],configuration:{}})}),O({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 M(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class R{static of(e,t){return new R(e,t)}dispose(){this.singletonInstance&&C(this.singletonInstance,"onDispose",this.context),P(this,R)}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){M(this,"context",void 0),M(this,"identifier",void 0),M(this,"concrete",void 0),M(this,"configuration",void 0),M(this,"dependenciesIds",void 0),M(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 N(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class q{static build(e){return new q(e)}dispose(){for(const[e,t]of this.injectables)t.dispose();P(this,q)}register(e){const t=R.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){N(this,"injectables",new Map),N(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.AbstractEventManager=class{},exports.Assemblage=t=>{const n=t?a(t):{};return t=>(s("is_assemblage",!0,t),s(e,n,t),t)},exports.Assembler=q,exports.Configuration=d,exports.Context=f,exports.Definition=g,exports.EventManager=$;
package/dist/index.mjs CHANGED
@@ -216,7 +216,7 @@ const forIn = (e)=>(t)=>{
216
216
  t(r(o));
217
217
  }
218
218
  };
219
- const e$3 = (e, t)=>{
219
+ const e$4 = (e, t)=>{
220
220
  return [
221
221
  ...Object.getOwnPropertyNames(t.prototype),
222
222
  ...Object.getOwnPropertyNames(Object.getPrototypeOf(e)),
@@ -228,7 +228,7 @@ const proxifyIterable = (t, r)=>{
228
228
  get: function(o, n) {
229
229
  if (n === Symbol.iterator) {
230
230
  return o[Symbol.iterator].bind(o);
231
- } else if (!e$3(t, r).includes(n)) {
231
+ } else if (!e$4(t, r).includes(n)) {
232
232
  return o.collection[n];
233
233
  }
234
234
  return o[n];
@@ -268,96 +268,7 @@ const callHook = (n, r, t)=>{
268
268
  });
269
269
  };
270
270
 
271
- const i = (n)=>{
272
- return {
273
- identifier: n[0],
274
- concrete: n[0],
275
- configuration: {}
276
- };
277
- };
278
- const c = (r)=>{
279
- const i = ()=>isClass(r[0]) && isClass(r[1]);
280
- const c = ()=>isClass(r[0]) && isObject(r[1]);
281
- const u = ()=>pipe(conditionally({
282
- if: ()=>i(),
283
- then: ()=>{
284
- return {
285
- identifier: r[0],
286
- concrete: r[1],
287
- configuration: {}
288
- };
289
- }
290
- }), conditionally({
291
- if: ()=>c(),
292
- then: ()=>{
293
- return {
294
- identifier: r[0],
295
- concrete: r[0],
296
- configuration: r[1]
297
- };
298
- },
299
- else: (n)=>n
300
- }))();
301
- return u();
302
- };
303
- const u = (n)=>{
304
- return {
305
- identifier: n[0],
306
- concrete: n[1],
307
- configuration: n[2]
308
- };
309
- };
310
- const resolveInjectionTuple = (n)=>switchCase({
311
- 1: ()=>i(n),
312
- 2: ()=>c(n),
313
- 3: ()=>u(n)
314
- }, ()=>{
315
- throw new Error(`Injection tuple must be of length 1, 2 or 3.`);
316
- })(n.length);
317
-
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) {
271
+ function e$3(e, t, n) {
361
272
  if (t in e) {
362
273
  Object.defineProperty(e, t, {
363
274
  value: n,
@@ -466,13 +377,13 @@ class ListenerCollection {
466
377
  };
467
378
  }
468
379
  constructor(){
469
- e$2(this, "collection", {});
380
+ e$3(this, "collection", {});
470
381
  const t = proxifyIterable(this, ListenerCollection);
471
382
  return t;
472
383
  }
473
384
  }
474
385
 
475
- function e$1(e, n, s) {
386
+ function e$2(e, n, s) {
476
387
  if (n in e) {
477
388
  Object.defineProperty(e, n, {
478
389
  value: s,
@@ -574,51 +485,140 @@ class EventManager {
574
485
  return onlyAlphanumeric(e, '*');
575
486
  }
576
487
  constructor(...n){
577
- e$1(this, "listeners", new ListenerCollection());
578
- e$1(this, "onceListeners", new ListenerCollection());
579
- e$1(this, "channels", new Set([
488
+ e$2(this, "listeners", new ListenerCollection());
489
+ e$2(this, "onceListeners", new ListenerCollection());
490
+ e$2(this, "channels", new Set([
580
491
  '*'
581
492
  ]));
582
493
  this.addChannels(...n);
583
494
  }
584
495
  }
585
496
 
586
- function t(t, e, i) {
587
- if (e in t) {
588
- Object.defineProperty(t, e, {
589
- value: i,
497
+ const i = (n)=>{
498
+ return {
499
+ identifier: n[0],
500
+ concrete: n[0],
501
+ configuration: {}
502
+ };
503
+ };
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
+ };
515
+ }
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();
528
+ };
529
+ const u = (n)=>{
530
+ return {
531
+ identifier: n[0],
532
+ concrete: n[1],
533
+ configuration: n[2]
534
+ };
535
+ };
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
+
544
+ const resolveParameters = (o)=>{
545
+ 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++;
553
+ continue;
554
+ }
555
+ if (i.configuration.includes(s)) {
556
+ t.push(o.configuration);
557
+ s++;
558
+ continue;
559
+ }
560
+ if (i.definition.includes(s)) {
561
+ t.push(o.definition);
562
+ s++;
563
+ continue;
564
+ }
565
+ t.push(o.context.require(n));
566
+ s++;
567
+ }
568
+ return t;
569
+ };
570
+ const resolveDependencies = (o)=>{
571
+ 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++;
578
+ continue;
579
+ }
580
+ t.push(n);
581
+ s++;
582
+ }
583
+ return t;
584
+ };
585
+
586
+ function e$1(e, t, n) {
587
+ if (t in e) {
588
+ Object.defineProperty(e, t, {
589
+ value: n,
590
590
  enumerable: true,
591
591
  configurable: true,
592
592
  writable: true
593
593
  });
594
594
  } else {
595
- t[e] = i;
595
+ e[t] = n;
596
596
  }
597
- return t;
597
+ return e;
598
598
  }
599
599
  class Injectable {
600
- static of(t, e) {
601
- return new Injectable(t, e);
600
+ static of(e, t) {
601
+ return new Injectable(e, t);
602
602
  }
603
603
  dispose() {
604
- if (this.singleton) {
605
- callHook(this.singleton, 'onDispose', this.context);
604
+ if (this.singletonInstance) {
605
+ callHook(this.singletonInstance, 'onDispose', this.context);
606
606
  }
607
607
  clearInstance(this, Injectable);
608
608
  }
609
609
  build() {
610
- if (this.singleton) return this.singleton;
611
- const t = resolveParameters(this.concrete, this.context, this.definition, this.configuration);
612
- const e = new this.concrete(...t);
613
- const i = this.concrete.prototype instanceof EventManager;
614
- if (i) {
615
- e.addChannels(...this.events);
610
+ if (this.singletonInstance) return this.singletonInstance;
611
+ const e = resolveParameters(this);
612
+ const t = new this.concrete(...e);
613
+ const n = this.concrete.prototype instanceof EventManager;
614
+ if (n) {
615
+ t.addChannels(...this.events);
616
616
  }
617
- callHook(e, 'onInit', this.context);
617
+ callHook(t, 'onInit', this.context);
618
618
  if (this.isSingleton) {
619
- this.singleton = e;
619
+ this.singletonInstance = t;
620
620
  }
621
- return e;
621
+ return t;
622
622
  }
623
623
  get dependencies() {
624
624
  return this.dependenciesIds;
@@ -629,6 +629,9 @@ class Injectable {
629
629
  get isSingleton() {
630
630
  return getDefinitionValue('singleton', this.concrete) || true;
631
631
  }
632
+ get singleton() {
633
+ return this.singletonInstance;
634
+ }
632
635
  get injections() {
633
636
  return getDefinitionValue('inject', this.concrete) || [];
634
637
  }
@@ -638,22 +641,21 @@ class Injectable {
638
641
  get events() {
639
642
  return getDefinitionValue('events', this.concrete) || [];
640
643
  }
641
- constructor(e, i){
642
- t(this, "context", undefined);
643
- t(this, "identifier", undefined);
644
- t(this, "concrete", undefined);
645
- t(this, "configuration", undefined);
646
- t(this, "singleton", undefined);
647
- t(this, "dependenciesIds", undefined);
644
+ constructor(t, i){
645
+ e$1(this, "context", undefined);
646
+ e$1(this, "identifier", undefined);
647
+ e$1(this, "concrete", undefined);
648
+ e$1(this, "configuration", undefined);
649
+ e$1(this, "dependenciesIds", undefined);
650
+ e$1(this, "singletonInstance", undefined);
648
651
  this.context = i;
649
652
  this.dependenciesIds = [];
650
- const n = resolveInjectionTuple(e);
651
- this.identifier = n.identifier;
652
- this.concrete = n.concrete;
653
- this.configuration = n.configuration;
654
- for (const t of this.injections){
655
- this.context.register(t);
656
- }
653
+ const s = resolveInjectionTuple(t);
654
+ this.identifier = s.identifier;
655
+ this.concrete = s.concrete;
656
+ this.configuration = s.configuration;
657
+ const o = forOf(this.injections);
658
+ o((e)=>this.context.register(e));
657
659
  this.dependenciesIds = resolveDependencies(this.concrete);
658
660
  if (this.isSingleton) {
659
661
  this.build();
@@ -732,4 +734,7 @@ class Assembler {
732
734
  }
733
735
  }
734
736
 
735
- export { AbstractAssemblage, AbstractAssembler, Assemblage, Assembler, x as Configuration, s as Context, c$1 as Definition };
737
+ class AbstractEventManager {
738
+ }
739
+
740
+ export { AbstractAssemblage, AbstractAssembler, AbstractEventManager, Assemblage, Assembler, x as Configuration, s as Context, c$1 as Definition, 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.98",
4
+ "version": "0.1.0",
5
5
  "author": "Benoît LAHOZ <info@benoitlahoz.io>",
6
6
  "bugs": "https://github.com/benoitlahoz/assemblerjs/issues",
7
7
  "devDependencies": {