assemblerjs 0.3.1 → 0.3.21
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 +69 -9
- package/dist/index.d.ts +9 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +2 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# assembler.js
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
[](https://badge.fury.io/js/assemblerjs)
|
|
3
|
+
A general purpose and zero-dependency [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) framework for node and browser.
|
|
6
4
|
|
|
7
|
-
   
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
---
|
|
10
8
|
|
|
11
9
|
`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)>).
|
|
12
10
|
|
|
@@ -24,8 +22,70 @@ npm install assemblerjs
|
|
|
24
22
|
|
|
25
23
|
### Order of execution
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
Dependencies are registered and built recursively from the entry assemblage resolved by `Assembler.build`.
|
|
26
|
+
|
|
27
|
+
##### `onRegister`
|
|
28
|
+
|
|
29
|
+
Static hook called when registering the assemblage.
|
|
30
|
+
Other dependencies may or may not have been registered at this point, and dependency tree is not built yet.
|
|
31
|
+
|
|
32
|
+
##### `constructor`
|
|
33
|
+
|
|
34
|
+
Build the instance and requires an instance of each dependency passed to the constructor.
|
|
35
|
+
If the dependency is not a singleton a new instance is returned, meaning the same dependency required in another assemblage will be another object, as when using the `require` method of the `AssemblerContext` passed to hooks or injected by the `@Context` decorator.
|
|
36
|
+
|
|
37
|
+
##### `onInit`
|
|
38
|
+
|
|
39
|
+
Called on every dependency when the dependency tree is ready.
|
|
40
|
+
Except for the entry assemblage (i.e. the one built on bootstrap by `Assembler.build`) the hook is called according to the latter.
|
|
41
|
+
The entry point assemblage is called last.
|
|
42
|
+
|
|
43
|
+
##### `onDispose`
|
|
44
|
+
|
|
45
|
+
Called when disposing the assembler via the `dispose` method injected by the `@Dispose` decorator.
|
|
46
|
+
This will be called like the `onInit` method, walking through the dependency tree, except for the entry point assemblage, called last.
|
|
30
47
|
|
|
31
|
-
|
|
48
|
+
### Events
|
|
49
|
+
|
|
50
|
+
`assembler.js` provides an `EventManager` that can be subclassed by any assemblage.
|
|
51
|
+
|
|
52
|
+
Because all events **are forwarded by `AssemblerContext`** the `EventManager` is quite strict on which events can be broadcasted and they must be registered explicitly using the `events` property of the `AssemblageDefinition`. To avoid collision between events channels, user is strongly encouraged to create _strong_ channels names, e.g.: `com.domain.app.assemblage-name:init`.
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
const prefix = 'com.domain.app.emitter-assemblage';
|
|
56
|
+
|
|
57
|
+
export enum EmitterAssemblageEvents {
|
|
58
|
+
Init = `${prefix}:init`,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@Assemblage({
|
|
62
|
+
events: Object.values(EmitterAssemblageEvents),
|
|
63
|
+
})
|
|
64
|
+
export class EmitterAssemblage
|
|
65
|
+
extends EventManager
|
|
66
|
+
implements AbstractEventAssemblage
|
|
67
|
+
{
|
|
68
|
+
constructor() {
|
|
69
|
+
super();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public async onInit(): Promise<void> {
|
|
73
|
+
this.emit(EmitterAssemblageEvents.Init, true);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@Assemblage()
|
|
78
|
+
export class SubcriberAssemblage implements AbstractAssemblage {
|
|
79
|
+
constructor(@Context() private context: AssemblerContext) {
|
|
80
|
+
context.on(EmitterAssemblageEvents.Init, (value: boolean) => {
|
|
81
|
+
console.log(value); // true.
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
context.on('*', (value: boolean) => {
|
|
85
|
+
console.log(value); // true.
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
Assembler.build(SubcriberAssemblage);
|
|
91
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export declare abstract class AbstractAssemblage {
|
|
|
17
17
|
*/
|
|
18
18
|
static onRegister(context: AssemblerContext): void;
|
|
19
19
|
/**
|
|
20
|
-
* Called
|
|
20
|
+
* Called on instantiated class after the dependency tree is fully resolved.
|
|
21
21
|
*
|
|
22
22
|
* @param { AssemblerContext } context The assembler's context.
|
|
23
23
|
*/
|
|
@@ -168,7 +168,14 @@ declare interface AssemblerPrivateContext extends AssemblerContext {
|
|
|
168
168
|
removeChannels: AbstractAssembler['removeChannels'];
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
|
|
171
|
+
/**
|
|
172
|
+
* Recursively check if a property is defined and truthy to call an async method.
|
|
173
|
+
*
|
|
174
|
+
* @param { string } property The name of the class proprty to wait for.
|
|
175
|
+
* @param { number | undefined } interval The interval in milliseconds at which the value is checked (defaults to 25 milliseconds).
|
|
176
|
+
* @returns { Promise<void> } A promise that calls the original method when resolving.
|
|
177
|
+
*/
|
|
178
|
+
export declare const Await: (property: string, interval?: number) => (_target: any, _propertyKey: string, descriptor: TypedPropertyDescriptor<(...params: any[]) => Promise<any>>) => void;
|
|
172
179
|
|
|
173
180
|
/**
|
|
174
181
|
* Injectable binds a concrete class to an abstract class as identifier without configuration.
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
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))},h=(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},l=(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 u=Symbol.iterator;class f{dispose(){l(this,f)}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}[u](){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 h(this,f)}}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(),l(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),h=a(i),l=a(r);o((e=>{this.run(e,...t),this.onceListeners.remove("*",e)})),c((e=>{this.run(e,...t)})),h((e=>{this.run(e,...t),this.onceListeners.remove(n,e)})),l((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){d(this,"listeners",new f),d(this,"onceListeners",new f),d(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="use_param_index",C="use_token",j=(e,t,n)=>{Reflect.defineMetadata(`__${e}__`,t,n)},O=(e,t)=>Reflect.getOwnMetadata(`__${e}__`,t),A=e=>Reflect.getMetadata("design:paramtypes",e)||[],I={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},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},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}},E=e=>{const t={...e};for(const n in t){if(!Object.keys(I).includes(n))throw new Error(`Property '${n}' is not a valid assemblage definition property.`);const e=I[n].test,s=I[n].throw,i=I[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=>O(b,e),P=(e,t)=>_(t)[e];const $=e=>{const t=e?E(e):{};return e=>(j(g,!0,e),j(b,t,e),e)};class S{}S=function(e,t,n,s){var i,r=arguments.length,o=r<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,n):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,n,s);else for(var c=e.length-1;c>=0;c--)(i=e[c])&&(o=(r<3?i(o):r>3?i(t,n,o):i(t,n))||o);return r>3&&o&&Object.defineProperty(t,n,o),o}([$()],S);const R=(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))}})),k=e=>{const t=(e=>O(y,e)||[])(e),n=(e=>O(m,e)||[])(e),s=(e=>O(v,e)||[])(e),i=(e=>O(w,e)||[])(e),r=(e=>O(x,e)||[])(e);return{context:t,definition:n,configuration:s,dispose:i,use:r}};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 L{static of(e,t,n){return new L(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),R(this.singletonInstance,"onDispose",this.publicContext),l(this.singletonInstance,this.concrete)),l(this,L)}build(){if(this.singletonInstance)return this.singletonInstance;const e=(e=>{const t=[],n=A(e.concrete),s=k(e.concrete);let i=0;for(const r of n)if(s.context.includes(i))t.push(e.publicContext),i++;else if(s.configuration.includes(i))t.push(e.configuration),i++;else if(s.definition.includes(i))t.push(e.definition),i++;else if(s.dispose.includes(i))t.push(e.privateContext.dispose),i++;else if(s.use.includes(i)){const n=O(C,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.prepareInit(t),this.singletonInstance):(R(t,"onInit",this.publicContext),t)}get dependencies(){return this.dependenciesIds}get definition(){return _(this.concrete)||{}}get isSingleton(){return P("singleton",this.concrete)||!0}get singleton(){return this.singletonInstance}get injections(){return P("inject",this.concrete)||[]}get objects(){return P("use",this.concrete)||[]}get tags(){return P("tags",this.concrete)||[]}get events(){return P("events",this.concrete)||[]}constructor(e,t,n){if(M(this,"privateContext",void 0),M(this,"publicContext",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.privateContext=t,this.publicContext=n,this.dependenciesIds=[],this.identifier=e.identifier,this.concrete=e.concrete,this.configuration=e.configuration,!(e=>O(g,e)||!1)(this.concrete))throw new Error(`Class '${this.concrete.name}' is not an Assemblage.`);a(this.injections)((e=>this.privateContext.register(e)));a(this.objects)((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=A(e),s=k(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)}}const q=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}))()},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:{}}))(e),2:()=>q(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 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 z extends p{static build(e){const t=new z;((e,t,n)=>{const s=_(n);s[e]=t,E(s)})("singleton",!0,e);const n=t.register([e]),s=t.require(n.identifier),i=t.initCache.indexOf(s);t.initCache.splice(i,1);for(const r of t.initCache)R(r,"onInit",t.publicContext);return R(s,"onInit",t.publicContext),s}dispose(){for(const[e,t]of this.injectables)t.dispose();l(this,z)}register(e,t=!1){const n=!0===t?{identifier:(s=e)[0],concrete:s[0],instance:s[1],configuration:{}}:N(e);var s;if(this.has(n.identifier))throw new Error(`An assemblage is already registered with identifier '${n.identifier.name}'.`);const i=L.of(n,this.privateContext,this.publicContext);return this.injectables.set(i.identifier,i),R(i.concrete,"onRegister",this.publicContext),i}use(e,t){if(this.has(e))throw new Error(`A valu is already registered for identifier '${String(e)}'.`);return this.objects.set(e,t),t}prepareInit(e){return this.initCache.push(e),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(`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(),D(this,"injectables",new Map),D(this,"objects",new Map),D(this,"initCache",[]),D(this,"privateContext",void 0),D(this,"publicContext",void 0),this.publicContext={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,register:this.register.bind(this),use:this.use.bind(this),prepareInit:this.prepareInit.bind(this),emit:this.emit.bind(this),addChannels:this.addChannels.bind(this),removeChannels:this.removeChannels.bind(this),dispose:this.dispose.bind(this)}}}const W=e=>()=>(t,n,s)=>{const i=O(e,t)||[];i.push(s),j(e,i,t)},F=W(y),T=W(v),U=W(m),Z=W(w);class B{}exports.AbstractAssemblage=class{static onRegister(e){}},exports.AbstractAssembler=class extends B{},exports.AbstractEventManager=B,exports.Assemblage=$,exports.Assembler=z,exports.Await=(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=T,exports.Context=F,exports.Definition=U,exports.Dispose=Z,exports.EventManager=p,exports.Use=e=>(t,n,s)=>{const i=O(x,t)||[];i.push(s),j(x,i,t);const r=O(C,t)||{};r[s]=e,j(C,r,t)};
|
|
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))},h=(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},l=(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 u=Symbol.iterator;class f{dispose(){l(this,f)}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}[u](){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 h(this,f)}}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(),l(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),h=a(i),l=a(r);o((e=>{this.run(e,...t),this.onceListeners.remove("*",e)})),c((e=>{this.run(e,...t)})),h((e=>{this.run(e,...t),this.onceListeners.remove(n,e)})),l((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){d(this,"listeners",new f),d(this,"onceListeners",new f),d(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="use_param_index",C="use_token",j=(e,t,n)=>{Reflect.defineMetadata(`__${e}__`,t,n)},O=(e,t)=>Reflect.getOwnMetadata(`__${e}__`,t),A=e=>Reflect.getMetadata("design:paramtypes",e)||[],I={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},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},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}},E=e=>{const t={...e};for(const n in t){if(!Object.keys(I).includes(n))throw new Error(`Property '${n}' is not a valid assemblage definition property.`);const e=I[n].test,s=I[n].throw,i=I[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=>O(b,e),P=(e,t)=>_(t)[e];const $=e=>{const t=e?E(e):{};return e=>(j(g,!0,e),j(b,t,e),e)};class S{}S=function(e,t,n,s){var i,r=arguments.length,o=r<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,n):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,n,s);else for(var c=e.length-1;c>=0;c--)(i=e[c])&&(o=(r<3?i(o):r>3?i(t,n,o):i(t,n))||o);return r>3&&o&&Object.defineProperty(t,n,o),o}([$()],S);const R=(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))}})),k=e=>{const t=(e=>O(y,e)||[])(e),n=(e=>O(m,e)||[])(e),s=(e=>O(v,e)||[])(e),i=(e=>O(w,e)||[])(e),r=(e=>O(x,e)||[])(e);return{context:t,definition:n,configuration:s,dispose:i,use:r}};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 L{static of(e,t,n){return new L(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),R(this.singletonInstance,"onDispose",this.publicContext),l(this.singletonInstance,this.concrete)),l(this,L)}build(){if(this.singletonInstance)return this.singletonInstance;const e=(e=>{const t=[],n=A(e.concrete),s=k(e.concrete);let i=0;for(const r of n)if(s.context.includes(i))t.push(e.publicContext),i++;else if(s.configuration.includes(i))t.push(e.configuration),i++;else if(s.definition.includes(i))t.push(e.definition),i++;else if(s.dispose.includes(i))t.push(e.privateContext.dispose),i++;else if(s.use.includes(i)){const n=O(C,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.prepareInit(t),this.singletonInstance):(R(t,"onInit",this.publicContext),t)}get dependencies(){return this.dependenciesIds}get definition(){return _(this.concrete)||{}}get isSingleton(){return P("singleton",this.concrete)||!0}get singleton(){return this.singletonInstance}get injections(){return P("inject",this.concrete)||[]}get objects(){return P("use",this.concrete)||[]}get tags(){return P("tags",this.concrete)||[]}get events(){return P("events",this.concrete)||[]}constructor(e,t,n){if(M(this,"privateContext",void 0),M(this,"publicContext",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.privateContext=t,this.publicContext=n,this.dependenciesIds=[],this.identifier=e.identifier,this.concrete=e.concrete,this.configuration=e.configuration,!(e=>O(g,e)||!1)(this.concrete))throw new Error(`Class '${this.concrete.name}' is not an Assemblage.`);a(this.injections)((e=>this.privateContext.register(e)));a(this.objects)((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=A(e),s=k(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)}}const q=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}))()},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:{}}))(e),2:()=>q(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 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 z extends p{static build(e){const t=new z;((e,t,n)=>{const s=_(n);s[e]=t,E(s)})("singleton",!0,e);const n=t.register([e]),s=t.require(n.identifier),i=t.initCache.indexOf(s);t.initCache.splice(i,1);for(const r of t.initCache)R(r,"onInit",t.publicContext);return R(s,"onInit",t.publicContext),t.initCache.length=0,s}dispose(){for(const[e,t]of this.injectables)t.dispose();l(this,z)}register(e,t=!1){const n=!0===t?{identifier:(s=e)[0],concrete:s[0],instance:s[1],configuration:{}}:N(e);var s;if(this.has(n.identifier))throw new Error(`An assemblage is already registered with identifier '${n.identifier.name}'.`);const i=L.of(n,this.privateContext,this.publicContext);return this.injectables.set(i.identifier,i),R(i.concrete,"onRegister",this.publicContext),i}use(e,t){if(this.has(e))throw new Error(`A valu is already registered for identifier '${String(e)}'.`);return this.objects.set(e,t),t}prepareInit(e){return this.initCache.push(e),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(`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(),D(this,"injectables",new Map),D(this,"objects",new Map),D(this,"initCache",[]),D(this,"privateContext",void 0),D(this,"publicContext",void 0),this.publicContext={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,register:this.register.bind(this),use:this.use.bind(this),prepareInit:this.prepareInit.bind(this),emit:this.emit.bind(this),addChannels:this.addChannels.bind(this),removeChannels:this.removeChannels.bind(this),dispose:this.dispose.bind(this)}}}const W=e=>()=>(t,n,s)=>{const i=O(e,t)||[];i.push(s),j(e,i,t)},F=W(y),T=W(v),U=W(m),Z=W(w);class B{}exports.AbstractAssemblage=class{static onRegister(e){}},exports.AbstractAssembler=class extends B{},exports.AbstractEventManager=B,exports.Assemblage=$,exports.Assembler=z,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=T,exports.Context=F,exports.Definition=U,exports.Dispose=Z,exports.EventManager=p,exports.Use=e=>(t,n,s)=>{const i=O(x,t)||[];i.push(s),j(x,i,t);const r=O(C,t)||{};r[s]=e,j(C,r,t)};
|
package/dist/index.mjs
CHANGED
|
@@ -772,6 +772,7 @@ class Assembler extends EventManager {
|
|
|
772
772
|
callHook(e, 'onInit', t.publicContext);
|
|
773
773
|
}
|
|
774
774
|
callHook(s, 'onInit', t.publicContext);
|
|
775
|
+
t.initCache.length = 0;
|
|
775
776
|
return s;
|
|
776
777
|
}
|
|
777
778
|
dispose() {
|
|
@@ -887,7 +888,7 @@ const l = (o)=>{
|
|
|
887
888
|
|
|
888
889
|
const Await = (t, e = 25)=>{
|
|
889
890
|
return (n, s, a)=>{
|
|
890
|
-
|
|
891
|
+
const i = a.value;
|
|
891
892
|
a.value = async function() {
|
|
892
893
|
return new Promise((n)=>{
|
|
893
894
|
if (this[t]) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "assemblerjs",
|
|
3
|
-
"description": "A
|
|
4
|
-
"version": "0.3.
|
|
3
|
+
"description": "A general purpose and zero-dependency Dependency Injection framework for node and browser.",
|
|
4
|
+
"version": "0.3.21",
|
|
5
5
|
"author": "Benoît LAHOZ <info@benoitlahoz.io>",
|
|
6
6
|
"bugs": "https://github.com/benoitlahoz/assemblerjs/issues",
|
|
7
7
|
"devDependencies": {
|