UNPKG

di-tory

Version:

Compose applications with dependency injection

141 lines (140 loc) 5.73 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Module = exports.scope = void 0; const Stack_js_1 = require("../stack/Stack.js"); const DependencyResolutionError_js_1 = require("../DependencyResolutionError.js"); exports.scope = { module: 'module', singleton: 'singleton', }; const createModule = (singletons, privateResolvers, publicResolvers, initializers, params) => { const resolvers = Object.assign(Object.assign({}, privateResolvers), publicResolvers); const resolutionStack = new Stack_js_1.Stack(); const moduleInstances = new Map(); const self = {}; const module = {}; for (const name of Object.keys(privateResolvers)) { Object.defineProperty(self, name, { get: () => resolve(name), }); Object.defineProperty(module, name, { get: () => { throw new DependencyResolutionError_js_1.DependencyResolutionError(DependencyResolutionError_js_1.DependencyResolutionErrorCode.PrivateMemberAccessFailure, resolutionStack.toStringArray(), String(name)); }, }); } for (const name of Object.keys(publicResolvers)) { Object.defineProperty(self, name, { get: () => resolve(name), }); Object.defineProperty(module, name, { get: () => resolve(name), }); } const resolve = (name) => { var _a; const resolver = resolvers[name]; const instances = resolver.scope === 'singleton' ? singletons : moduleInstances; if (instances.has(name)) return instances.get(name); const currentStack = resolutionStack.toStringArray(); try { resolutionStack.push(name); } catch (_b) { throw new DependencyResolutionError_js_1.DependencyResolutionError(DependencyResolutionError_js_1.DependencyResolutionErrorCode.CircularDependencyFailure, resolutionStack.toStringArray(), String(name)); } let instance; try { instance = resolver(self, params); } catch (err) { if (err instanceof DependencyResolutionError_js_1.DependencyResolutionError) throw err; throw new DependencyResolutionError_js_1.DependencyResolutionError(DependencyResolutionError_js_1.DependencyResolutionErrorCode.InstantiationFailure, currentStack, String(name), err); } resolutionStack.pop(); instances.set(name, instance); if (resolutionStack.length === 0) { (_a = initializers[name]) === null || _a === void 0 ? void 0 : _a.call(instance, self, params); } return instance; }; return module; }; const Module = () => { const privateResolvers = {}; const publicResolvers = {}; let initializers = null; let sealed = false; const singletons = new Map(); const self = { private(resolvers, scope) { var _a; if (sealed) { throw new Error('Cannot extend initialized module'); } for (const name of Object.keys(resolvers)) { const resolver = resolvers[name]; if (typeof resolver !== 'function') { throw new Error(`Expected ${String(name)} to be a function, but got ${typeof resolver}`); } (_a = resolver.scope) !== null && _a !== void 0 ? _a : (resolver.scope = scope); privateResolvers[name] = resolver; } return self; }, privateImpl(implementation) { if (sealed) { throw new Error('Cannot extend initialized module'); } for (const name of Object.keys(implementation)) { const method = implementation[name]; const resolver = (moduleInstance) => (...args) => method(moduleInstance, ...args); resolver.scope = 'module'; privateResolvers[name] = resolver; } return self; }, public(resolvers, scope) { var _a; if (sealed) { throw new Error('Cannot extend initialized module'); } for (const name of Object.keys(resolvers)) { const resolver = resolvers[name]; if (typeof resolver !== 'function') { throw new Error(`Expected ${String(name)} to be a function, but got ${typeof resolver}`); } (_a = resolver.scope) !== null && _a !== void 0 ? _a : (resolver.scope = scope); publicResolvers[name] = resolver; } return self; }, publicImpl(implementation) { if (sealed) { throw new Error('Cannot extend initialized module'); } for (const name of Object.keys(implementation)) { const method = implementation[name]; const resolver = (moduleInstance) => (...args) => method(moduleInstance, ...args); resolver.scope = 'module'; publicResolvers[name] = resolver; } return self; }, init(initializer) { initializers = initializer; sealed = true; return self; }, create(params = {}) { sealed = true; return createModule(singletons, privateResolvers, publicResolvers, initializers !== null && initializers !== void 0 ? initializers : {}, params); }, }; // eslint-disable-next-line @typescript-eslint/no-explicit-any return self; }; exports.Module = Module; exports.default = exports.Module;