UNPKG

conteneur

Version:

TypeScript Inversion of Control container for Dependency Injection.

64 lines (62 loc) 2.08 kB
// src/container/container.ts var createContainer = (options) => createRegistry(options); var createRegistry = (options) => { const defaultStrategy = options?.defaultStrategy ?? "transient"; const parentRegistry = options?.parentRegistry; const registrationMap = /* @__PURE__ */ new Map(); const resolutionCache = /* @__PURE__ */ new Map(); const resolutionStack = []; const cradle = new Proxy({}, { get: (_target, key) => resolve(key), set: (_target, key) => { throw new Error(`Direct assignment for ${key} is not allowed`); } }); const register = (entries) => { for (const [key, [target, options2]] of Object.entries(entries)) { registrationMap.set(key, { target, strategy: options2?.strategy ?? defaultStrategy }); } }; const resolve = (key) => { if (resolutionStack.includes(key)) { throw new Error(`Cyclic dependency detected: ${resolutionStack.join(" -> ")} -> ${String(key)}`); } resolutionStack.push(key); const resolver = registrationMap.get(key) ?? parentRegistry?.registrationMap.get(key); if (!resolver) { resolutionStack.pop(); throw new Error(`Resolver for ${String(key)} not found`); } let resolved; if (resolver.strategy === "singleton") { let cached = resolutionCache.get(key); if (cached === void 0) { cached = inject(resolver.target); resolutionCache.set(key, cached); } resolved = cached; } else { resolved = inject(resolver.target); } resolutionStack.pop(); return resolved; }; const inject = (target) => { if (typeof target !== "function") { throw new Error("Injection target must be a function or a class"); } if (!!target.prototype && typeof target.prototype === "object") { return new target(cradle); } return target(cradle); }; const createScope = () => createRegistry({ defaultStrategy, parentRegistry: { registrationMap } }); return { register, resolve, inject, createScope }; }; export { createContainer };