UNPKG

@dazejs/framework

Version:

Daze.js - A powerful web framework for Node.js

261 lines 11.1 kB
"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