assemblerjs
Version:
A general purpose Dependency Injection library for node and browser.
920 lines (893 loc) • 28.4 kB
JavaScript
import { switchCase, pipe, conditionally, isClass, isObject, clearInstance, isDefined, isOfType, forIn, forOf, proxifyIterable, isAsync, onlyAlphanumeric } from '@assemblerjs/core';
class AbstractAssemblage {
static onRegister(s, t) {}
}
const ReflectParamTypes = 'design:paramtypes';
const ReflectPrefix = '__';
const ReflectSuffix = '__';
var ReflectFlags;
(function(e) {
e["IsAssemblage"] = "is_assemblage";
})(ReflectFlags || (ReflectFlags = {}));
var ReflectValue;
(function(e) {
e["AssemblageDefinition"] = "assemblage:definition.value";
e["AssemblageContext"] = "assemblage:context.value";
})(ReflectValue || (ReflectValue = {}));
const defineCustomMetadata = (t, o, n)=>{
Reflect.defineMetadata(`${ReflectPrefix}${t}${ReflectSuffix}`, o, n);
};
const getOwnCustomMetadata = (t, o)=>{
return Reflect.getOwnMetadata(`${ReflectPrefix}${t}${ReflectSuffix}`, o);
};
const getParamTypes = (e)=>{
return Reflect.getMetadata(ReflectParamTypes, e) || [];
};
const isAssemblage = (s)=>{
return getOwnCustomMetadata(ReflectFlags.IsAssemblage, s) || false;
};
const getAssemblageDefinition = (e)=>{
return getOwnCustomMetadata(ReflectValue.AssemblageDefinition, e);
};
const getAssemblageContext = (e)=>{
return getOwnCustomMetadata(ReflectValue.AssemblageContext, e);
};
const n = {
singleton: {
test: (r)=>typeof r === 'boolean' || typeof r === 'undefined',
throw: ()=>{
throw new Error(`'singleton' property must be of type 'boolean' or 'undefined'.`);
},
transform: (r)=>{
return typeof r === 'undefined' ? true : r ? true : false;
}
},
events: {
test: (r)=>typeof r === 'undefined' || Array.isArray(r) && r.every((r)=>typeof r === 'string'),
throw: ()=>{
throw new Error(`'events' property must be an array of strings or 'undefined'.`);
},
transform: (r)=>r
},
inject: {
test: (r)=>typeof r === 'undefined' || Array.isArray(r) && r.every((r)=>Array.isArray(r) && r.length >= 1 && r.length <= 3),
throw: ()=>{
throw new Error(`'inject' property must be an array of tuples of length 1, 2 or 3.`);
},
transform: (r)=>r
},
use: {
test: (r)=>typeof r === 'undefined' || Array.isArray(r) && r.every((r)=>Array.isArray(r) && r.length == 2),
throw: ()=>{
throw new Error(`'use' property must be an array of tuples of length 2.`);
},
transform: (r)=>r
},
tags: {
test: (r)=>typeof r === 'undefined' || typeof r === 'string' || Array.isArray(r) && r.every((r)=>typeof r === 'string'),
throw: ()=>{
throw new Error(`'tags' property must be a string or an array of strings.`);
},
transform: (r)=>typeof r === 'string' ? [
r
] : r
},
metadata: {
test: (r)=>(typeof r === 'object' || typeof r === 'undefined') && !Array.isArray(r),
throw: ()=>{
throw new Error(`'metadata' property must be of type 'object' or 'undefined'.`);
},
transform: (r)=>r
},
global: {
test: (r)=>(typeof r === 'object' || typeof r === 'undefined') && !Array.isArray(r),
throw: ()=>{
throw new Error(`'global' property must be of type 'object' or 'undefined'.`);
},
transform: (r)=>r
}
};
const validateDefinition = (r)=>{
const t = {
...r
};
for(const r in t){
if (!Object.keys(n).includes(r)) {
throw new Error(`Property '${r}' is not a valid assemblage definition property.`);
}
}
for(const r in n){
const e = n[r].test;
const o = n[r].throw;
const s = n[r].transform;
if (!e(t[r])) {
o();
}
t[r] = s(t[r]);
}
return t;
};
const getDefinition = (t)=>{
if (!isAssemblage(t)) {
throw new Error(`Class '${t.name}' is not an assemblage.`);
}
return getOwnCustomMetadata(ReflectValue.AssemblageDefinition, t);
};
const getDefinitionValue = (r, t)=>{
const e = getDefinition(t);
return e[r];
};
const setDefinitionValue = (e, o, n)=>{
const s = getDefinition(n);
s[e] = o;
const i = validateDefinition(s);
defineCustomMetadata(ReflectValue.AssemblageDefinition, i, n);
return i;
};
const i$2 = (e)=>{
return {
identifier: e[0],
concrete: e[0],
configuration: {}
};
};
const c$2 = (o)=>{
const i = ()=>isClass(o[0]) && isClass(o[1]);
const c = ()=>isClass(o[0]) && isObject(o[1]);
const s = ()=>pipe(conditionally({
if: ()=>i(),
then: ()=>{
return {
identifier: o[0],
concrete: o[1],
configuration: {}
};
}
}), conditionally({
if: ()=>c(),
then: ()=>{
return {
identifier: o[0],
concrete: o[0],
configuration: o[1]
};
},
else: (e)=>e
}))();
return s();
};
const s$2 = (e)=>{
return {
identifier: e[0],
concrete: e[1],
configuration: e[2]
};
};
const resolveInjectionTuple = (e)=>switchCase({
1: ()=>i$2(e),
2: ()=>c$2(e),
3: ()=>s$2(e)
}, ()=>{
throw new Error(`Injection tuple must be of length 1, 2 or 3.`);
})(e.length);
const resolveInstanceInjectionTuple = (e)=>{
return {
identifier: e[0],
concrete: e[0],
instance: e[1],
configuration: {}
};
};
const Assemblage = (e)=>{
return (o)=>{
return decorateAssemblage(o, e);
};
};
const decorateAssemblage = (s, m)=>{
const n = validateDefinition(m || {});
defineCustomMetadata(ReflectFlags.IsAssemblage, true, s);
defineCustomMetadata(ReflectValue.AssemblageDefinition, n, s);
return s;
};
class AbstractListenerCollection {
}
class ListenerCollection {
dispose() {
clearInstance(this, ListenerCollection);
}
add(...t) {
const n = (t)=>this.collection[t.channel].push(t.listener);
const l = conditionally({
if: ()=>t.length === 2,
then: ()=>{
return {
channel: t[0],
listener: t[1]
};
},
else: ()=>{
const e = t[0];
return {
channel: e[0],
listener: e[1]
};
}
});
const c = conditionally({
if: (t)=>!isDefined(this.collection[t.channel]),
then: (t)=>{
this.collection[t.channel] = [];
n(t);
},
else: (t)=>{
n(t);
}
});
pipe(l, c)();
return this;
}
remove(t, n) {
const l = (e)=>this.collection[t].splice(e, 1);
const c = conditionally({
if: ()=>this.collection[t] && this.collection[t].length === 0,
then: ()=>delete this.collection[t]
});
const o = conditionally({
if: ()=>isDefined(n),
then: ()=>l(this.collection[t].indexOf(n)),
else: ()=>delete this.collection[t]
});
const r = conditionally({
if: (t)=>this.has(t),
then: (t)=>this.collection[t]
});
pipe(r, o, c)();
return this;
}
has(...t) {
if (isOfType('string')(t[0])) {
return Object.keys(this.collection).includes(t[0]);
} else if (isOfType('function')(t[0])) {
return Object.values(this.collection).flat().includes(t[0]);
}
return false;
}
get(...t) {
if (isOfType('string')(t[0])) {
return this.collection[t[0]];
} else if (isOfType('function')(t[0])) {
return Object.values(this.collection).flat().filter((e)=>e === t[0]);
}
return [];
}
clear() {
const t = forIn(this.collection);
const e = (t)=>forOf(this.collection[t])((e)=>this.remove(t, e));
t((t)=>e(t));
return 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;
}
[Symbol.iterator]() {
let t = -1;
const e = this.collection ? Object.keys(this.collection) : [];
return {
next: ()=>({
value: e[++t],
done: !(t in e)
})
};
}
constructor(){
this.collection = {};
const t = proxifyIterable(this, ListenerCollection);
return t;
}
}
class AbstractEventManager {
}
class EventManager {
dispose() {
this.listeners.dispose();
this.channels.clear();
clearInstance(this, EventManager);
}
addChannels(...e) {
const n = forOf(e);
n((e)=>{
const s = this.cleanChannel(e);
if (this.channels.has(s)) {
throw new Error(`Channel '${s}' already exists.`);
}
this.channels.add(s);
});
return this;
}
removeChannels(...e) {
const n = forOf(e);
n((e)=>{
const s = this.cleanChannel(e);
if (s !== '*' && this.channels.has(s)) {
this.channels.delete(s);
this.listeners.remove(s);
this.onceListeners.remove(s);
}
});
return this;
}
on(e, s) {
const n = this.cleanChannel(e);
this.listeners.add(n, s);
return this;
}
once(e, s) {
const n = this.cleanChannel(e);
this.onceListeners.add(n, s);
return this;
}
off(e, s) {
const n = this.cleanChannel(e);
this.listeners.remove(n, s);
return this;
}
emit(e, ...n) {
const t = this.cleanChannel(e);
if (this.channels.has(t)) {
const e = this.onceListeners.get('*') || [];
const i = this.listeners.get('*') || [];
const h = this.onceListeners.get(t) || [];
const r = this.listeners.get(t) || [];
const o = forOf(e);
const c = forOf(i);
const l = forOf(h);
const a = forOf(r);
o((e)=>{
this.run(e, ...n);
this.onceListeners.remove('*', e);
});
c((e)=>{
this.run(e, ...n);
});
l((e)=>{
this.run(e, ...n);
this.onceListeners.remove(t, e);
});
a((e)=>{
this.run(e, ...n);
});
}
return this;
}
run(e, ...s) {
if (isAsync(e)) {
const n = e;
return n(...s).then(()=>Promise.resolve());
}
e(...s);
}
cleanChannel(e) {
return onlyAlphanumeric(e, '*', ':', '.', '-', '_');
}
constructor(...e){
this.listeners = new ListenerCollection();
this.onceListeners = new ListenerCollection();
this.channels = new Set([
'*'
]);
this.addChannels(...e);
}
}
const registerEvents = (t, n)=>{
const o = t.concrete.prototype instanceof EventManager;
if (o) {
const e = n;
const o = e.channels;
for (const n of t.events){
if (!o.has(n)) e.addChannels(n);
if (!t.privateContext.events.has(n)) t.privateContext.addChannels(n);
}
for (const e of t.events){
n.on(e, (...n)=>{
t.privateContext.emit(e, ...n);
});
}
} else {
for (const e of t.events){
if (!t.privateContext.events.has(e)) t.privateContext.addChannels(e);
}
}
};
const unregisterEvents = (t, n)=>{
const o = t.concrete.prototype instanceof EventManager;
if (o) {
const e = n;
for (const n of t.events){
e.off(n);
}
e.removeChannels(...t.events);
t.privateContext.removeChannels(...t.events);
} else {
for (const e of t.events){
if (t.privateContext.events.has(e)) {
t.privateContext.removeChannels(e);
}
}
}
};
const Await = (t, e = 25)=>{
return (n, s, a)=>{
const i = a.value;
a.value = async function() {
return new Promise((n)=>{
if (this[t]) {
i.apply(this);
n();
} else {
const s = setInterval(()=>{
if (this[t]) {
clearInterval(s);
i.apply(this);
n();
}
}, e);
}
});
};
};
};
var ReflectParamValue;
(function(e) {
e["UseIdentifier"] = "assemblage:use.param.value";
e["GlobalIdentifier"] = "assemblage:global.param.value";
})(ReflectParamValue || (ReflectParamValue = {}));
var ReflectParamIndex;
(function(e) {
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["Global"] = "assemblage:global.param.index";
})(ReflectParamIndex || (ReflectParamIndex = {}));
const i$1 = (t)=>()=>{
return (i, s, r)=>{
const c = getOwnCustomMetadata(t, i) || [];
c.push(r);
defineCustomMetadata(t, c, i);
};
};
const s$1 = i$1(ReflectParamIndex.Context);
const r$1 = i$1(ReflectParamIndex.Configuration);
const c$1 = i$1(ReflectParamIndex.Definition);
const e$1 = i$1(ReflectParamIndex.Dispose);
const Use = (e)=>{
return (o, t, s)=>{
decorateUse(e, o, s);
};
};
const decorateUse = (r, n, c)=>{
const U = getOwnCustomMetadata(ReflectParamIndex.Use, n) || [];
U.push(c);
defineCustomMetadata(ReflectParamIndex.Use, U, n);
const i = getOwnCustomMetadata(ReflectParamValue.UseIdentifier, n) || {};
i[c] = r;
defineCustomMetadata(ReflectParamValue.UseIdentifier, i, n);
};
const Global = (o)=>{
return (t, l, r)=>{
decorateGlobal(o, t, r);
};
};
const decorateGlobal = (e, a, n)=>{
const c = getOwnCustomMetadata(ReflectParamIndex.Global, a) || [];
c.push(n);
defineCustomMetadata(ReflectParamIndex.Global, c, a);
const b = getOwnCustomMetadata(ReflectParamValue.GlobalIdentifier, a) || {};
b[n] = e;
defineCustomMetadata(ReflectParamValue.GlobalIdentifier, b, a);
};
const o = (o)=>{
return getOwnCustomMetadata(ReflectParamIndex.Context, o) || [];
};
const r = (o)=>{
return getOwnCustomMetadata(ReflectParamIndex.Configuration, o) || [];
};
const s = (o)=>{
return getOwnCustomMetadata(ReflectParamIndex.Definition, o) || [];
};
const e = (o)=>{
return getOwnCustomMetadata(ReflectParamIndex.Dispose, o) || [];
};
const c = (o)=>{
return getOwnCustomMetadata(ReflectParamIndex.Use, o) || [];
};
const i = (o)=>{
return getOwnCustomMetadata(ReflectParamIndex.Global, o) || [];
};
const getDecoratedParametersIndexes = (t)=>{
const n = o(t) || [];
const u = s(t) || [];
const m = r(t) || [];
const a = e(t) || [];
const f = c(t) || [];
const p = i(t) || [];
return {
Context: n,
Definition: u,
Configuration: m,
Dispose: a,
Use: f,
Global: p
};
};
const createConstructorDecorator = (t)=>{
return (o)=>ConstructorDecorator(t, o);
};
const ConstructorDecorator = (f, p)=>(l)=>{
const m = class extends l {
constructor(...t){
super(...t);
if (f) f.call(this, p);
}
};
Object.defineProperty(m, 'name', {
value: l.name
});
const d = Reflect.getOwnMetadata(ReflectParamTypes, l) || [];
const D = getDecoratedParametersIndexes(l);
const C = [];
for(let e = 0; e < d.length; e++){
if (D.Context.includes(e)) {
const n = getOwnCustomMetadata(ReflectParamIndex.Context, l) || [];
n.push(e);
defineCustomMetadata(ReflectParamIndex.Context, n, m);
continue;
}
if (D.Definition.includes(e)) {
const n = getOwnCustomMetadata(ReflectParamIndex.Definition, l) || [];
n.push(e);
defineCustomMetadata(ReflectParamIndex.Definition, n, m);
continue;
}
if (D.Configuration.includes(e)) {
const n = getOwnCustomMetadata(ReflectParamIndex.Configuration, l) || [];
n.push(e);
defineCustomMetadata(ReflectParamIndex.Configuration, n, m);
continue;
}
if (D.Dispose.includes(e)) {
const n = getOwnCustomMetadata(ReflectParamIndex.Dispose, l) || [];
n.push(e);
defineCustomMetadata(ReflectParamIndex.Dispose, n, m);
C.push(d[e]);
continue;
}
if (D.Use.includes(e)) {
const t = getOwnCustomMetadata(ReflectParamValue.UseIdentifier, l);
decorateUse(t[e], m, e);
continue;
}
if (D.Global.includes(e)) {
const t = getOwnCustomMetadata(ReflectParamValue.GlobalIdentifier, l);
decorateGlobal(t[e], m, e);
continue;
}
}
return decorateAssemblage(m, getOwnCustomMetadata(ReflectValue.AssemblageDefinition, l));
};
const resolveInjectableParameters = (i)=>{
const s = [];
const c = getParamTypes(i.concrete);
const r = getDecoratedParametersIndexes(i.concrete);
let u = 0;
for (const n of c){
if (r.Context.includes(u)) {
s.push(i.publicContext);
u++;
continue;
}
if (r.Configuration.includes(u)) {
s.push(i.configuration);
u++;
continue;
}
if (r.Definition.includes(u)) {
s.push(i.definition);
u++;
continue;
}
if (r.Dispose.includes(u)) {
s.push(i.privateContext.dispose);
u++;
continue;
}
if (r.Use.includes(u)) {
const n = getOwnCustomMetadata(ReflectParamValue.UseIdentifier, i.concrete);
const t = n[u];
s.push(i.privateContext.require(t));
u++;
continue;
}
if (r.Global.includes(u)) {
const n = getOwnCustomMetadata(ReflectParamValue.GlobalIdentifier, i.concrete);
const t = n[u];
s.push(i.privateContext.global(t));
u++;
continue;
}
s.push(i.privateContext.require(n));
u++;
}
return s;
};
const resolveDependencies = (e)=>{
const o = [];
const i = getParamTypes(e);
const s = getDecoratedParametersIndexes(e);
let c = 0;
for (const e of i){
if (s.Context.includes(c) || s.Configuration.includes(c) || s.Definition.includes(c) || s.Dispose.includes(c) || s.Use.includes(c) || s.Global.includes(c)) {
c++;
continue;
}
o.push(e);
c++;
}
return o;
};
class Injectable {
static of(t, e, n) {
return new Injectable(t, e, n);
}
dispose() {
if (this.singletonInstance) {
unregisterEvents(this, this.singletonInstance);
callHook(this.singletonInstance, 'onDispose', this.publicContext, this.configuration);
clearInstance(this.singletonInstance, this.concrete);
}
clearInstance(this, Injectable);
}
build(t) {
if (this.singletonInstance) return this.singletonInstance;
const e = resolveInjectableParameters(this);
const n = new this.concrete(...e);
registerEvents(this, n);
if (this.isSingleton) {
this.singletonInstance = n;
this.privateContext.prepareInitHook(n, this.configuration);
return this.singletonInstance;
}
let i = {};
if (this.configuration) {
i = this.configuration;
}
if (t) {
i = {
...i,
...t
};
}
callHook(n, 'onInit', this.publicContext, i);
return n;
}
get dependencies() {
return this.dependenciesIds;
}
get definition() {
return getDefinition(this.concrete) || {};
}
get isSingleton() {
return getDefinitionValue('singleton', this.concrete);
}
get singleton() {
return this.singletonInstance;
}
get injections() {
return getDefinitionValue('inject', this.concrete) || [];
}
get objects() {
return getDefinitionValue('use', this.concrete) || [];
}
get tags() {
return getDefinitionValue('tags', this.concrete) || [];
}
get globals() {
return getDefinitionValue('global', this.concrete);
}
get events() {
return getDefinitionValue('events', this.concrete) || [];
}
constructor(t, o, r){
this.privateContext = o;
this.publicContext = r;
this.dependenciesIds = [];
this.identifier = t.identifier;
this.concrete = t.concrete;
this.configuration = t.configuration;
if (!isAssemblage(this.concrete)) {
throw new Error(`Class '${this.concrete.name}' is not an Assemblage.`);
}
defineCustomMetadata(ReflectValue.AssemblageContext, this.publicContext, this.concrete);
const c = forOf(this.injections);
const h = forOf(this.objects);
c((t)=>this.privateContext.register(t));
h((t)=>{
if (typeof t[0] === 'string' || typeof t[0] === 'symbol') {
this.privateContext.use(t[0], t[1]);
} else {
this.privateContext.register(t, true);
}
});
this.dependenciesIds = resolveDependencies(this.concrete);
if (this.globals) {
for(const t in this.globals){
this.privateContext.addGlobal(t, this.globals[t]);
}
}
if (t.instance) {
this.singletonInstance = t.instance;
} else if (this.isSingleton) ;
}
}
const callHook = (e, o, n, t)=>{
return new Promise((i)=>{
const s = e[o];
if (s) {
if (isAsync(s)) {
s.bind(e)(n, t).then(()=>{
i();
});
return;
}
i(s.bind(e)(n, t));
}
});
};
class Assembler extends EventManager {
static build(e) {
const i = new Assembler();
setDefinitionValue('singleton', true, e);
const s = i.register([
e
]);
const n = i.require(s.identifier);
const r = i.initCache.find((e)=>e.instance === n);
if (!r) {
throw new Error('Root instance not found in assemblages cache.');
}
const h = i.initCache.indexOf(r);
i.initCache.splice(h, 1);
for (const e of i.initCache){
callHook(e.instance, 'onInit', i.publicContext, e.configuration);
}
callHook(n, 'onInit', i.publicContext, s.configuration);
for (const e of i.initCache.reverse()){
callHook(e.instance, 'onInited', i.publicContext, e.configuration);
}
callHook(n, 'onInited', i.publicContext, s.configuration);
i.initCache.length = 0;
return n;
}
dispose() {
for (const [e, t] of this.injectables){
t.dispose();
}
clearInstance(this, Assembler);
}
register(e, t = false) {
const r = t === true ? resolveInstanceInjectionTuple(e) : resolveInjectionTuple(e);
if (this.has(r.identifier)) {
throw new Error(`An assemblage is already registered with identifier '${r.identifier.name}'.`);
}
const h = Injectable.of(r, this.privateContext, this.publicContext);
this.injectables.set(h.identifier, h);
callHook(h.concrete, 'onRegister', this.publicContext, h.configuration);
return h;
}
use(e, t) {
if (this.has(e)) {
throw new Error(`A value is already registered with identifier '${String(e)}'.`);
}
this.objects.set(e, t);
return t;
}
prepareInitHook(e, t) {
this.initCache.push({
instance: e,
configuration: t
});
return this.initCache;
}
has(e) {
if (typeof e === 'string' || typeof e === 'symbol') {
return this.objects.has(e);
}
return this.injectables.has(e);
}
require(e, t) {
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.`);
}
const i = this.injectables.get(e);
const s = i.build(t);
return s;
}
}
}
concrete(e) {
const t = this.injectables.get(e);
if (t) return t.concrete;
return;
}
tagged(...e) {
const t = [];
for (const i of e){
for (const [e, s] of this.injectables){
if (s.tags.includes(i)) t.push(s.build());
}
}
return t;
}
addGlobal(e, t) {
if (this.globals.has(e)) {
throw new Error(`Global value with key '${e}' has already been registered.`);
}
this.globals.set(e, t);
}
global(e) {
return this.globals.get(e);
}
get size() {
return this.injectables.size;
}
constructor(){
super();
this.injectables = new Map();
this.objects = new Map();
this.globals = new Map();
this.initCache = [];
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),
global: this.global.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),
addGlobal: this.addGlobal.bind(this),
prepareInitHook: this.prepareInitHook.bind(this),
emit: this.emit.bind(this),
addChannels: this.addChannels.bind(this),
removeChannels: this.removeChannels.bind(this)
};
}
}
class AbstractAssembler extends AbstractEventManager {
}
export { AbstractAssemblage, AbstractAssembler, AbstractEventManager, AbstractListenerCollection, Assemblage, Assembler, Await, r$1 as Configuration, ConstructorDecorator, s$1 as Context, c$1 as Definition, e$1 as Dispose, EventManager, Global, ListenerCollection, ReflectParamIndex, ReflectParamValue, Use, createConstructorDecorator, decorateAssemblage, decorateGlobal, decorateUse, getAssemblageContext, getAssemblageDefinition, getDecoratedParametersIndexes, isAssemblage };