@dazejs/framework
Version:
Daze.js - A powerful web framework for Node.js
261 lines • 11.1 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Container = void 0;
const events_1 = require("events");
const symbols = __importStar(require("../symbol"));
const BIND = Symbol('Container#bind');
class Container extends events_1.EventEmitter {
constructor() {
super(...arguments);
this.binds = new Map();
this.instances = new Map();
this.tags = {};
this.paths = new Map();
}
singleton(abstract, concrete = null, callable = false) {
this[BIND](abstract, concrete, true, callable);
return this;
}
multiton(abstract, concrete = null, callable = false) {
this[BIND](abstract, concrete, false, callable);
}
isShared(abstract) {
return this.instances.has(abstract) || (this.binds.get(abstract)
&& Reflect.has(this.binds.get(abstract), 'shared')
&& this.binds.get(abstract).shared === true);
}
bound(abstract) {
return this.binds.has(abstract) || this.instances.has(abstract);
}
exists(abstract) {
return this.instances.has(abstract);
}
[BIND](abstract, concrete, shared = false, callable = false) {
if (!abstract || !concrete)
return;
let isShared = shared;
if (concrete && Reflect.getMetadata(symbols.MULTITON, concrete) === true) {
isShared = false;
}
else if (concrete && Reflect.getMetadata(symbols.SINGLETON, concrete) === true) {
isShared = true;
}
if (typeof concrete === 'function') {
this.binds.set(abstract, {
concrete,
shared: isShared,
callable,
});
}
else {
this.instances.set(abstract, {
concrete,
shared: true,
callable: false,
});
}
this.emit('binding', this.instances.get(abstract), this);
return this;
}
make(abstract, args = [], force = false) {
const shared = this.isShared(abstract);
let obj;
if (this.instances.has(abstract) && shared && !force) {
return this.instances.get(abstract).concrete;
}
if (this.binds.has(abstract)) {
const { concrete, callable } = this.binds.get(abstract);
if (callable) {
obj = this.invokeFunction(abstract, args);
}
else if (Reflect.getMetadata(symbols.INJECTABLE, concrete) === true) {
obj = this.invokeInjectAbleClass(abstract, args);
}
else {
obj = this.invokeConstructor(abstract, args);
}
this.emit('resolving', obj, this);
}
if (shared && obj !== undefined && !force) {
this.instances.set(abstract, {
concrete: obj,
shared,
});
}
return obj;
}
invokeFunction(abstract, args) {
const { concrete } = this.binds.get(abstract);
return concrete(...args, this);
}
invokeConstructor(abstract, args) {
const { concrete: Concrete } = this.binds.get(abstract);
return new Concrete(...args, this);
}
invokeInjectAbleClass(abstract, args) {
const { concrete: Concrete } = this.binds.get(abstract);
const that = this;
const ConcreteProxy = new Proxy(Concrete, {
construct(target, targetArgArray = [], newTarget) {
const params = that.bindConstructorParams(Concrete, args, targetArgArray);
const instance = Reflect.construct(target, [...params], newTarget);
instance.__context__ = args;
return new Proxy(instance, {
get(instanceTarget, propertyKey, receiver) {
if (propertyKey === 'constructor')
return Reflect.get(instanceTarget, propertyKey, receiver);
if (typeof instanceTarget[propertyKey] === 'function') {
return new Proxy(instanceTarget[propertyKey], {
apply(methodTarget, thisArg, argArray) {
const methodParams = that.bindMethodParams(Concrete, propertyKey.toString(), args, argArray);
return Reflect.apply(methodTarget, thisArg, [...methodParams]);
}
});
}
const propertyParam = that.bindProperty(Concrete, args, propertyKey.toString());
return propertyParam !== null && propertyParam !== void 0 ? propertyParam : Reflect.get(instanceTarget, propertyKey, receiver);
}
});
}
});
return Reflect.construct(ConcreteProxy, [...args, this]);
}
isBuildInType(type) {
return type === Number ||
type === String ||
type === Object ||
type === Boolean ||
type === Array ||
type === Function;
}
bindConstructorParams(Concrete, args = [], vars = []) {
var _a, _b;
const disableInject = Reflect.getMetadata(symbols.DISABLE_INJECT, Concrete);
if (disableInject)
return vars;
const injectParams = (_a = Reflect.getMetadata(symbols.INJECTTYPE_METADATA, Concrete)) !== null && _a !== void 0 ? _a : [];
const typeParams = (_b = Reflect.getMetadata(symbols.PARAMTYPES_METADATA, Concrete)) !== null && _b !== void 0 ? _b : [];
const argsLength = Math.max(Concrete.length, injectParams.length, typeParams.length, vars.length);
return this.bindParams(argsLength, injectParams, typeParams, args, vars);
}
bindMethodParams(Concrete, key, args = [], vars = []) {
var _a, _b;
const disableInject = Reflect.getMetadata(symbols.DISABLE_INJECT, Concrete, key);
if (disableInject)
return vars;
const injectParams = (_a = Reflect.getMetadata(symbols.INJECTTYPE_METADATA, Concrete, key)) !== null && _a !== void 0 ? _a : [];
const typeParams = (_b = Reflect.getMetadata(symbols.PARAMTYPES_METADATA, Concrete.prototype, key)) !== null && _b !== void 0 ? _b : [];
const argsLength = Math.max(Concrete.prototype[key].length, injectParams.length, typeParams.length, vars.length);
return this.bindParams(argsLength, injectParams, typeParams, args, vars);
}
bindProperty(Concrete, args = [], key) {
var _a;
const injects = (_a = Reflect.getMetadata(symbols.INJECTTYPE_METADATA, Concrete, key)) !== null && _a !== void 0 ? _a : [];
const typeParam = Reflect.getMetadata(symbols.PROPERTYTYPE_METADATA, Concrete, key);
if (injects[0]) {
const { abstract, params, handler } = injects[0];
const injectedParam = this.make(abstract, [...params !== null && params !== void 0 ? params : [], ...args]);
if (typeof handler === 'function') {
return handler(injectedParam);
}
return injectedParam;
}
return this.make(typeParam, [...args]);
}
bindParams(argsLength, injectParams, typeParams, args, vars) {
const params = [];
const unPositionInjectParams = [];
const positionInjectParams = [];
for (const item of injectParams) {
if (item.index !== undefined) {
positionInjectParams.push(item);
}
else {
unPositionInjectParams.push(item);
}
}
for (let index = 0; index < argsLength; index++) {
const injectParam = positionInjectParams.find(item => item.index === index);
const typeParam = typeParams[index];
if (injectParam) {
const { abstract, params: _params, handler } = injectParam;
const injected = this.make(abstract, [...(_params !== null && _params !== void 0 ? _params : []), ...args]);
params.push(typeof handler === 'function' ? handler(injected) : injected);
}
else if (typeParam && !this.isBuildInType(typeParam)) {
const injected = this.make(typeParams[index], [...args]);
params.push(injected);
}
else if (unPositionInjectParams.length > 0) {
const { abstract, params: _params, handler } = unPositionInjectParams.pop();
const injected = this.make(abstract, [...(_params !== null && _params !== void 0 ? _params : []), ...args]);
params.push(typeof handler === 'function' ? handler(injected) : injected);
}
else if (vars.length > 0) {
params.push(vars.shift());
}
}
params.push(...vars);
return params;
}
bindPath(abstract, path) {
if (!abstract || !path)
return;
this.paths.set(abstract, path);
}
getPath(abstract) {
if (!abstract)
return;
return this.paths.get(abstract);
}
static tag(abstract, tag) {
if (!abstract || !tag)
return;
if (!this.getInstance().tags[tag])
this.getInstance().tags[tag] = [];
this.getInstance().tags[tag].push(abstract);
}
static get(abstract, args = []) {
return this.getInstance().make(abstract, args);
}
static bind(abstract, concrete = null, shared = true, callable = false) {
return this.getInstance()[BIND](abstract, concrete, shared, callable);
}
static has(abstract) {
return this.getInstance().binds.has(abstract) || this.getInstance().instances.has(abstract);
}
static getInstance() {
if (!this.instance) {
this.instance = new Container();
}
return this.instance;
}
static setInstance(instance) {
this.instance = instance;
}
}
exports.Container = Container;
//# sourceMappingURL=index.js.map