assemblerjs 0.7.4 → 0.7.6

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  A general purpose and zero-dependency [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) library for node and browser.
4
4
 
5
- ![Statements](https://img.shields.io/badge/statements-91.28%25-brightgreen.svg?style=flat) ![Branches](https://img.shields.io/badge/branches-80.32%25-yellow.svg?style=flat) ![Functions](https://img.shields.io/badge/functions-87.62%25-yellow.svg?style=flat) ![Lines](https://img.shields.io/badge/lines-90.89%25-brightgreen.svg?style=flat)
5
+ ![Statements](https://img.shields.io/badge/statements-91.14%25-brightgreen.svg?style=flat) ![Branches](https://img.shields.io/badge/branches-79.6%25-red.svg?style=flat) ![Functions](https://img.shields.io/badge/functions-87.56%25-yellow.svg?style=flat) ![Lines](https://img.shields.io/badge/lines-90.76%25-brightgreen.svg?style=flat)
6
6
 
7
7
  ---
8
8
 
package/dist/index.d.ts CHANGED
@@ -114,8 +114,6 @@ declare interface AssemblageDefinition {
114
114
  metadata?: Record<string, any>;
115
115
  }
116
116
 
117
- export declare const AssemblageWrappedDecorator: (fn?: () => void) => any;
118
-
119
117
  /**
120
118
  * `assembler.js` dependency injection container and handler.
121
119
  */
@@ -320,20 +318,34 @@ export declare class Assembler extends EventManager implements AbstractAssembler
320
318
  Record<string, any>
321
319
  ]>;
322
320
 
321
+ /**
322
+ * A custom decorator that adds a function called after the original constructor
323
+ * and that can wrap an `Assemblage` with its own parameters decorator (e.g. @Use, @Context, ...).
324
+ * Note that it must be placed before the `Assemnblage` decorator.
325
+ *
326
+ * @param { function(): void | undefined } fn A function to execute after `super`.
327
+ * Do not use arrow function here if access to `this` is required.
328
+ * @param { boolean | undefined } asAssemblage If `true` decorate the class as an assemblage (defaults to `true`).
329
+ * @returns A new decorator.
330
+ */
331
+ export declare const ConstructorDecorator: (fn?: () => void, asAssemblage?: boolean) => any;
332
+
323
333
  /**
324
334
  * Injects the Assembler's context.
325
335
  */
326
336
  export declare const Context: () => ParameterDecorator;
327
337
 
328
338
  /**
329
- * Create a custom decorator to wrap `Assemblage`.
339
+ * Create a custom decorator that adds a function called after the original constructor
340
+ * and that can wrap an `Assemblage` with its own parameters decorator (e.g. @Use, @Context, ...).
330
341
  * Note that it must be placed before the `Assemnblage` decorator.
331
342
  *
332
343
  * @param { function(): void | undefined } fn A function to execute after `super`.
333
344
  * Do not use arrow function here if access to `this` is required.
345
+ * @param { boolean | undefined } asAssemblage If `true` decorate the class as an assemblage (defaults to `true`).
334
346
  * @returns A new decorator.
335
347
  */
336
- export declare const createWrappedDecorator: (fn?: () => void) => any;
348
+ export declare const createConstructorDecorator: (fn?: () => void, asAssemblage?: boolean) => any;
337
349
 
338
350
  export declare const decorateAssemblage: <T>(target: Concrete<T>, definition?: AssemblageDefinition) => Concrete<T>;
339
351
 
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="design:paramtypes";var t=function(e){return e.IsAssemblage="is_assemblage",e}({}),n=function(e){return e.AssemblageDefinition="assemblage:definition.value",e}({});const s=(...e)=>{},i=(...e)=>t=>{if(e.includes(typeof t))return typeof t},r=e=>!(e=>void 0===e)(e)&&!(e=>null===e)(e),o=e=>e&&"function"==typeof e&&void 0!==e.constructor,c=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,a=(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,"")},l=(...e)=>t=>e.reduce(((e,t)=>t(e)),t),h=e=>t=>e.if(t)?e.then(t):e.else?e.else(t):void 0,u=e=>t=>{const n=Array.isArray(e)?e=>parseInt(e):s;for(const[s,i]of Object.entries(e))t(i,n(s))},f=(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},d=(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]},p=(e,t,n)=>{Reflect.defineMetadata(`__${e}__`,t,n)},g=(e,t)=>Reflect.getOwnMetadata(`__${e}__`,t),b=t=>Reflect.getMetadata(e,t)||[],m=e=>g(t.IsAssemblage,e)||!1,y={singleton:{test:e=>"boolean"==typeof e||void 0===e,throw:()=>{throw new Error("'singleton' property must be of type 'boolean' or 'undefined'.")},transform:e=>void 0===e||!!e},events:{test:e=>void 0===e||Array.isArray(e)&&e.every((e=>"string"==typeof e)),throw:()=>{throw new Error("'events' property must be an array of strings or 'undefined'.")},transform:e=>e},inject:{test:e=>void 0===e||Array.isArray(e)&&e.every((e=>Array.isArray(e)&&e.length>=1&&e.length<=3)),throw:()=>{throw new Error("'inject' property must be an array of tuples of length 1, 2 or 3.")},transform:e=>e},use:{test:e=>void 0===e||Array.isArray(e)&&e.every((e=>Array.isArray(e)&&2==e.length)),throw:()=>{throw new Error("'use' property must be an array of tuples of length 2.")},transform:e=>e},tags:{test:e=>void 0===e||"string"==typeof e||Array.isArray(e)&&e.every((e=>"string"==typeof e)),throw:()=>{throw new Error("'tags' property must be a string or an array of strings.")},transform:e=>"string"==typeof e?[e]:e},metadata:{test:e=>("object"==typeof e||void 0===e)&&!Array.isArray(e),throw:()=>{throw new Error("'metadata' property must be of type 'object' or 'undefined'.")},transform:e=>e}},v=e=>{const t={...e};for(const n in t)if(!Object.keys(y).includes(n))throw new Error(`Property '${n}' is not a valid assemblage definition property.`);for(const n in y){const e=y[n].test,s=y[n].throw,i=y[n].transform;e(t[n])||s(),t[n]=i(t[n])}return t},C=e=>{if(!m(e))throw new Error(`Class '${e.name}' is not an assemblage.`);return g(n.AssemblageDefinition,e)},w=(e,t)=>C(t)[e],x=e=>{const t=()=>o(e[0])&&(e=>"object"==typeof e&&!Array.isArray(e)&&!o(e))(e[1]);return l(h({if:()=>o(e[0])&&o(e[1]),then:()=>({identifier:e[0],concrete:e[1],configuration:{}})}),h({if:()=>t(),then:()=>({identifier:e[0],concrete:e[0],configuration:e[1]}),else:e=>e}))()},j=(e,s)=>{const i=v(s||{});return p(t.IsAssemblage,!0,e),p(n.AssemblageDefinition,i,e),e};let A=Symbol.iterator;class I{dispose(){d(this,I)}add(...e){const t=e=>this.collection[e.channel].push(e.listener),n=h({if:()=>2===e.length,then:()=>({channel:e[0],listener:e[1]}),else:()=>{const t=e[0];return{channel:t[0],listener:t[1]}}}),s=h({if:e=>!r(this.collection[e.channel]),then:e=>{this.collection[e.channel]=[],t(e)},else:e=>{t(e)}});return l(n,s)(),this}remove(e,t){const n=t=>this.collection[e].splice(t,1),s=h({if:()=>this.collection[e]&&0===this.collection[e].length,then:()=>delete this.collection[e]}),i=h({if:()=>r(t),then:()=>n(this.collection[e].indexOf(t)),else:()=>delete this.collection[e]}),o=h({if:e=>this.has(e),then:e=>this.collection[e]});return l(o,i,s)(),this}has(...e){return i("string")(e[0])?Object.keys(this.collection).includes(e[0]):!!i("function")(e[0])&&Object.values(this.collection).flat().includes(e[0])}get(...e){return i("string")(e[0])?this.collection[e[0]]:i("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=>u(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}[A](){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 f(this,I)}}class O{}function D(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(),d(this,P)}addChannels(...e){return u(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 u(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=u(e),c=u(s),a=u(i),l=u(r);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(c(e)){return e(...t).then((()=>Promise.resolve()))}e(...t)}cleanChannel(e){return a(e,"*")}constructor(...e){D(this,"listeners",new I),D(this,"onceListeners",new I),D(this,"channels",new Set(["*"])),this.addChannels(...e)}}var E=function(e){return e.UseIdentifier="assemblage:use.param.value",e}({}),U=function(e){return e.Context="assembler:context.param.index",e.Dispose="assembler:dispose.param.index",e.Definition="assemblage:definition.param.index",e.Configuration="assemblage:configuration.param.index",e.Use="assemblage:use.param.index",e}({});const S=e=>()=>(t,n,s)=>{const i=g(e,t)||[];i.push(s),p(e,i,t)},$=S(U.Context),R=S(U.Configuration),M=S(U.Definition),_=S(U.Dispose),k=(e,t,n)=>{const s=g(U.Use,t)||[];s.push(n),p(U.Use,s,t);const i=g(E.UseIdentifier,t)||{};i[n]=e,p(E.UseIdentifier,i,t)},L=e=>{const t=(e=>g(U.Context,e)||[])(e),n=(e=>g(U.Definition,e)||[])(e),s=(e=>g(U.Configuration,e)||[])(e),i=(e=>g(U.Dispose,e)||[])(e),r=(e=>g(U.Use,e)||[])(e);return{Context:t,Definition:n,Configuration:s,Dispose:i,Use:r}},q=t=>s=>{const i=class extends s{constructor(...e){super(...e),t&&t.call(this)}},r=Reflect.getOwnMetadata(e,s)||[],o=L(s),c=[];for(let e=0;e<r.length;e++)if(o.Context.includes(e)){const t=g(U.Context,s)||[];t.push(e),p(U.Context,t,i)}else if(o.Definition.includes(e)){const t=g(U.Definition,s)||[];t.push(e),p(U.Definition,t,i)}else if(o.Configuration.includes(e)){const t=g(U.Configuration,s)||[];t.push(e),p(U.Configuration,t,i)}else if(o.Dispose.includes(e)){const t=g(U.Dispose,s)||[];t.push(e),p(U.Dispose,t,i),c.push(r[e])}else if(o.Use.includes(e)){const t=g(E.UseIdentifier,s);k(t[e],i,e)}else;return Object.defineProperty(i,"name",{value:s.name}),j(i,g(n.AssemblageDefinition,s))};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 H{static of(e,t,n){return new H(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),z(this.singletonInstance,"onDispose",this.publicContext,this.configuration),d(this.singletonInstance,this.concrete)),d(this,H)}build(){if(this.singletonInstance)return this.singletonInstance;const e=(e=>{const t=[],n=b(e.concrete),s=L(e.concrete);let i=0;for(const r of n)if(s.Context.includes(i))t.push(e.publicContext),i++;else if(s.Configuration.includes(i))t.push(e.configuration),i++;else if(s.Definition.includes(i))t.push(e.definition),i++;else if(s.Dispose.includes(i))t.push(e.privateContext.dispose),i++;else if(s.Use.includes(i)){const n=g(E.UseIdentifier,e.concrete)[i];t.push(e.privateContext.require(n)),i++}else 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),this.isSingleton?(this.singletonInstance=t,this.privateContext.prepareInitHook(t,this.configuration),this.singletonInstance):(z(t,"onInit",this.publicContext),t)}get dependencies(){return this.dependenciesIds}get definition(){return C(this.concrete)||{}}get isSingleton(){return w("singleton",this.concrete)}get singleton(){return this.singletonInstance}get injections(){return w("inject",this.concrete)||[]}get objects(){return w("use",this.concrete)||[]}get tags(){return w("tags",this.concrete)||[]}get events(){return w("events",this.concrete)||[]}constructor(e,t,n){if(N(this,"privateContext",void 0),N(this,"publicContext",void 0),N(this,"identifier",void 0),N(this,"concrete",void 0),N(this,"configuration",void 0),N(this,"dependenciesIds",void 0),N(this,"singletonInstance",void 0),this.privateContext=t,this.publicContext=n,this.dependenciesIds=[],this.identifier=e.identifier,this.concrete=e.concrete,this.configuration=e.configuration,!m(this.concrete))throw new Error(`Class '${this.concrete.name}' is not an Assemblage.`);const s=u(this.injections),i=u(this.objects);s((e=>this.privateContext.register(e))),i((e=>{"string"==typeof e[0]||"symbol"==typeof e[0]?this.privateContext.use(e[0],e[1]):this.privateContext.register(e,!0)})),this.dependenciesIds=(e=>{const t=[],n=b(e),s=L(e);let i=0;for(const r of n)s.Context.includes(i)||s.Configuration.includes(i)||s.Definition.includes(i)||s.Dispose.includes(i)||s.Use.includes(i)||t.push(r),i++;return t})(this.concrete),e.instance?this.singletonInstance=e.instance:this.isSingleton}}const z=(e,t,n,s)=>new Promise((i=>{const r=e[t];if(r){if(c(r))return void r.bind(e)(n,s).then((()=>{i()}));i(r.bind(e)(n,s))}}));function W(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class F extends P{static build(e){const t=new F;((e,t,s)=>{const i=C(s);i[e]=t;const r=v(i);p(n.AssemblageDefinition,r,s)})("singleton",!0,e);const s=t.register([e]),i=t.require(s.identifier),r=t.initCache.find((e=>e.instance===i));if(!r)throw new Error("Root instance not found in assemblages cache.");const o=t.initCache.indexOf(r);t.initCache.splice(o,1);for(const n of t.initCache)z(n.instance,"onInit",t.publicContext,n.configuration);return z(i,"onInit",t.publicContext,s.configuration),t.initCache.length=0,i}dispose(){for(const[e,t]of this.injectables)t.dispose();d(this,F)}register(e,t=!1){const n=!0===t?(e=>({identifier:e[0],concrete:e[0],instance:e[1],configuration:{}}))(e):(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:{}}))(e),2:()=>x(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))(e);if(this.has(n.identifier))throw new Error(`An assemblage is already registered with identifier '${n.identifier.name}'.`);const s=H.of(n,this.privateContext,this.publicContext);return this.injectables.set(s.identifier,s),z(s.concrete,"onRegister",this.publicContext,s.configuration),s}use(e,t){if(this.has(e))throw new Error(`A value is already registered with identifier '${String(e)}'.`);return this.objects.set(e,t),t}prepareInitHook(e,t){return this.initCache.push({instance:e,configuration:t}),this.initCache}has(e){return"string"==typeof e||"symbol"==typeof e?this.objects.has(e):this.injectables.has(e)}require(e){switch(typeof e){case"string":case"symbol":if(!this.objects.has(e))throw new Error(`Injected object with identifier '${String(e)}' has not been registered.`);return this.objects.get(e);default:if(!this.injectables.has(e))throw new Error(`Class with identifier '${e.name}' has not been registered or is a circular dependency.`);return this.injectables.get(e).build()}}concrete(e){const t=this.injectables.get(e);if(t)return t.concrete}tagged(...e){const t=[];for(const n of e)for(const[e,s]of this.injectables)s.tags.includes(n)&&t.push(s.build());return t}get size(){return this.injectables.size}constructor(){super(),W(this,"injectables",new Map),W(this,"objects",new Map),W(this,"initCache",[]),W(this,"privateContext",void 0),W(this,"publicContext",void 0),this.publicContext={has:this.has.bind(this),require:this.require.bind(this),concrete:this.concrete.bind(this),tagged:this.tagged.bind(this),dispose:this.dispose.bind(this),on:this.on.bind(this),once:this.once.bind(this),off:this.off.bind(this),events:this.channels},this.privateContext={...this.publicContext,register:this.register.bind(this),use:this.use.bind(this),prepareInitHook:this.prepareInitHook.bind(this),emit:this.emit.bind(this),addChannels:this.addChannels.bind(this),removeChannels:this.removeChannels.bind(this)}}}exports.AbstractAssemblage=class{static onRegister(e,t){}},exports.AbstractAssembler=class extends O{},exports.AbstractEventManager=O,exports.Assemblage=e=>t=>j(t,e),exports.AssemblageWrappedDecorator=q,exports.Assembler=F,exports.Await=(e,t=25)=>(n,s,i)=>{const r=i.value;i.value=async function(){return new Promise((n=>{if(this[e])r.apply(this),n();else{const s=setInterval((()=>{this[e]&&(clearInterval(s),r.apply(this),n())}),t)}}))}},exports.Configuration=R,exports.Context=$,exports.Definition=M,exports.Dispose=_,exports.EventManager=P,exports.ReflectParamIndex=U,exports.ReflectParamValue=E,exports.Use=e=>(t,n,s)=>{k(e,t,s)},exports.createWrappedDecorator=e=>()=>q(e),exports.decorateAssemblage=j,exports.decorateUse=k,exports.getDecoratedParametersIndexes=L,exports.isAssemblage=m;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="design:paramtypes";var t=function(e){return e.IsAssemblage="is_assemblage",e}({}),n=function(e){return e.AssemblageDefinition="assemblage:definition.value",e}({});const s=(...e)=>{},i=(...e)=>t=>{if(e.includes(typeof t))return typeof t},r=e=>!(e=>void 0===e)(e)&&!(e=>null===e)(e),o=e=>e&&"function"==typeof e&&void 0!==e.constructor,c=e=>"function"==typeof e&&"AsyncFunction"===e.constructor.name,a=(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,"")},l=(...e)=>t=>e.reduce(((e,t)=>t(e)),t),h=e=>t=>e.if(t)?e.then(t):e.else?e.else(t):void 0,u=e=>t=>{const n=Array.isArray(e)?e=>parseInt(e):s;for(const[s,i]of Object.entries(e))t(i,n(s))},f=(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},d=(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]},p=(e,t,n)=>{Reflect.defineMetadata(`__${e}__`,t,n)},g=(e,t)=>Reflect.getOwnMetadata(`__${e}__`,t),b=t=>Reflect.getMetadata(e,t)||[],m=e=>g(t.IsAssemblage,e)||!1,y={singleton:{test:e=>"boolean"==typeof e||void 0===e,throw:()=>{throw new Error("'singleton' property must be of type 'boolean' or 'undefined'.")},transform:e=>void 0===e||!!e},events:{test:e=>void 0===e||Array.isArray(e)&&e.every((e=>"string"==typeof e)),throw:()=>{throw new Error("'events' property must be an array of strings or 'undefined'.")},transform:e=>e},inject:{test:e=>void 0===e||Array.isArray(e)&&e.every((e=>Array.isArray(e)&&e.length>=1&&e.length<=3)),throw:()=>{throw new Error("'inject' property must be an array of tuples of length 1, 2 or 3.")},transform:e=>e},use:{test:e=>void 0===e||Array.isArray(e)&&e.every((e=>Array.isArray(e)&&2==e.length)),throw:()=>{throw new Error("'use' property must be an array of tuples of length 2.")},transform:e=>e},tags:{test:e=>void 0===e||"string"==typeof e||Array.isArray(e)&&e.every((e=>"string"==typeof e)),throw:()=>{throw new Error("'tags' property must be a string or an array of strings.")},transform:e=>"string"==typeof e?[e]:e},metadata:{test:e=>("object"==typeof e||void 0===e)&&!Array.isArray(e),throw:()=>{throw new Error("'metadata' property must be of type 'object' or 'undefined'.")},transform:e=>e}},v=e=>{const t={...e};for(const n in t)if(!Object.keys(y).includes(n))throw new Error(`Property '${n}' is not a valid assemblage definition property.`);for(const n in y){const e=y[n].test,s=y[n].throw,i=y[n].transform;e(t[n])||s(),t[n]=i(t[n])}return t},C=e=>{if(!m(e))throw new Error(`Class '${e.name}' is not an assemblage.`);return g(n.AssemblageDefinition,e)},w=(e,t)=>C(t)[e],x=e=>{const t=()=>o(e[0])&&(e=>"object"==typeof e&&!Array.isArray(e)&&!o(e))(e[1]);return l(h({if:()=>o(e[0])&&o(e[1]),then:()=>({identifier:e[0],concrete:e[1],configuration:{}})}),h({if:()=>t(),then:()=>({identifier:e[0],concrete:e[0],configuration:e[1]}),else:e=>e}))()},j=(e,s)=>{const i=v(s||{});return p(t.IsAssemblage,!0,e),p(n.AssemblageDefinition,i,e),e};let A=Symbol.iterator;class I{dispose(){d(this,I)}add(...e){const t=e=>this.collection[e.channel].push(e.listener),n=h({if:()=>2===e.length,then:()=>({channel:e[0],listener:e[1]}),else:()=>{const t=e[0];return{channel:t[0],listener:t[1]}}}),s=h({if:e=>!r(this.collection[e.channel]),then:e=>{this.collection[e.channel]=[],t(e)},else:e=>{t(e)}});return l(n,s)(),this}remove(e,t){const n=t=>this.collection[e].splice(t,1),s=h({if:()=>this.collection[e]&&0===this.collection[e].length,then:()=>delete this.collection[e]}),i=h({if:()=>r(t),then:()=>n(this.collection[e].indexOf(t)),else:()=>delete this.collection[e]}),o=h({if:e=>this.has(e),then:e=>this.collection[e]});return l(o,i,s)(),this}has(...e){return i("string")(e[0])?Object.keys(this.collection).includes(e[0]):!!i("function")(e[0])&&Object.values(this.collection).flat().includes(e[0])}get(...e){return i("string")(e[0])?this.collection[e[0]]:i("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=>u(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}[A](){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 f(this,I)}}class O{}function D(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(),d(this,P)}addChannels(...e){return u(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 u(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=u(e),c=u(s),a=u(i),l=u(r);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(c(e)){return e(...t).then((()=>Promise.resolve()))}e(...t)}cleanChannel(e){return a(e,"*")}constructor(...e){D(this,"listeners",new I),D(this,"onceListeners",new I),D(this,"channels",new Set(["*"])),this.addChannels(...e)}}var E=function(e){return e.UseIdentifier="assemblage:use.param.value",e}({}),U=function(e){return e.Context="assembler:context.param.index",e.Dispose="assembler:dispose.param.index",e.Definition="assemblage:definition.param.index",e.Configuration="assemblage:configuration.param.index",e.Use="assemblage:use.param.index",e}({});const S=e=>()=>(t,n,s)=>{const i=g(e,t)||[];i.push(s),p(e,i,t)},$=S(U.Context),R=S(U.Configuration),M=S(U.Definition),_=S(U.Dispose),k=(e,t,n)=>{const s=g(U.Use,t)||[];s.push(n),p(U.Use,s,t);const i=g(E.UseIdentifier,t)||{};i[n]=e,p(E.UseIdentifier,i,t)},L=e=>{const t=(e=>g(U.Context,e)||[])(e),n=(e=>g(U.Definition,e)||[])(e),s=(e=>g(U.Configuration,e)||[])(e),i=(e=>g(U.Dispose,e)||[])(e),r=(e=>g(U.Use,e)||[])(e);return{Context:t,Definition:n,Configuration:s,Dispose:i,Use:r}},q=(t,s=!0)=>i=>{const r=class extends i{constructor(...e){super(...e),t&&t.call(this)}};if(Object.defineProperty(r,"name",{value:i.name}),!s)return r;const o=Reflect.getOwnMetadata(e,i)||[],c=L(i),a=[];for(let e=0;e<o.length;e++)if(c.Context.includes(e)){const t=g(U.Context,i)||[];t.push(e),p(U.Context,t,r)}else if(c.Definition.includes(e)){const t=g(U.Definition,i)||[];t.push(e),p(U.Definition,t,r)}else if(c.Configuration.includes(e)){const t=g(U.Configuration,i)||[];t.push(e),p(U.Configuration,t,r)}else if(c.Dispose.includes(e)){const t=g(U.Dispose,i)||[];t.push(e),p(U.Dispose,t,r),a.push(o[e])}else if(c.Use.includes(e)){const t=g(E.UseIdentifier,i);k(t[e],r,e)}else;return s?j(r,g(n.AssemblageDefinition,i)):r};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 H{static of(e,t,n){return new H(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),z(this.singletonInstance,"onDispose",this.publicContext,this.configuration),d(this.singletonInstance,this.concrete)),d(this,H)}build(){if(this.singletonInstance)return this.singletonInstance;const e=(e=>{const t=[],n=b(e.concrete),s=L(e.concrete);let i=0;for(const r of n)if(s.Context.includes(i))t.push(e.publicContext),i++;else if(s.Configuration.includes(i))t.push(e.configuration),i++;else if(s.Definition.includes(i))t.push(e.definition),i++;else if(s.Dispose.includes(i))t.push(e.privateContext.dispose),i++;else if(s.Use.includes(i)){const n=g(E.UseIdentifier,e.concrete)[i];t.push(e.privateContext.require(n)),i++}else 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),this.isSingleton?(this.singletonInstance=t,this.privateContext.prepareInitHook(t,this.configuration),this.singletonInstance):(z(t,"onInit",this.publicContext),t)}get dependencies(){return this.dependenciesIds}get definition(){return C(this.concrete)||{}}get isSingleton(){return w("singleton",this.concrete)}get singleton(){return this.singletonInstance}get injections(){return w("inject",this.concrete)||[]}get objects(){return w("use",this.concrete)||[]}get tags(){return w("tags",this.concrete)||[]}get events(){return w("events",this.concrete)||[]}constructor(e,t,n){if(N(this,"privateContext",void 0),N(this,"publicContext",void 0),N(this,"identifier",void 0),N(this,"concrete",void 0),N(this,"configuration",void 0),N(this,"dependenciesIds",void 0),N(this,"singletonInstance",void 0),this.privateContext=t,this.publicContext=n,this.dependenciesIds=[],this.identifier=e.identifier,this.concrete=e.concrete,this.configuration=e.configuration,!m(this.concrete))throw new Error(`Class '${this.concrete.name}' is not an Assemblage.`);const s=u(this.injections),i=u(this.objects);s((e=>this.privateContext.register(e))),i((e=>{"string"==typeof e[0]||"symbol"==typeof e[0]?this.privateContext.use(e[0],e[1]):this.privateContext.register(e,!0)})),this.dependenciesIds=(e=>{const t=[],n=b(e),s=L(e);let i=0;for(const r of n)s.Context.includes(i)||s.Configuration.includes(i)||s.Definition.includes(i)||s.Dispose.includes(i)||s.Use.includes(i)||t.push(r),i++;return t})(this.concrete),e.instance?this.singletonInstance=e.instance:this.isSingleton}}const z=(e,t,n,s)=>new Promise((i=>{const r=e[t];if(r){if(c(r))return void r.bind(e)(n,s).then((()=>{i()}));i(r.bind(e)(n,s))}}));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 T extends P{static build(e){const t=new T;((e,t,s)=>{const i=C(s);i[e]=t;const r=v(i);p(n.AssemblageDefinition,r,s)})("singleton",!0,e);const s=t.register([e]),i=t.require(s.identifier),r=t.initCache.find((e=>e.instance===i));if(!r)throw new Error("Root instance not found in assemblages cache.");const o=t.initCache.indexOf(r);t.initCache.splice(o,1);for(const n of t.initCache)z(n.instance,"onInit",t.publicContext,n.configuration);return z(i,"onInit",t.publicContext,s.configuration),t.initCache.length=0,i}dispose(){for(const[e,t]of this.injectables)t.dispose();d(this,T)}register(e,t=!1){const n=!0===t?(e=>({identifier:e[0],concrete:e[0],instance:e[1],configuration:{}}))(e):(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:{}}))(e),2:()=>x(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))(e);if(this.has(n.identifier))throw new Error(`An assemblage is already registered with identifier '${n.identifier.name}'.`);const s=H.of(n,this.privateContext,this.publicContext);return this.injectables.set(s.identifier,s),z(s.concrete,"onRegister",this.publicContext,s.configuration),s}use(e,t){if(this.has(e))throw new Error(`A value is already registered with identifier '${String(e)}'.`);return this.objects.set(e,t),t}prepareInitHook(e,t){return this.initCache.push({instance:e,configuration:t}),this.initCache}has(e){return"string"==typeof e||"symbol"==typeof e?this.objects.has(e):this.injectables.has(e)}require(e){switch(typeof e){case"string":case"symbol":if(!this.objects.has(e))throw new Error(`Injected object with identifier '${String(e)}' has not been registered.`);return this.objects.get(e);default:if(!this.injectables.has(e))throw new Error(`Class with identifier '${e.name}' has not been registered or is a circular dependency.`);return this.injectables.get(e).build()}}concrete(e){const t=this.injectables.get(e);if(t)return t.concrete}tagged(...e){const t=[];for(const n of e)for(const[e,s]of this.injectables)s.tags.includes(n)&&t.push(s.build());return t}get size(){return this.injectables.size}constructor(){super(),F(this,"injectables",new Map),F(this,"objects",new Map),F(this,"initCache",[]),F(this,"privateContext",void 0),F(this,"publicContext",void 0),this.publicContext={has:this.has.bind(this),require:this.require.bind(this),concrete:this.concrete.bind(this),tagged:this.tagged.bind(this),dispose:this.dispose.bind(this),on:this.on.bind(this),once:this.once.bind(this),off:this.off.bind(this),events:this.channels},this.privateContext={...this.publicContext,register:this.register.bind(this),use:this.use.bind(this),prepareInitHook:this.prepareInitHook.bind(this),emit:this.emit.bind(this),addChannels:this.addChannels.bind(this),removeChannels:this.removeChannels.bind(this)}}}exports.AbstractAssemblage=class{static onRegister(e,t){}},exports.AbstractAssembler=class extends O{},exports.AbstractEventManager=O,exports.Assemblage=e=>t=>j(t,e),exports.Assembler=T,exports.Await=(e,t=25)=>(n,s,i)=>{const r=i.value;i.value=async function(){return new Promise((n=>{if(this[e])r.apply(this),n();else{const s=setInterval((()=>{this[e]&&(clearInterval(s),r.apply(this),n())}),t)}}))}},exports.Configuration=R,exports.ConstructorDecorator=q,exports.Context=$,exports.Definition=M,exports.Dispose=_,exports.EventManager=P,exports.ReflectParamIndex=U,exports.ReflectParamValue=E,exports.Use=e=>(t,n,s)=>{k(e,t,s)},exports.createConstructorDecorator=(e,t=!0)=>()=>q(e,t),exports.decorateAssemblage=j,exports.decorateUse=k,exports.getDecoratedParametersIndexes=L,exports.isAssemblage=m;
package/dist/index.mjs CHANGED
@@ -617,55 +617,59 @@ const getDecoratedParametersIndexes = (t)=>{
617
617
  };
618
618
  };
619
619
 
620
- const createWrappedDecorator = (e)=>{
621
- return ()=>AssemblageWrappedDecorator(e);
622
- };
623
- const AssemblageWrappedDecorator = (p)=>(u)=>{
624
- const f = class extends u {
625
- constructor(...e){
626
- super(...e);
627
- if (p) p.call(this);
620
+ const createConstructorDecorator = (t, o = true)=>{
621
+ return ()=>ConstructorDecorator(t, o);
622
+ };
623
+ const ConstructorDecorator = (f, a = true)=>(p)=>{
624
+ const m = class extends p {
625
+ constructor(...t){
626
+ super(...t);
627
+ if (f) f.call(this);
628
628
  }
629
629
  };
630
- const m = Reflect.getOwnMetadata(ReflectParamTypes, u) || [];
631
- const l = getDecoratedParametersIndexes(u);
630
+ Object.defineProperty(m, 'name', {
631
+ value: p.name
632
+ });
633
+ if (!a) {
634
+ return m;
635
+ }
636
+ const l = Reflect.getOwnMetadata(ReflectParamTypes, p) || [];
637
+ const D = getDecoratedParametersIndexes(p);
632
638
  const d = [];
633
- for(let t = 0; t < m.length; t++){
634
- if (l.Context.includes(t)) {
635
- const n = getOwnCustomMetadata(ReflectParamIndex.Context, u) || [];
636
- n.push(t);
637
- defineCustomMetadata(ReflectParamIndex.Context, n, f);
639
+ for(let n = 0; n < l.length; n++){
640
+ if (D.Context.includes(n)) {
641
+ const e = getOwnCustomMetadata(ReflectParamIndex.Context, p) || [];
642
+ e.push(n);
643
+ defineCustomMetadata(ReflectParamIndex.Context, e, m);
638
644
  continue;
639
645
  }
640
- if (l.Definition.includes(t)) {
641
- const n = getOwnCustomMetadata(ReflectParamIndex.Definition, u) || [];
642
- n.push(t);
643
- defineCustomMetadata(ReflectParamIndex.Definition, n, f);
646
+ if (D.Definition.includes(n)) {
647
+ const e = getOwnCustomMetadata(ReflectParamIndex.Definition, p) || [];
648
+ e.push(n);
649
+ defineCustomMetadata(ReflectParamIndex.Definition, e, m);
644
650
  continue;
645
651
  }
646
- if (l.Configuration.includes(t)) {
647
- const n = getOwnCustomMetadata(ReflectParamIndex.Configuration, u) || [];
648
- n.push(t);
649
- defineCustomMetadata(ReflectParamIndex.Configuration, n, f);
652
+ if (D.Configuration.includes(n)) {
653
+ const e = getOwnCustomMetadata(ReflectParamIndex.Configuration, p) || [];
654
+ e.push(n);
655
+ defineCustomMetadata(ReflectParamIndex.Configuration, e, m);
650
656
  continue;
651
657
  }
652
- if (l.Dispose.includes(t)) {
653
- const n = getOwnCustomMetadata(ReflectParamIndex.Dispose, u) || [];
654
- n.push(t);
655
- defineCustomMetadata(ReflectParamIndex.Dispose, n, f);
656
- d.push(m[t]);
658
+ if (D.Dispose.includes(n)) {
659
+ const e = getOwnCustomMetadata(ReflectParamIndex.Dispose, p) || [];
660
+ e.push(n);
661
+ defineCustomMetadata(ReflectParamIndex.Dispose, e, m);
662
+ d.push(l[n]);
657
663
  continue;
658
664
  }
659
- if (l.Use.includes(t)) {
660
- const e = getOwnCustomMetadata(ReflectParamValue.UseIdentifier, u);
661
- decorateUse(e[t], f, t);
665
+ if (D.Use.includes(n)) {
666
+ const t = getOwnCustomMetadata(ReflectParamValue.UseIdentifier, p);
667
+ decorateUse(t[n], m, n);
662
668
  continue;
663
669
  }
664
670
  }
665
- Object.defineProperty(f, 'name', {
666
- value: u.name
667
- });
668
- return decorateAssemblage(f, getOwnCustomMetadata(ReflectValue.AssemblageDefinition, u));
671
+ if (!a) return m;
672
+ return decorateAssemblage(m, getOwnCustomMetadata(ReflectValue.AssemblageDefinition, p));
669
673
  };
670
674
 
671
675
  const resolveInjectableParameters = (i)=>{
@@ -968,4 +972,4 @@ class Assembler extends EventManager {
968
972
  class AbstractAssembler extends AbstractEventManager {
969
973
  }
970
974
 
971
- export { AbstractAssemblage, AbstractAssembler, AbstractEventManager, Assemblage, AssemblageWrappedDecorator, Assembler, Await, r$1 as Configuration, s$1 as Context, c$1 as Definition, e$2 as Dispose, EventManager, ReflectParamIndex, ReflectParamValue, Use, createWrappedDecorator, decorateAssemblage, decorateUse, getDecoratedParametersIndexes, isAssemblage };
975
+ export { AbstractAssemblage, AbstractAssembler, AbstractEventManager, Assemblage, Assembler, Await, r$1 as Configuration, ConstructorDecorator, s$1 as Context, c$1 as Definition, e$2 as Dispose, EventManager, ReflectParamIndex, ReflectParamValue, Use, createConstructorDecorator, decorateAssemblage, decorateUse, getDecoratedParametersIndexes, isAssemblage };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "assemblerjs",
3
3
  "description": "A general purpose and zero-dependency Dependency Injection library for node and browser.",
4
- "version": "0.7.4",
4
+ "version": "0.7.6",
5
5
  "author": "Benoît LAHOZ <info@benoitlahoz.io>",
6
6
  "bugs": "https://github.com/benoitlahoz/assemblerjs/issues",
7
7
  "devDependencies": {
@@ -49,7 +49,8 @@
49
49
  "multi",
50
50
  "reflection",
51
51
  "swc",
52
- "typescript"
52
+ "typescript",
53
+ "reflect-metadata"
53
54
  ],
54
55
  "license": "MIT",
55
56
  "main": "dist/index.js",