@autometa/injection
Advanced tools
| > @autometa/injection@0.1.5 build /Users/ben.aherne/Documents/GitHub/autometa/packages/injection | ||
| > tsup && pnpm run build:types | ||
| [34mCLI[39m Building entry: src/index.ts | ||
| [34mCLI[39m Using tsconfig: tsconfig.bundle.json | ||
| [34mCLI[39m tsup v7.2.0 | ||
| [34mCLI[39m Using tsup config: /Users/ben.aherne/Documents/GitHub/autometa/packages/injection/tsup.config.ts | ||
| [34mCLI[39m Target: es2020 | ||
| [34mCLI[39m Cleaning output folder | ||
| [34mCJS[39m Build start | ||
| [34mESM[39m Build start | ||
| [32mCJS[39m [1mdist/index.cjs [22m[32m13.94 KB[39m | ||
| [32mCJS[39m [1mdist/index.cjs.map [22m[32m32.43 KB[39m | ||
| [32mCJS[39m ⚡️ Build success in 386ms | ||
| [32mESM[39m [1mdist/index.js [22m[32m13.66 KB[39m | ||
| [32mESM[39m [1mdist/index.js.map [22m[32m32.43 KB[39m | ||
| [32mESM[39m ⚡️ Build success in 385ms | ||
| > @autometa/injection@0.1.5 build:types /Users/ben.aherne/Documents/GitHub/autometa/packages/injection | ||
| > rimraf tsconfig.types.tsbuildinfo && tsc --build tsconfig.types.json | ||
| > @autometa/injection@0.1.5 build:types /Users/ben.aherne/Documents/GitHub/autometa/packages/injection | ||
| > tsc -p tsconfig.types.json | ||
| > @autometa/injection@0.1.5 lint /Users/ben.aherne/Documents/GitHub/autometa/packages/injection | ||
| > eslint . --max-warnings 0 | ||
| /** | ||
| * Core container implementation for dependency injection | ||
| */ | ||
| import { IContainer, Identifier, Constructor, Token, Binding, RegistrationOptions } from "./types"; | ||
| export declare class Container implements IContainer { | ||
| private readonly bindings; | ||
| private readonly instances; | ||
| private readonly scopedInstances; | ||
| private readonly children; | ||
| readonly parent?: IContainer; | ||
| constructor(parent?: IContainer); | ||
| register<T>(identifier: Identifier<T>, binding: Partial<Binding<T>>): IContainer; | ||
| registerClass<T>(target: Constructor<T>, options?: RegistrationOptions): IContainer; | ||
| registerValue<T>(identifier: Identifier<T>, value: T, options?: RegistrationOptions): IContainer; | ||
| registerFactory<T>(identifier: Identifier<T>, factory: (container: IContainer) => T, options?: RegistrationOptions): IContainer; | ||
| registerToken<T>(token: Token<T>, target: Constructor<T> | ((container: IContainer) => T), options?: RegistrationOptions): IContainer; | ||
| resolve<T>(identifier: Identifier<T>): T; | ||
| resolveAll<T>(identifier: Identifier<T>): T[]; | ||
| tryResolve<T>(identifier: Identifier<T>): T | undefined; | ||
| isRegistered<T>(identifier: Identifier<T>): boolean; | ||
| getBinding<T>(identifier: Identifier<T>): Binding<T> | undefined; | ||
| createChild(): IContainer; | ||
| resolveByTag<T>(tag: string): T[]; | ||
| dispose(): Promise<void>; | ||
| private resolveWithContext; | ||
| private getBindingInternal; | ||
| private createInstance; | ||
| private instantiateClass; | ||
| private isConstructor; | ||
| private createContextAwareContainer; | ||
| private getScopedCache; | ||
| private identifierMatches; | ||
| private bindingHasMatchingTag; | ||
| private normalizePropertyOptions; | ||
| private isPropertyInjectionObject; | ||
| } | ||
| export declare function createContainer(): IContainer; | ||
| export declare function createChildContainer(parent: IContainer): IContainer; |
| import "reflect-metadata"; | ||
| import { Scope } from "./types"; | ||
| import type { Identifier, IContainer } from "./types"; | ||
| export interface InjectableOptions { | ||
| scope?: Scope; | ||
| deps?: Identifier[]; | ||
| } | ||
| /** | ||
| * Creates a set of decorators bound to a specific container instance. | ||
| * This factory pattern ensures the decorators are decoupled from a global | ||
| * container and can be used with multiple, separate containers. | ||
| * @param container The container instance to which the decorators will register classes. | ||
| */ | ||
| export declare function createDecorators(container: IContainer): { | ||
| Injectable: (options?: InjectableOptions) => ClassDecorator; | ||
| Inject: (token: Identifier) => PropertyDecorator & ParameterDecorator; | ||
| LazyInject: (token: Identifier) => PropertyDecorator; | ||
| }; |
+457
| 'use strict'; | ||
| require('reflect-metadata'); | ||
| // src/types.ts | ||
| var Scope = /* @__PURE__ */ ((Scope2) => { | ||
| Scope2["SINGLETON"] = "singleton"; | ||
| Scope2["TRANSIENT"] = "transient"; | ||
| Scope2["REQUEST"] = "request"; | ||
| Scope2["SESSION"] = "session"; | ||
| Scope2["SCENARIO"] = "scenario"; | ||
| return Scope2; | ||
| })(Scope || {}); | ||
| var DependencyInjectionError = class extends Error { | ||
| constructor(message, identifier, context) { | ||
| super(message); | ||
| this.identifier = identifier; | ||
| this.context = context; | ||
| this.name = "DependencyInjectionError"; | ||
| } | ||
| }; | ||
| var CircularDependencyError = class extends DependencyInjectionError { | ||
| constructor(identifier, context) { | ||
| const identifierName = getIdentifierName(identifier); | ||
| const pathNames = [...context.path].map(getIdentifierName); | ||
| const path = pathNames.join(" -> "); | ||
| super( | ||
| `Circular dependency detected: ${path} -> ${identifierName}`, | ||
| identifier, | ||
| context | ||
| ); | ||
| this.name = "CircularDependencyError"; | ||
| } | ||
| }; | ||
| var UnregisteredDependencyError = class extends DependencyInjectionError { | ||
| constructor(identifier) { | ||
| const name = getIdentifierName(identifier); | ||
| super(`No registration found for identifier: ${name}`, identifier); | ||
| this.name = "UnregisteredDependencyError"; | ||
| } | ||
| }; | ||
| function getIdentifierName(identifier) { | ||
| if (typeof identifier === "string") { | ||
| return identifier; | ||
| } | ||
| if (typeof identifier === "symbol") { | ||
| return identifier.toString(); | ||
| } | ||
| return identifier.name || "anonymous"; | ||
| } | ||
| function createToken(description) { | ||
| return Symbol(description); | ||
| } | ||
| // src/container.ts | ||
| var Container = class _Container { | ||
| constructor(parent) { | ||
| this.bindings = /* @__PURE__ */ new Map(); | ||
| this.instances = /* @__PURE__ */ new Map(); | ||
| this.scopedInstances = /* @__PURE__ */ new Map(); | ||
| this.children = /* @__PURE__ */ new Set(); | ||
| if (parent !== void 0) { | ||
| this.parent = parent; | ||
| } | ||
| } | ||
| // Registration methods | ||
| register(identifier, binding) { | ||
| const fullBinding = { | ||
| scope: "transient" /* TRANSIENT */, | ||
| tags: [], | ||
| ...binding | ||
| }; | ||
| this.bindings.set(identifier, fullBinding); | ||
| return this; | ||
| } | ||
| registerClass(target, options = {}) { | ||
| const propertyDeps = this.normalizePropertyOptions(options.props); | ||
| const binding = { | ||
| type: "class", | ||
| target, | ||
| scope: options.scope || "transient" /* TRANSIENT */, | ||
| tags: options.tags || [], | ||
| deps: options.deps || [], | ||
| ...propertyDeps.length > 0 ? { props: propertyDeps } : {} | ||
| }; | ||
| this.bindings.set(target, binding); | ||
| return this; | ||
| } | ||
| registerValue(identifier, value, options = {}) { | ||
| const binding = { | ||
| type: "value", | ||
| value, | ||
| scope: options.scope || "singleton" /* SINGLETON */, | ||
| tags: options.tags || [] | ||
| }; | ||
| this.bindings.set(identifier, binding); | ||
| return this; | ||
| } | ||
| registerFactory(identifier, factory, options = {}) { | ||
| const binding = { | ||
| type: "factory", | ||
| factory, | ||
| scope: options.scope || "transient" /* TRANSIENT */, | ||
| tags: options.tags || [] | ||
| }; | ||
| this.bindings.set(identifier, binding); | ||
| return this; | ||
| } | ||
| registerToken(token, target, options = {}) { | ||
| const binding = { | ||
| type: "token", | ||
| token, | ||
| target, | ||
| scope: options.scope || "transient" /* TRANSIENT */, | ||
| tags: options.tags || [] | ||
| }; | ||
| this.bindings.set(token, binding); | ||
| return this; | ||
| } | ||
| // Resolution methods | ||
| resolve(identifier) { | ||
| const context = { | ||
| path: /* @__PURE__ */ new Set(), | ||
| depth: 0, | ||
| maxDepth: 50 | ||
| }; | ||
| return this.resolveWithContext(identifier, context); | ||
| } | ||
| resolveAll(identifier) { | ||
| const results = []; | ||
| for (const [key, binding] of this.bindings.entries()) { | ||
| if (this.identifierMatches(key, identifier) || this.bindingHasMatchingTag(binding, identifier)) { | ||
| try { | ||
| const instance = this.resolve(key); | ||
| results.push(instance); | ||
| } catch { | ||
| } | ||
| } | ||
| } | ||
| if (this.parent) { | ||
| results.push(...this.parent.resolveAll(identifier)); | ||
| } | ||
| return results; | ||
| } | ||
| tryResolve(identifier) { | ||
| try { | ||
| return this.resolve(identifier); | ||
| } catch { | ||
| return void 0; | ||
| } | ||
| } | ||
| // Introspection | ||
| isRegistered(identifier) { | ||
| return this.bindings.has(identifier) || (this.parent?.isRegistered(identifier) ?? false); | ||
| } | ||
| getBinding(identifier) { | ||
| const binding = this.bindings.get(identifier); | ||
| return binding || this.parent?.getBinding(identifier); | ||
| } | ||
| // Container hierarchy | ||
| createChild() { | ||
| const child = new _Container(this); | ||
| this.children.add(child); | ||
| return child; | ||
| } | ||
| // Tagged resolution | ||
| resolveByTag(tag) { | ||
| const results = []; | ||
| for (const [identifier, binding] of this.bindings.entries()) { | ||
| if (binding.tags.includes(tag)) { | ||
| try { | ||
| const instance = this.resolve(identifier); | ||
| results.push(instance); | ||
| } catch { | ||
| } | ||
| } | ||
| } | ||
| if (this.parent) { | ||
| results.push(...this.parent.resolveByTag(tag)); | ||
| } | ||
| return results; | ||
| } | ||
| // Lifecycle | ||
| async dispose() { | ||
| await Promise.all([...this.children].map((child) => child.dispose())); | ||
| this.children.clear(); | ||
| for (const instance of this.instances.values()) { | ||
| if (instance && typeof instance === "object" && "dispose" in instance) { | ||
| const disposable = instance; | ||
| await disposable.dispose(); | ||
| } | ||
| } | ||
| this.instances.clear(); | ||
| this.scopedInstances.clear(); | ||
| this.bindings.clear(); | ||
| } | ||
| // Private resolution implementation | ||
| resolveWithContext(identifier, context) { | ||
| if (context.path.has(identifier)) { | ||
| throw new CircularDependencyError(identifier, context); | ||
| } | ||
| if (context.depth >= context.maxDepth) { | ||
| throw new Error( | ||
| `Maximum resolution depth exceeded (${context.maxDepth})` | ||
| ); | ||
| } | ||
| const binding = this.getBindingInternal(identifier); | ||
| if (!binding) { | ||
| throw new UnregisteredDependencyError(identifier); | ||
| } | ||
| if (binding.scope === "singleton" /* SINGLETON */ && this.instances.has(identifier)) { | ||
| return this.instances.get(identifier); | ||
| } | ||
| const scopedCache = this.getScopedCache(binding.scope); | ||
| if (scopedCache?.has(identifier)) { | ||
| return scopedCache.get(identifier); | ||
| } | ||
| context.path.add(identifier); | ||
| context.depth++; | ||
| try { | ||
| const instance = this.createInstance(binding, context); | ||
| if (binding.scope === "singleton" /* SINGLETON */) { | ||
| this.instances.set(identifier, instance); | ||
| } else if (scopedCache) { | ||
| scopedCache.set(identifier, instance); | ||
| } | ||
| return instance; | ||
| } finally { | ||
| context.path.delete(identifier); | ||
| context.depth--; | ||
| } | ||
| } | ||
| getBindingInternal(identifier) { | ||
| const binding = this.bindings.get(identifier); | ||
| return binding || this.parent?.getBindingInternal?.(identifier); | ||
| } | ||
| createInstance(binding, context) { | ||
| switch (binding.type) { | ||
| case "value": | ||
| return binding.value; | ||
| case "factory": { | ||
| const contextAwareContainer = this.createContextAwareContainer(context); | ||
| return binding.factory(contextAwareContainer); | ||
| } | ||
| case "class": | ||
| return this.instantiateClass( | ||
| binding.target, | ||
| context | ||
| ); | ||
| case "token": { | ||
| if (typeof binding.target === "function") { | ||
| if (this.isConstructor(binding.target)) { | ||
| return this.instantiateClass( | ||
| binding.target, | ||
| context | ||
| ); | ||
| } else { | ||
| const contextAwareContainer = this.createContextAwareContainer(context); | ||
| return binding.target( | ||
| contextAwareContainer | ||
| ); | ||
| } | ||
| } | ||
| throw new Error( | ||
| `Invalid token binding target for ${binding.token.toString()}` | ||
| ); | ||
| } | ||
| default: | ||
| throw new Error(`Unknown binding type: ${binding.type}`); | ||
| } | ||
| } | ||
| instantiateClass(constructor, context) { | ||
| const binding = this.getBindingInternal(constructor); | ||
| if (!binding || binding.type !== "class") { | ||
| throw new Error( | ||
| `No class binding found for constructor: ${constructor.name}` | ||
| ); | ||
| } | ||
| const constructorArgs = (binding.deps || []).map((dep) => { | ||
| return this.resolveWithContext(dep, context); | ||
| }); | ||
| const instance = new constructor(...constructorArgs); | ||
| if (binding.props) { | ||
| for (const prop of binding.props) { | ||
| if (prop.lazy) { | ||
| Object.defineProperty(instance, prop.property, { | ||
| configurable: true, | ||
| enumerable: true, | ||
| get: () => { | ||
| const resolved = this.resolveWithContext(prop.token, context); | ||
| Object.defineProperty(instance, prop.property, { | ||
| configurable: true, | ||
| enumerable: true, | ||
| writable: true, | ||
| value: resolved | ||
| }); | ||
| return resolved; | ||
| } | ||
| }); | ||
| continue; | ||
| } | ||
| instance[prop.property] = this.resolveWithContext( | ||
| prop.token, | ||
| context | ||
| ); | ||
| } | ||
| } | ||
| return instance; | ||
| } | ||
| isConstructor(fn) { | ||
| return typeof fn === "function" && fn.prototype !== void 0; | ||
| } | ||
| createContextAwareContainer(context) { | ||
| return { | ||
| register: (identifier, binding) => this.register(identifier, binding), | ||
| registerClass: (target, options) => this.registerClass(target, options), | ||
| registerValue: (identifier, value, options) => this.registerValue(identifier, value, options), | ||
| registerFactory: (identifier, factory, options) => this.registerFactory(identifier, factory, options), | ||
| registerToken: (token, target, options) => this.registerToken(token, target, options), | ||
| resolve: (identifier) => { | ||
| return this.resolveWithContext(identifier, context); | ||
| }, | ||
| resolveAll: (identifier) => this.resolveAll(identifier), | ||
| tryResolve: (identifier) => this.tryResolve(identifier), | ||
| isRegistered: (identifier) => this.isRegistered(identifier), | ||
| getBinding: (identifier) => this.getBinding(identifier), | ||
| createChild: () => this.createChild(), | ||
| resolveByTag: (tag) => this.resolveByTag(tag), | ||
| dispose: () => this.dispose() | ||
| }; | ||
| } | ||
| getScopedCache(scope) { | ||
| if (scope === "singleton" /* SINGLETON */ || scope === "transient" /* TRANSIENT */) { | ||
| return void 0; | ||
| } | ||
| if (!this.scopedInstances.has(scope)) { | ||
| this.scopedInstances.set(scope, /* @__PURE__ */ new Map()); | ||
| } | ||
| return this.scopedInstances.get(scope); | ||
| } | ||
| identifierMatches(a, b) { | ||
| return a === b; | ||
| } | ||
| bindingHasMatchingTag(binding, identifier) { | ||
| if (typeof identifier !== "string") { | ||
| return false; | ||
| } | ||
| return binding.tags.includes(identifier); | ||
| } | ||
| normalizePropertyOptions(props) { | ||
| if (!props) { | ||
| return []; | ||
| } | ||
| if (Array.isArray(props)) { | ||
| return props.map((prop) => ({ ...prop })); | ||
| } | ||
| const map = props; | ||
| const normalized = []; | ||
| const descriptorMap = map; | ||
| for (const key of Reflect.ownKeys(descriptorMap)) { | ||
| const descriptor = descriptorMap[key]; | ||
| if (!descriptor) { | ||
| continue; | ||
| } | ||
| if (!this.isPropertyInjectionObject(descriptor)) { | ||
| normalized.push({ | ||
| property: key, | ||
| token: descriptor | ||
| }); | ||
| continue; | ||
| } | ||
| normalized.push({ | ||
| property: key, | ||
| token: descriptor.token, | ||
| ...descriptor.lazy ? { lazy: descriptor.lazy } : {} | ||
| }); | ||
| } | ||
| return normalized; | ||
| } | ||
| isPropertyInjectionObject(descriptor) { | ||
| return typeof descriptor === "object" && descriptor !== null && "token" in descriptor; | ||
| } | ||
| }; | ||
| function createContainer() { | ||
| return new Container(); | ||
| } | ||
| function createChildContainer(parent) { | ||
| return parent.createChild(); | ||
| } | ||
| var INJECT_PARAM_KEY = "autometa:inject_param"; | ||
| var INJECT_PROP_KEY = "autometa:inject_prop"; | ||
| function ensureInjectableTarget(value, decorator) { | ||
| if (typeof value !== "function") { | ||
| throw new TypeError( | ||
| `[${decorator}] can only be used on classes. Received ${typeof value}.` | ||
| ); | ||
| } | ||
| } | ||
| function createDecorators(container) { | ||
| function registerPropertyDependency(target, propertyKey, token, lazy) { | ||
| const existing = Reflect.getMetadata(INJECT_PROP_KEY, target) || []; | ||
| const filtered = existing.filter((dep) => dep.property !== propertyKey); | ||
| filtered.push({ property: propertyKey, token, lazy }); | ||
| Reflect.defineMetadata(INJECT_PROP_KEY, filtered, target); | ||
| } | ||
| function Injectable(options = {}) { | ||
| return (target) => { | ||
| ensureInjectableTarget(target, "Injectable"); | ||
| const ctor = target; | ||
| const deps = options.deps || []; | ||
| const props = Reflect.getMetadata(INJECT_PROP_KEY, ctor.prototype) || []; | ||
| const identifier = ctor; | ||
| const binding = { | ||
| type: "class", | ||
| target: ctor, | ||
| scope: options.scope || "transient" /* TRANSIENT */, | ||
| tags: [], | ||
| deps, | ||
| props | ||
| }; | ||
| container.register(identifier, binding); | ||
| }; | ||
| } | ||
| function Inject(token) { | ||
| return (...args) => { | ||
| const [target, propertyKey, parameterIndex] = args; | ||
| if (typeof parameterIndex === "number") { | ||
| ensureInjectableTarget(target, "Inject parameter"); | ||
| const ctor = target; | ||
| const paramTokens = Reflect.getMetadata(INJECT_PARAM_KEY, ctor) || /* @__PURE__ */ new Map(); | ||
| paramTokens.set(parameterIndex, token); | ||
| Reflect.defineMetadata(INJECT_PARAM_KEY, paramTokens, ctor); | ||
| return; | ||
| } | ||
| registerPropertyDependency(target, propertyKey, token, false); | ||
| }; | ||
| } | ||
| function LazyInject(token) { | ||
| return (target, propertyKey) => { | ||
| registerPropertyDependency(target, propertyKey, token, true); | ||
| }; | ||
| } | ||
| return { Injectable, Inject, LazyInject }; | ||
| } | ||
| exports.CircularDependencyError = CircularDependencyError; | ||
| exports.Container = Container; | ||
| exports.DependencyInjectionError = DependencyInjectionError; | ||
| exports.Scope = Scope; | ||
| exports.UnregisteredDependencyError = UnregisteredDependencyError; | ||
| exports.createChildContainer = createChildContainer; | ||
| exports.createContainer = createContainer; | ||
| exports.createDecorators = createDecorators; | ||
| exports.createToken = createToken; | ||
| exports.getIdentifierName = getIdentifierName; | ||
| //# sourceMappingURL=out.js.map | ||
| //# sourceMappingURL=index.cjs.map |
| {"version":3,"sources":["../src/types.ts","../src/container.ts","../src/decorators.ts"],"names":["Scope"],"mappings":"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","sourcesContent":["/**\n * Core types for the dependency injection framework\n */\n\n// Constructor type for classes\nexport interface Constructor<T = object> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- constructors often declare specific dependency types; we need a permissive arg signature\n new (...args: any[]): T;\n name?: string;\n prototype?: T;\n}\n\n// Token type for symbolic references\nexport type Token<T = object> = symbol & { __type?: T };\n\n// Identifier can be a constructor, token, or string\nexport type Identifier<T = object> = Constructor<T> | Token<T> | string;\n\n// Scope definitions\nexport enum Scope {\n SINGLETON = \"singleton\",\n TRANSIENT = \"transient\",\n REQUEST = \"request\",\n SESSION = \"session\",\n SCENARIO = \"scenario\",\n}\n\n// Registration options\nexport type PropertyInjectionDescriptor =\n | Identifier\n | {\n readonly token: Identifier;\n readonly lazy?: boolean;\n };\n\nexport type PropertyInjectionMap = {\n readonly [Key in string | number | symbol]?: PropertyInjectionDescriptor;\n};\n\nexport interface RegistrationOptions {\n scope?: Scope;\n tags?: string[];\n factory?: boolean;\n deps?: Identifier[];\n props?: PropertyDep[] | PropertyInjectionMap;\n}\n\n// Binding types\nexport interface ClassBinding<T = object> {\n type: \"class\";\n target: Constructor<T>;\n scope: Scope;\n tags: string[];\n deps?: Identifier[];\n props?: PropertyDep[];\n}\n\nexport interface ValueBinding<T = object> {\n type: \"value\";\n value: T;\n scope: Scope;\n tags: string[];\n}\n\nexport interface FactoryBinding<T = object> {\n type: \"factory\";\n factory: (container: IContainer) => T;\n scope: Scope;\n tags: string[];\n}\n\nexport interface TokenBinding<T = object> {\n type: \"token\";\n token: Token<T>;\n target: Constructor<T> | ((container: IContainer) => T);\n scope: Scope;\n tags: string[];\n}\n\nexport type Binding<T = object> =\n | ClassBinding<T>\n | ValueBinding<T>\n | FactoryBinding<T>\n | TokenBinding<T>;\n\n// Resolution context for circular dependency detection\nexport interface ResolutionContext {\n path: Set<Identifier>;\n depth: number;\n maxDepth: number;\n}\n\n// Container interface\nexport interface IContainer {\n // Registration methods\n register<T>(\n identifier: Identifier<T>,\n binding: Partial<Binding<T>>\n ): IContainer;\n registerClass<T>(\n target: Constructor<T>,\n options?: RegistrationOptions\n ): IContainer;\n registerValue<T>(\n identifier: Identifier<T>,\n value: T,\n options?: RegistrationOptions\n ): IContainer;\n registerFactory<T>(\n identifier: Identifier<T>,\n factory: (container: IContainer) => T,\n options?: RegistrationOptions\n ): IContainer;\n registerToken<T>(\n token: Token<T>,\n target: Constructor<T> | ((container: IContainer) => T),\n options?: RegistrationOptions\n ): IContainer;\n\n // Resolution methods\n resolve<T>(identifier: Identifier<T>): T;\n resolveAll<T>(identifier: Identifier<T>): T[];\n tryResolve<T>(identifier: Identifier<T>): T | undefined;\n\n // Introspection\n isRegistered<T>(identifier: Identifier<T>): boolean;\n getBinding<T>(identifier: Identifier<T>): Binding<T> | undefined;\n\n // Container hierarchy\n createChild(): IContainer;\n parent?: IContainer;\n\n // Lifecycle\n dispose(): Promise<void>;\n\n // Tagged resolution\n resolveByTag<T>(tag: string): T[];\n}\n\n// Dependency injection errors\nexport class DependencyInjectionError extends Error {\n constructor(\n message: string,\n public readonly identifier?: Identifier,\n public readonly context?: ResolutionContext\n ) {\n super(message);\n this.name = \"DependencyInjectionError\";\n }\n}\n\nexport class CircularDependencyError extends DependencyInjectionError {\n constructor(identifier: Identifier, context: ResolutionContext) {\n const identifierName = getIdentifierName(identifier);\n const pathNames = [...context.path].map(getIdentifierName);\n const path = pathNames.join(\" -> \");\n\n super(\n `Circular dependency detected: ${path} -> ${identifierName}`,\n identifier,\n context\n );\n this.name = \"CircularDependencyError\";\n }\n}\n\nexport class UnregisteredDependencyError extends DependencyInjectionError {\n constructor(identifier: Identifier) {\n const name = getIdentifierName(identifier);\n\n super(`No registration found for identifier: ${name}`, identifier);\n this.name = \"UnregisteredDependencyError\";\n }\n}\n\n// Helper function to get identifier name\nexport function getIdentifierName(identifier: Identifier): string {\n if (typeof identifier === \"string\") {\n return identifier;\n }\n if (typeof identifier === \"symbol\") {\n return identifier.toString();\n }\n return identifier.name || \"anonymous\";\n}\n\n// Helper to create tokens\nexport function createToken<T>(description?: string): Token<T> {\n return Symbol(description) as Token<T>;\n}\n\nexport interface PropertyDep {\n property: string | symbol;\n token: Identifier;\n lazy?: boolean;\n}\n","/**\n * Core container implementation for dependency injection\n */\n\nimport {\n IContainer,\n Identifier,\n Constructor,\n Token,\n Binding,\n ClassBinding,\n ValueBinding,\n FactoryBinding,\n TokenBinding,\n Scope,\n RegistrationOptions,\n PropertyDep,\n PropertyInjectionDescriptor,\n PropertyInjectionMap,\n ResolutionContext,\n CircularDependencyError,\n UnregisteredDependencyError,\n} from \"./types\";\n\nexport class Container implements IContainer {\n private readonly bindings = new Map<Identifier, Binding>();\n private readonly instances = new Map<Identifier, unknown>();\n private readonly scopedInstances = new Map<\n string,\n Map<Identifier, unknown>\n >();\n private readonly children = new Set<Container>();\n declare public readonly parent?: IContainer;\n\n constructor(parent?: IContainer) {\n if (parent !== undefined) {\n this.parent = parent;\n }\n }\n\n // Registration methods\n register<T>(\n identifier: Identifier<T>,\n binding: Partial<Binding<T>>\n ): IContainer {\n const fullBinding: Binding<T> = {\n scope: Scope.TRANSIENT,\n tags: [],\n ...binding,\n } as Binding<T>;\n\n this.bindings.set(identifier as Identifier, fullBinding as Binding);\n return this;\n }\n\n registerClass<T>(\n target: Constructor<T>,\n options: RegistrationOptions = {}\n ): IContainer {\n const propertyDeps = this.normalizePropertyOptions(options.props);\n const binding: ClassBinding<T> = {\n type: \"class\",\n target,\n scope: options.scope || Scope.TRANSIENT,\n tags: options.tags || [],\n deps: options.deps || [],\n ...(propertyDeps.length > 0 ? { props: propertyDeps } : {}),\n };\n\n this.bindings.set(target as Identifier, binding as Binding);\n return this;\n }\n\n registerValue<T>(\n identifier: Identifier<T>,\n value: T,\n options: RegistrationOptions = {}\n ): IContainer {\n const binding: ValueBinding<T> = {\n type: \"value\",\n value,\n scope: options.scope || Scope.SINGLETON,\n tags: options.tags || [],\n };\n\n this.bindings.set(identifier as Identifier, binding as Binding);\n return this;\n }\n\n registerFactory<T>(\n identifier: Identifier<T>,\n factory: (container: IContainer) => T,\n options: RegistrationOptions = {}\n ): IContainer {\n const binding: FactoryBinding<T> = {\n type: \"factory\",\n factory,\n scope: options.scope || Scope.TRANSIENT,\n tags: options.tags || [],\n };\n\n this.bindings.set(identifier as Identifier, binding as Binding);\n return this;\n }\n\n registerToken<T>(\n token: Token<T>,\n target: Constructor<T> | ((container: IContainer) => T),\n options: RegistrationOptions = {}\n ): IContainer {\n const binding: TokenBinding<T> = {\n type: \"token\",\n token,\n target,\n scope: options.scope || Scope.TRANSIENT,\n tags: options.tags || [],\n };\n\n this.bindings.set(token as Identifier, binding as Binding);\n return this;\n }\n\n // Resolution methods\n resolve<T>(identifier: Identifier<T>): T {\n const context: ResolutionContext = {\n path: new Set(),\n depth: 0,\n maxDepth: 50,\n };\n\n return this.resolveWithContext(identifier as Identifier, context) as T;\n }\n\n resolveAll<T>(identifier: Identifier<T>): T[] {\n const results: T[] = [];\n\n // Collect from this container\n for (const [key, binding] of this.bindings.entries()) {\n if (\n this.identifierMatches(key, identifier as Identifier) ||\n this.bindingHasMatchingTag(binding, identifier as Identifier)\n ) {\n try {\n const instance = this.resolve(key as Identifier<T>);\n results.push(instance);\n } catch {\n // Skip failed resolutions\n }\n }\n }\n\n // Collect from parent\n if (this.parent) {\n results.push(...this.parent.resolveAll(identifier));\n }\n\n return results;\n }\n\n tryResolve<T>(identifier: Identifier<T>): T | undefined {\n try {\n return this.resolve(identifier);\n } catch {\n return undefined;\n }\n }\n\n // Introspection\n isRegistered<T>(identifier: Identifier<T>): boolean {\n return (\n this.bindings.has(identifier as Identifier) ||\n (this.parent?.isRegistered(identifier) ?? false)\n );\n }\n\n getBinding<T>(identifier: Identifier<T>): Binding<T> | undefined {\n const binding = this.bindings.get(identifier as Identifier) as\n | Binding<T>\n | undefined;\n return binding || this.parent?.getBinding(identifier);\n }\n\n // Container hierarchy\n createChild(): IContainer {\n const child = new Container(this);\n this.children.add(child);\n return child;\n }\n\n // Tagged resolution\n resolveByTag<T>(tag: string): T[] {\n const results: T[] = [];\n\n for (const [identifier, binding] of this.bindings.entries()) {\n if (binding.tags.includes(tag)) {\n try {\n const instance = this.resolve(identifier as Identifier<T>);\n results.push(instance);\n } catch {\n // Skip failed resolutions\n }\n }\n }\n\n if (this.parent) {\n results.push(...this.parent.resolveByTag<T>(tag));\n }\n\n return results;\n }\n\n // Lifecycle\n async dispose(): Promise<void> {\n // Dispose children first\n await Promise.all([...this.children].map((child) => child.dispose()));\n this.children.clear();\n\n // Dispose instances that implement disposal\n for (const instance of this.instances.values()) {\n if (instance && typeof instance === \"object\" && \"dispose\" in instance) {\n const disposable = instance as { dispose(): Promise<void> | void };\n await disposable.dispose();\n }\n }\n\n // Clear all caches\n this.instances.clear();\n this.scopedInstances.clear();\n this.bindings.clear();\n }\n\n // Private resolution implementation\n private resolveWithContext<T>(\n identifier: Identifier,\n context: ResolutionContext\n ): T {\n // Check for circular dependencies\n if (context.path.has(identifier)) {\n throw new CircularDependencyError(identifier, context);\n }\n\n if (context.depth >= context.maxDepth) {\n throw new Error(\n `Maximum resolution depth exceeded (${context.maxDepth})`\n );\n }\n\n // Get binding first to check scope\n const binding = this.getBindingInternal(identifier);\n if (!binding) {\n throw new UnregisteredDependencyError(identifier);\n }\n\n // Check for cached instances based on scope\n if (binding.scope === Scope.SINGLETON && this.instances.has(identifier)) {\n return this.instances.get(identifier) as T;\n }\n\n // Check scoped cache for other scopes\n const scopedCache = this.getScopedCache(binding.scope);\n if (scopedCache?.has(identifier)) {\n return scopedCache.get(identifier) as T;\n }\n\n // Add to resolution path\n context.path.add(identifier);\n context.depth++;\n\n try {\n // Create instance\n const instance = this.createInstance(binding, context) as T;\n\n // Cache based on scope\n if (binding.scope === Scope.SINGLETON) {\n this.instances.set(identifier, instance);\n } else if (scopedCache) {\n scopedCache.set(identifier, instance);\n }\n\n return instance;\n } finally {\n // Clean up resolution path\n context.path.delete(identifier);\n context.depth--;\n }\n }\n\n private getBindingInternal<T>(\n identifier: Identifier<T>\n ): Binding<T> | undefined {\n const binding = this.bindings.get(identifier as Identifier);\n return (binding ||\n (this.parent as Container)?.getBindingInternal?.(identifier)) as\n | Binding<T>\n | undefined;\n }\n\n private createInstance<T>(\n binding: Binding<T>,\n context: ResolutionContext\n ): T {\n switch (binding.type) {\n case \"value\":\n return binding.value;\n\n case \"factory\": {\n // Create a context-aware container for factories\n const contextAwareContainer = this.createContextAwareContainer(context);\n return binding.factory(contextAwareContainer);\n }\n\n case \"class\":\n return this.instantiateClass(\n binding.target as unknown as Constructor<T & object>,\n context\n ) as T;\n\n case \"token\": {\n if (typeof binding.target === \"function\") {\n if (this.isConstructor(binding.target)) {\n return this.instantiateClass(\n binding.target as Constructor<T & object>,\n context\n );\n } else {\n // Create a context-aware container for token factories\n const contextAwareContainer =\n this.createContextAwareContainer(context);\n return (binding.target as (container: IContainer) => T)(\n contextAwareContainer\n );\n }\n }\n throw new Error(\n `Invalid token binding target for ${binding.token.toString()}`\n );\n }\n\n default:\n throw new Error(`Unknown binding type: ${(binding as Binding).type}`);\n }\n }\n\n private instantiateClass<T extends object>(\n constructor: Constructor<T>,\n context: ResolutionContext\n ): T {\n const binding = this.getBindingInternal(constructor) as ClassBinding<T>;\n if (!binding || binding.type !== \"class\") {\n throw new Error(\n `No class binding found for constructor: ${constructor.name}`\n );\n }\n\n // Resolve constructor dependencies from the 'deps' array\n const constructorArgs = (binding.deps || []).map((dep) => {\n return this.resolveWithContext(dep, context);\n });\n\n // Create the instance\n const instance = new constructor(...constructorArgs);\n\n // Resolve and set property dependencies from the 'props' array\n if (binding.props) {\n for (const prop of binding.props) {\n if (prop.lazy) {\n Object.defineProperty(instance, prop.property, {\n configurable: true,\n enumerable: true,\n get: () => {\n const resolved = this.resolveWithContext(prop.token, context);\n Object.defineProperty(instance, prop.property, {\n configurable: true,\n enumerable: true,\n writable: true,\n value: resolved,\n });\n return resolved;\n },\n });\n continue;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (instance as any)[prop.property] = this.resolveWithContext(\n prop.token,\n context\n );\n }\n }\n\n return instance;\n }\n\n private isConstructor(fn: unknown): fn is Constructor {\n return typeof fn === \"function\" && fn.prototype !== undefined;\n }\n\n private createContextAwareContainer(context: ResolutionContext): IContainer {\n return {\n register: <T>(identifier: Identifier<T>, binding: Partial<Binding<T>>) =>\n this.register(identifier, binding),\n registerClass: <T>(\n target: Constructor<T>,\n options?: RegistrationOptions\n ) => this.registerClass(target, options),\n registerValue: <T>(\n identifier: Identifier<T>,\n value: T,\n options?: RegistrationOptions\n ) => this.registerValue(identifier, value, options),\n registerFactory: <T>(\n identifier: Identifier<T>,\n factory: (container: IContainer) => T,\n options?: RegistrationOptions\n ) => this.registerFactory(identifier, factory, options),\n registerToken: <T>(\n token: Token<T>,\n target: Constructor<T> | ((container: IContainer) => T),\n options?: RegistrationOptions\n ) => this.registerToken(token, target, options),\n\n resolve: <T>(identifier: Identifier<T>): T => {\n return this.resolveWithContext(identifier as Identifier, context) as T;\n },\n\n resolveAll: <T>(identifier: Identifier<T>) => this.resolveAll(identifier),\n tryResolve: <T>(identifier: Identifier<T>) => this.tryResolve(identifier),\n isRegistered: <T>(identifier: Identifier<T>) =>\n this.isRegistered(identifier),\n getBinding: <T>(identifier: Identifier<T>) => this.getBinding(identifier),\n createChild: () => this.createChild(),\n resolveByTag: <T>(tag: string) => this.resolveByTag<T>(tag),\n dispose: () => this.dispose(),\n };\n }\n\n private getScopedCache(scope: Scope): Map<Identifier, unknown> | undefined {\n if (scope === Scope.SINGLETON || scope === Scope.TRANSIENT) {\n return undefined; // Singletons use global cache, transients are never cached\n }\n\n if (!this.scopedInstances.has(scope)) {\n this.scopedInstances.set(scope, new Map());\n }\n\n return this.scopedInstances.get(scope);\n }\n\n private identifierMatches(a: Identifier, b: Identifier): boolean {\n return a === b;\n }\n\n private bindingHasMatchingTag(\n binding: Binding,\n identifier: Identifier\n ): boolean {\n if (typeof identifier !== \"string\") {\n return false;\n }\n return binding.tags.includes(identifier);\n }\n\n private normalizePropertyOptions(\n props?: RegistrationOptions[\"props\"]\n ): PropertyDep[] {\n if (!props) {\n return [];\n }\n\n if (Array.isArray(props)) {\n return props.map((prop) => ({ ...prop }));\n }\n\n const map = props as PropertyInjectionMap;\n const normalized: PropertyDep[] = [];\n const descriptorMap = map as Record<PropertyKey, PropertyInjectionDescriptor>;\n\n for (const key of Reflect.ownKeys(descriptorMap)) {\n const descriptor = descriptorMap[key as PropertyKey];\n if (!descriptor) {\n continue;\n }\n\n if (!this.isPropertyInjectionObject(descriptor)) {\n normalized.push({\n property: key,\n token: descriptor as Identifier,\n });\n continue;\n }\n\n normalized.push({\n property: key,\n token: descriptor.token,\n ...(descriptor.lazy ? { lazy: descriptor.lazy } : {}),\n });\n }\n\n return normalized;\n }\n\n private isPropertyInjectionObject(\n descriptor: PropertyInjectionDescriptor\n ): descriptor is { token: Identifier; lazy?: boolean } {\n return typeof descriptor === \"object\" && descriptor !== null && \"token\" in descriptor;\n }\n}\n\n// Export convenience functions\nexport function createContainer(): IContainer {\n return new Container();\n}\n\nexport function createChildContainer(parent: IContainer): IContainer {\n return parent.createChild();\n}","import \"reflect-metadata\";\nimport { Scope } from \"./types\";\nimport type { Identifier, PropertyDep, IContainer } from \"./types\";\n\n// Define unique keys for storing metadata via reflect-metadata\nconst INJECT_PARAM_KEY = \"autometa:inject_param\";\nconst INJECT_PROP_KEY = \"autometa:inject_prop\";\n\nexport interface InjectableOptions {\n scope?: Scope;\n deps?: Identifier[];\n}\n\ntype InjectableTarget = new (...args: unknown[]) => object;\n\nfunction ensureInjectableTarget(value: unknown, decorator: string): asserts value is InjectableTarget {\n if (typeof value !== \"function\") {\n throw new TypeError(\n `[${decorator}] can only be used on classes. Received ${typeof value}.`\n );\n }\n}\n\n/**\n * Creates a set of decorators bound to a specific container instance.\n * This factory pattern ensures the decorators are decoupled from a global\n * container and can be used with multiple, separate containers.\n * @param container The container instance to which the decorators will register classes.\n */\nexport function createDecorators(container: IContainer) {\n function registerPropertyDependency(\n target: object,\n propertyKey: string | symbol,\n token: Identifier,\n lazy: boolean\n ): void {\n const existing =\n (Reflect.getMetadata(INJECT_PROP_KEY, target) as PropertyDep[] | undefined) || [];\n const filtered = existing.filter((dep) => dep.property !== propertyKey);\n filtered.push({ property: propertyKey, token, lazy });\n Reflect.defineMetadata(INJECT_PROP_KEY, filtered, target);\n }\n\n /**\n * A class decorator that marks a class as available for injection.\n * It gathers all dependency metadata from `@Inject` decorators and\n * `reflect-metadata` and registers the class with the container.\n */\n function Injectable(options: InjectableOptions = {}): ClassDecorator {\n return (target) => {\n ensureInjectableTarget(target, \"Injectable\");\n const ctor = target;\n // --- Constructor Injection ---\n const deps = options.deps || [];\n\n // --- Property Injection ---\n const props =\n (Reflect.getMetadata(INJECT_PROP_KEY, ctor.prototype) as PropertyDep[] | undefined) || [];\n\n // --- Registration ---\n // The container's `register` method expects an identifier and a binding object.\n const identifier = ctor as unknown as Identifier;\n const binding = {\n type: \"class\" as const,\n target: ctor,\n scope: options.scope || Scope.TRANSIENT,\n tags: [],\n deps,\n props,\n };\n\n container.register(identifier, binding);\n };\n }\n\n /**\n * A decorator that can be used on constructor parameters or class properties\n * to specify a dependency token.\n * @param token The token representing the dependency to inject.\n */\n function Inject(token: Identifier): PropertyDecorator & ParameterDecorator {\n return ((...args: [object, string | symbol, number?]) => {\n const [target, propertyKey, parameterIndex] = args;\n\n if (typeof parameterIndex === \"number\") {\n ensureInjectableTarget(target, \"Inject parameter\");\n const ctor = target;\n const paramTokens =\n (Reflect.getMetadata(INJECT_PARAM_KEY, ctor) as Map<number, Identifier> | undefined) ||\n new Map<number, Identifier>();\n paramTokens.set(parameterIndex, token);\n Reflect.defineMetadata(INJECT_PARAM_KEY, paramTokens, ctor);\n return;\n }\n\n registerPropertyDependency(target, propertyKey, token, false);\n }) as PropertyDecorator & ParameterDecorator;\n }\n\n function LazyInject(token: Identifier): PropertyDecorator {\n return (target, propertyKey) => {\n registerPropertyDependency(target, propertyKey, token, true);\n };\n }\n\n return { Injectable, Inject, LazyInject };\n}\n"]} |
+100
| /** | ||
| * Core types for the dependency injection framework | ||
| */ | ||
| export interface Constructor<T = object> { | ||
| new (...args: any[]): T; | ||
| name?: string; | ||
| prototype?: T; | ||
| } | ||
| export type Token<T = object> = symbol & { | ||
| __type?: T; | ||
| }; | ||
| export type Identifier<T = object> = Constructor<T> | Token<T> | string; | ||
| export declare enum Scope { | ||
| SINGLETON = "singleton", | ||
| TRANSIENT = "transient", | ||
| REQUEST = "request", | ||
| SESSION = "session", | ||
| SCENARIO = "scenario" | ||
| } | ||
| export type PropertyInjectionDescriptor = Identifier | { | ||
| readonly token: Identifier; | ||
| readonly lazy?: boolean; | ||
| }; | ||
| export type PropertyInjectionMap = { | ||
| readonly [Key in string | number | symbol]?: PropertyInjectionDescriptor; | ||
| }; | ||
| export interface RegistrationOptions { | ||
| scope?: Scope; | ||
| tags?: string[]; | ||
| factory?: boolean; | ||
| deps?: Identifier[]; | ||
| props?: PropertyDep[] | PropertyInjectionMap; | ||
| } | ||
| export interface ClassBinding<T = object> { | ||
| type: "class"; | ||
| target: Constructor<T>; | ||
| scope: Scope; | ||
| tags: string[]; | ||
| deps?: Identifier[]; | ||
| props?: PropertyDep[]; | ||
| } | ||
| export interface ValueBinding<T = object> { | ||
| type: "value"; | ||
| value: T; | ||
| scope: Scope; | ||
| tags: string[]; | ||
| } | ||
| export interface FactoryBinding<T = object> { | ||
| type: "factory"; | ||
| factory: (container: IContainer) => T; | ||
| scope: Scope; | ||
| tags: string[]; | ||
| } | ||
| export interface TokenBinding<T = object> { | ||
| type: "token"; | ||
| token: Token<T>; | ||
| target: Constructor<T> | ((container: IContainer) => T); | ||
| scope: Scope; | ||
| tags: string[]; | ||
| } | ||
| export type Binding<T = object> = ClassBinding<T> | ValueBinding<T> | FactoryBinding<T> | TokenBinding<T>; | ||
| export interface ResolutionContext { | ||
| path: Set<Identifier>; | ||
| depth: number; | ||
| maxDepth: number; | ||
| } | ||
| export interface IContainer { | ||
| register<T>(identifier: Identifier<T>, binding: Partial<Binding<T>>): IContainer; | ||
| registerClass<T>(target: Constructor<T>, options?: RegistrationOptions): IContainer; | ||
| registerValue<T>(identifier: Identifier<T>, value: T, options?: RegistrationOptions): IContainer; | ||
| registerFactory<T>(identifier: Identifier<T>, factory: (container: IContainer) => T, options?: RegistrationOptions): IContainer; | ||
| registerToken<T>(token: Token<T>, target: Constructor<T> | ((container: IContainer) => T), options?: RegistrationOptions): IContainer; | ||
| resolve<T>(identifier: Identifier<T>): T; | ||
| resolveAll<T>(identifier: Identifier<T>): T[]; | ||
| tryResolve<T>(identifier: Identifier<T>): T | undefined; | ||
| isRegistered<T>(identifier: Identifier<T>): boolean; | ||
| getBinding<T>(identifier: Identifier<T>): Binding<T> | undefined; | ||
| createChild(): IContainer; | ||
| parent?: IContainer; | ||
| dispose(): Promise<void>; | ||
| resolveByTag<T>(tag: string): T[]; | ||
| } | ||
| export declare class DependencyInjectionError extends Error { | ||
| readonly identifier?: Identifier<object> | undefined; | ||
| readonly context?: ResolutionContext | undefined; | ||
| constructor(message: string, identifier?: Identifier<object> | undefined, context?: ResolutionContext | undefined); | ||
| } | ||
| export declare class CircularDependencyError extends DependencyInjectionError { | ||
| constructor(identifier: Identifier, context: ResolutionContext); | ||
| } | ||
| export declare class UnregisteredDependencyError extends DependencyInjectionError { | ||
| constructor(identifier: Identifier); | ||
| } | ||
| export declare function getIdentifierName(identifier: Identifier): string; | ||
| export declare function createToken<T>(description?: string): Token<T>; | ||
| export interface PropertyDep { | ||
| property: string | symbol; | ||
| token: Identifier; | ||
| lazy?: boolean; | ||
| } |
Sorry, the diff of this file is not supported yet
+8
-0
| module.exports = { | ||
| root: true, | ||
| extends: ["custom"], | ||
| overrides: [ | ||
| { | ||
| files: ["src/__tests__/**/*.ts"], | ||
| rules: { | ||
| "@typescript-eslint/no-explicit-any": "off", | ||
| }, | ||
| }, | ||
| ], | ||
| }; |
+22
-13
| > @autometa/injection@0.1.3 test /Users/ben.aherne/Documents/GitHub/autometa/packages/injection | ||
| > vitest run --passWithNoTests | ||
| > @autometa/injection@0.1.5 test /Users/ben.aherne/Documents/GitHub/autometa/packages/injection | ||
| > vitest run src/__tests__/integration/mixed-injection.test.ts | ||
| RUN v1.4.0 /Users/ben.aherne/Documents/GitHub/autometa/packages/injection | ||
| [7m[1m[36m RUN [39m[22m[27m [36mv1.4.0[39m [90m/Users/ben.aherne/Documents/GitHub/autometa/packages/injection[39m | ||
| ✓ src/inject.spec.ts (2 tests) 23ms | ||
| ✓ src/metadata.spec.ts (4 tests) 53ms | ||
| ✓ src/container-context.spec.ts (3 tests) 1ms | ||
| ✓ src/fixture.spec.ts (3 tests) 2ms | ||
| ✓ src/metadata-registry.spec.ts (8 tests) 16ms | ||
| ✓ src/container.spec.ts (12 tests) 10ms | ||
| [?25l [90m·[39m Mixed Injection Tests[2m (3)[22m | ||
| [90m·[39m should resolve a service with both constructor and property injection | ||
| [90m·[39m should resolve a complex dependency graph | ||
| [90m·[39m should resolve ServiceCImpl directly | ||
| [?25l[?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [32m✓[39m Mixed Injection Tests[2m (3)[22m | ||
| [32m✓[39m should resolve a service with both constructor and property injection | ||
| [32m✓[39m should resolve a complex dependency graph | ||
| [32m✓[39m should resolve ServiceCImpl directly | ||
| [?25l[2K[1A[2K[1A[2K[1A[2K[1A[2K[G [32m✓[39m [2msrc/__tests__/integration/[22mmixed-injection[2m.test.ts[22m[2m (3)[22m | ||
| [32m✓[39m Mixed Injection Tests[2m (3)[22m | ||
| [32m✓[39m should resolve a service with both constructor and property injection | ||
| [32m✓[39m should resolve a complex dependency graph | ||
| [32m✓[39m should resolve ServiceCImpl directly | ||
| Test Files 6 passed (6) | ||
| Tests 32 passed (32) | ||
| Start at 13:48:40 | ||
| Duration 2.18s (transform 578ms, setup 0ms, collect 1.56s, tests 105ms, environment 1ms, prepare 5.16s) | ||
| [2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m | ||
| [2m Tests [22m [1m[32m3 passed[39m[22m[90m (3)[39m | ||
| [2m Start at [22m 01:06:24 | ||
| [2m Duration [22m 3.13s[2m (transform 326ms, setup 0ms, collect 509ms, tests 6ms, environment 0ms, prepare 649ms)[22m | ||
| [?25h[?25h |
+37
-0
| # @autometa/injection | ||
| ## 1.0.0-rc.0 | ||
| ### Major Changes | ||
| - 39896e93: Autometa v1 rewrite: start the `-rc` prerelease line for the new major version series (HTTP is a breaking change from v1 and becomes v2). | ||
| This release candidate includes: | ||
| **Breaking Changes:** | ||
| - Complete v1 rewrite with new architecture and API | ||
| - HTTP package breaking changes (now v2) | ||
| **Fixes:** | ||
| - `dto-builder`: Omit undefined validator in extend config | ||
| - `dto-builder`: Factory extend with defaults and methods support | ||
| - `test-builder`: Avoid non-null assertions in edit distance calculation | ||
| - `assertions`: Move HTTP matcher placeholder out of test files | ||
| - `runner`: Make JSON.stringify(world) safe | ||
| - `http`: Avoid double query serialization in axios transport | ||
| **Improvements:** | ||
| - `testrail-cucumber`: Harden Gherkin parsing and attach rule metadata | ||
| - `cli`: Improve test stability (ANSI color handling, control regex) | ||
| - `bind-decorator`: Add error case test coverage to meet 90% threshold | ||
| - Build stability: Isolated tsbuildinfo for type builds | ||
| - CI workflows: Fixed shell quoting in version detection across all workflows | ||
| - Examples: Align tsconfigs and use this-bound step functions | ||
| **Documentation:** | ||
| - Expanded lifecycle and runtime architecture docs | ||
| - New discovery and from-scratch getting started guides | ||
| - Updated configuration and HTTP client reference | ||
| ## 0.1.5 | ||
@@ -4,0 +41,0 @@ |
+12
-181
@@ -1,184 +0,15 @@ | ||
| import { Class } from '@autometa/types'; | ||
| declare const META_DATA: unique symbol; | ||
| declare const CONSTRUCTOR: unique symbol; | ||
| declare const AutometaSymbol: { | ||
| readonly META_DATA: typeof META_DATA; | ||
| readonly CONSTRUCTOR: typeof CONSTRUCTOR; | ||
| }; | ||
| declare class InjectionToken { | ||
| readonly name: string; | ||
| constructor(name: string); | ||
| } | ||
| declare function Token(name: string): InjectionToken; | ||
| declare const DisposeMethod: unique symbol; | ||
| declare const DisposeGlobalMethod: unique symbol; | ||
| declare function DisposeTagFilter(tagFilter: string): (_: { | ||
| [DisposeMethod](tags: string[], isTagsMatch: (filter: string) => boolean): unknown; | ||
| }, __: string | symbol, descriptor: PropertyDescriptor) => void; | ||
| type BaseMetadata = { | ||
| key: string; | ||
| custom?: Record<string, unknown>; | ||
| }; | ||
| type InjectValueMetadata = BaseMetadata & { | ||
| value: unknown; | ||
| custom?: Record<string, unknown>; | ||
| }; | ||
| type InjectClassMetadata = BaseMetadata & { | ||
| class: Class<unknown> | InjectionToken; | ||
| custom?: Record<string, unknown>; | ||
| }; | ||
| type InjectFactoryMetadata = BaseMetadata & { | ||
| factory: () => unknown; | ||
| custom?: Record<string, unknown>; | ||
| }; | ||
| type InjectTokenMetadata = BaseMetadata & { | ||
| token: InjectionToken; | ||
| custom?: Record<string, unknown>; | ||
| }; | ||
| type MetadataInfo = InjectClassMetadata | InjectValueMetadata | InjectFactoryMetadata | InjectTokenMetadata; | ||
| type AutometaMetadata = { | ||
| [key: string]: MetadataInfo; | ||
| }; | ||
| type InjectorKey = Class<unknown> | InjectionToken; | ||
| declare function metadata<T extends object>(target: T): { | ||
| set: (info: MetadataInfo, override?: boolean) => void; | ||
| update: (key: string, updater: (info: MetadataInfo) => void) => void; | ||
| custom: <T_1>(key: symbol, value: T_1, override?: boolean) => T_1; | ||
| getCustom: <T_2>(key: symbol) => T_2; | ||
| hasCustom: <T_3>(key: symbol) => T_3; | ||
| get: (key: string) => MetadataInfo; | ||
| readonly keys: (keyof T)[]; | ||
| }; | ||
| declare const INJECTION_SCOPE: { | ||
| readonly SINGLETON: 0; | ||
| readonly TRANSIENT: 1; | ||
| readonly CACHED: 2; | ||
| }; | ||
| type InjectionScope = (typeof INJECTION_SCOPE)[keyof typeof INJECTION_SCOPE]; | ||
| declare function registerSingleton<T extends InjectorKey>(target: T, instance: unknown): void; | ||
| declare function getSingleton<T extends InjectorKey>(target: T): unknown | undefined; | ||
| declare function hasSingleton<T extends InjectorKey>(target: T): boolean | undefined; | ||
| declare function registerScope<T extends InjectorKey>(target: T, scope: InjectionScope): void; | ||
| declare function getScope<T extends InjectorKey>(target: T): InjectionScope | undefined; | ||
| declare function hasScope<T extends InjectorKey>(target: T): boolean | undefined; | ||
| declare function registerContainerContext<T extends InjectorKey>(context: symbol, target: T, instance: unknown): unknown; | ||
| declare function getContainerContexts<T extends InjectorKey>(context: symbol, target: T): unknown | undefined; | ||
| declare function hasContainerContext<T extends InjectorKey>(context: symbol, target: T): boolean; | ||
| declare function registerTypeToken<T>(token: InjectionToken, target: Class<T>): void; | ||
| declare function getTypeToken<T>(token: InjectionToken): Class<T> | undefined; | ||
| declare function hasToken(token: InjectionToken): boolean; | ||
| declare function clearRegistries(): void; | ||
| /** | ||
| * Marks a class as injectable. Optionally, | ||
| * an Injection Scope can be defined, which determines | ||
| * the strategy used to initialize the decorated class. | ||
| * @autometa/injection - Dependency Injection Framework | ||
| * | ||
| * INJECTION_SCOPE.CACHED: The class will be initialized once per container, but behave as a singleton within the container | ||
| * INJECTION_SCOPE.SINGLETON: The class will be initialized once per container, and behave as a singleton across all containers | ||
| * INJECTION_SCOPE.TRANSIENT: The class will be initialized once per injection, it will not be cached. | ||
| * | ||
| * By default if no scope is specified, the class will be cached. Once created all dependant sharing a container will share this instance. | ||
| * @param target | ||
| * A modern, type-safe dependency injection framework with: | ||
| * - Container-based system with child container support | ||
| * - Class, value, factory, and token-based registration | ||
| * - Scoped instances (singleton, transient, request, session) | ||
| * - Circular dependency detection | ||
| * - Lazy resolution | ||
| */ | ||
| declare function Fixture(target: Class<unknown>): void; | ||
| declare function Fixture<T extends Class<unknown>>(scope?: InjectionScope): (target: T) => void; | ||
| declare const Inject: { | ||
| /** | ||
| * Decorator factory which defines the Type of the property to inject. This | ||
| * information will be used at class construction to automatically inject | ||
| * that property with the appropriate type. If the type is class which | ||
| * has not been marked as a `Fixture` then the dependency will be treated | ||
| * as cached - meaning once created, the same instance will be used for | ||
| * all subsequent injections. However the target class can be | ||
| * defined as a `Singleton` or `Transient` fixture to override this behavior. | ||
| */ | ||
| class: <T>(cls: InjectionToken | Class<T>) => (target: unknown, propertyKey: string) => void; | ||
| /** | ||
| * Decorator factory which defines a factory function that will | ||
| * be used to inject the property. The factory function will be | ||
| * called once per injection, and it's return value will be | ||
| * used as the value of the property. Currently only synchronous | ||
| * factory functions are supported. | ||
| * @param factory | ||
| * @returns | ||
| */ | ||
| factory: <T_1>(factory: () => T_1) => (target: unknown, propertyKey: string) => void; | ||
| /** | ||
| * Decorator factory which defines a value to inject into the property. | ||
| * The value will be injected directly into the property without any | ||
| * further processing. Equivalent to simply assigning the value to the | ||
| * property. | ||
| * | ||
| * @param value | ||
| * @returns | ||
| */ | ||
| value: <T_2 extends string | InjectionToken | Class<unknown>>(value: T_2) => (target: unknown, propertyKey: string) => void; | ||
| }; | ||
| /** | ||
| * Defines the constructor signature for an injectable class. | ||
| * Takes a Rest Parameter of Classes or Injection Tokens which | ||
| * match the constructor signature of the class. | ||
| * | ||
| * ```ts | ||
| * @Fixture | ||
| * @Constructor(HttpClient) | ||
| * class MyClient { | ||
| * constructor( | ||
| * readonly http: HttpClient, | ||
| * ) {} | ||
| * | ||
| * get() { | ||
| * return this.http.get("https://example.com"); | ||
| * } | ||
| * } | ||
| * ``` | ||
| * | ||
| * The `MyClient` class is now injectable and can be used automatically | ||
| * by adding it to the `App` with the same method. | ||
| * | ||
| * ```ts | ||
| * @AppType(World) | ||
| * @Constructor(MyClient) | ||
| * class App { | ||
| * constructor( | ||
| * readonly client: MyClient, | ||
| * ) {} | ||
| * } | ||
| * ``` | ||
| * | ||
| * @param args A Rest Parameter of Classes or Injection Tokens which can be used to automatically inject new, cached or singleton dependencies into this class | ||
| */ | ||
| declare function Constructor<T extends InjectorKey[]>(...args: T): (target: object) => void; | ||
| declare class Container { | ||
| #private; | ||
| readonly reference: symbol; | ||
| constructor(reference: symbol); | ||
| registerSingleton<T>(token: InjectionToken, type: Class<T>): Container; | ||
| registerSingleton<T>(type: Class<T>): Container; | ||
| registerCached<T>(token: InjectionToken, type: Class<T>): Container; | ||
| registerCached<T>(type: Class<T>): Container; | ||
| registerTransient<T>(target: Class<T>): Container; | ||
| registerTransient<T>(token: InjectionToken, target: Class<T>): Container; | ||
| registerSingletonValue(identifier: string, value: unknown): this; | ||
| registerCachedValue(identifier: string, value: unknown): this; | ||
| get<T>(token: string): T; | ||
| get<T>(token: InjectionToken): T; | ||
| get<T>(target: Class<T>): T; | ||
| get<T>(target: InjectorKey | string): T; | ||
| disposeAll(tags: string[], isTagsMatch: (tags: string[], filter: string) => boolean): Promise<void>; | ||
| disposeGlobal(tags: string[], isTagsMatch: (tags: string[], filter: string) => boolean): Promise<void>; | ||
| } | ||
| declare function defineContainerContext(name: string): symbol; | ||
| export { AutometaMetadata, AutometaSymbol, BaseMetadata, Constructor, Container, DisposeGlobalMethod, DisposeMethod, DisposeTagFilter, Fixture, INJECTION_SCOPE, Inject, InjectClassMetadata, InjectFactoryMetadata, InjectTokenMetadata, InjectValueMetadata, InjectionScope, InjectionToken, InjectorKey, MetadataInfo, Token, clearRegistries, defineContainerContext, getContainerContexts, getScope, getSingleton, getTypeToken, hasContainerContext, hasScope, hasSingleton, hasToken, metadata, registerContainerContext, registerScope, registerSingleton, registerTypeToken }; | ||
| export * from './types'; | ||
| export * from './container'; | ||
| export * from './decorators'; | ||
| export { Container, createContainer, createChildContainer } from './container'; | ||
| export { Scope, createToken, type IContainer, type Identifier, type Constructor, type Token } from './types'; |
+397
-444
@@ -1,493 +0,446 @@ | ||
| "use strict"; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| import 'reflect-metadata'; | ||
| // src/types.ts | ||
| var Scope = /* @__PURE__ */ ((Scope2) => { | ||
| Scope2["SINGLETON"] = "singleton"; | ||
| Scope2["TRANSIENT"] = "transient"; | ||
| Scope2["REQUEST"] = "request"; | ||
| Scope2["SESSION"] = "session"; | ||
| Scope2["SCENARIO"] = "scenario"; | ||
| return Scope2; | ||
| })(Scope || {}); | ||
| var DependencyInjectionError = class extends Error { | ||
| constructor(message, identifier, context) { | ||
| super(message); | ||
| this.identifier = identifier; | ||
| this.context = context; | ||
| this.name = "DependencyInjectionError"; | ||
| } | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| var CircularDependencyError = class extends DependencyInjectionError { | ||
| constructor(identifier, context) { | ||
| const identifierName = getIdentifierName(identifier); | ||
| const pathNames = [...context.path].map(getIdentifierName); | ||
| const path = pathNames.join(" -> "); | ||
| super( | ||
| `Circular dependency detected: ${path} -> ${identifierName}`, | ||
| identifier, | ||
| context | ||
| ); | ||
| this.name = "CircularDependencyError"; | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var __accessCheck = (obj, member, msg) => { | ||
| if (!member.has(obj)) | ||
| throw TypeError("Cannot " + msg); | ||
| var UnregisteredDependencyError = class extends DependencyInjectionError { | ||
| constructor(identifier) { | ||
| const name = getIdentifierName(identifier); | ||
| super(`No registration found for identifier: ${name}`, identifier); | ||
| this.name = "UnregisteredDependencyError"; | ||
| } | ||
| }; | ||
| var __privateGet = (obj, member, getter) => { | ||
| __accessCheck(obj, member, "read from private field"); | ||
| return getter ? getter.call(obj) : member.get(obj); | ||
| }; | ||
| var __privateAdd = (obj, member, value) => { | ||
| if (member.has(obj)) | ||
| throw TypeError("Cannot add the same private member more than once"); | ||
| member instanceof WeakSet ? member.add(obj) : member.set(obj, value); | ||
| }; | ||
| var __privateMethod = (obj, member, method) => { | ||
| __accessCheck(obj, member, "access private method"); | ||
| return method; | ||
| }; | ||
| // src/index.ts | ||
| var src_exports = {}; | ||
| __export(src_exports, { | ||
| AutometaSymbol: () => AutometaSymbol, | ||
| Constructor: () => Constructor, | ||
| Container: () => Container, | ||
| DisposeGlobalMethod: () => DisposeGlobalMethod, | ||
| DisposeMethod: () => DisposeMethod, | ||
| DisposeTagFilter: () => DisposeTagFilter, | ||
| Fixture: () => Fixture, | ||
| INJECTION_SCOPE: () => INJECTION_SCOPE, | ||
| Inject: () => Inject, | ||
| InjectionToken: () => InjectionToken, | ||
| Token: () => Token, | ||
| clearRegistries: () => clearRegistries, | ||
| defineContainerContext: () => defineContainerContext, | ||
| getContainerContexts: () => getContainerContexts, | ||
| getScope: () => getScope, | ||
| getSingleton: () => getSingleton, | ||
| getTypeToken: () => getTypeToken, | ||
| hasContainerContext: () => hasContainerContext, | ||
| hasScope: () => hasScope, | ||
| hasSingleton: () => hasSingleton, | ||
| hasToken: () => hasToken, | ||
| metadata: () => metadata, | ||
| registerContainerContext: () => registerContainerContext, | ||
| registerScope: () => registerScope, | ||
| registerSingleton: () => registerSingleton, | ||
| registerTypeToken: () => registerTypeToken | ||
| }); | ||
| module.exports = __toCommonJS(src_exports); | ||
| // src/symbol.ts | ||
| var META_DATA = Symbol("autometa:meta-data"); | ||
| var CONSTRUCTOR = Symbol("autometa:meta-data:constructor"); | ||
| var AutometaSymbol = { | ||
| META_DATA, | ||
| CONSTRUCTOR | ||
| }; | ||
| // src/metadata.ts | ||
| function metadata(target) { | ||
| const withMetaData = target; | ||
| if (!(AutometaSymbol.META_DATA in target)) { | ||
| defineNonEnumerable(target, AutometaSymbol.META_DATA, {}); | ||
| function getIdentifierName(identifier) { | ||
| if (typeof identifier === "string") { | ||
| return identifier; | ||
| } | ||
| const metadata2 = withMetaData[AutometaSymbol.META_DATA]; | ||
| return { | ||
| set: (info, override = true) => { | ||
| if (!metadata2[info.key]) { | ||
| defineEnumerable(metadata2, info.key, info); | ||
| return; | ||
| } | ||
| if (override) { | ||
| defineEnumerable(metadata2, info.key, info); | ||
| return; | ||
| } | ||
| }, | ||
| update: (key, updater) => { | ||
| const current = metadata2[key]; | ||
| if (!current) { | ||
| const name = "name" in target ? target.name : target.constructor.name; | ||
| const err = `Cannot create a constructor for ${name} as no metadata has been created for it. Try decorating it with '@Fixture'`; | ||
| throw new Error(err); | ||
| } | ||
| updater(current); | ||
| }, | ||
| custom: (key, value, override = true) => { | ||
| const md = withMetaData; | ||
| if (!md[key] || override) { | ||
| defineEnumerable(target, key, value); | ||
| } | ||
| return md[key]; | ||
| }, | ||
| getCustom: (key) => { | ||
| const md = withMetaData; | ||
| return md[key]; | ||
| }, | ||
| hasCustom: (key) => { | ||
| const md = withMetaData; | ||
| return md[key]; | ||
| }, | ||
| get: (key) => { | ||
| return metadata2[key]; | ||
| }, | ||
| get keys() { | ||
| return Object.keys(metadata2); | ||
| } | ||
| }; | ||
| } | ||
| function defineNonEnumerable(target, key, value) { | ||
| Object.defineProperty(target, key, { | ||
| enumerable: false, | ||
| configurable: true, | ||
| writable: false, | ||
| value | ||
| }); | ||
| } | ||
| function defineEnumerable(target, key, value) { | ||
| Object.defineProperty(target, key, { | ||
| enumerable: true, | ||
| configurable: true, | ||
| writable: true, | ||
| value | ||
| }); | ||
| } | ||
| // src/metadata-registry.ts | ||
| var ScopeRegistry = /* @__PURE__ */ new Map(); | ||
| var TokenTypeRegistry = /* @__PURE__ */ new Map(); | ||
| var SingletonRegistry = /* @__PURE__ */ new Map(); | ||
| var ContainerContextRegistry = /* @__PURE__ */ new Map(); | ||
| function registerSingleton(target, instance) { | ||
| if (SingletonRegistry.has(target)) { | ||
| throw new Error(`Singleton already registered for ${target.name}`); | ||
| if (typeof identifier === "symbol") { | ||
| return identifier.toString(); | ||
| } | ||
| SingletonRegistry.set(target, instance); | ||
| return identifier.name || "anonymous"; | ||
| } | ||
| function getSingleton(target) { | ||
| return SingletonRegistry.get(target); | ||
| function createToken(description) { | ||
| return Symbol(description); | ||
| } | ||
| function hasSingleton(target) { | ||
| return SingletonRegistry.has(target); | ||
| } | ||
| function registerScope(target, scope) { | ||
| ScopeRegistry.set(target, scope); | ||
| } | ||
| function getScope(target) { | ||
| return ScopeRegistry.get(target); | ||
| } | ||
| function hasScope(target) { | ||
| return ScopeRegistry.has(target); | ||
| } | ||
| function registerContainerContext(context, target, instance) { | ||
| if (!ContainerContextRegistry.has(context)) { | ||
| ContainerContextRegistry.set(context, /* @__PURE__ */ new Map()); | ||
| } | ||
| ContainerContextRegistry.get(context)?.set(target, instance); | ||
| return instance; | ||
| } | ||
| function getContainerContexts(context, target) { | ||
| if (!ContainerContextRegistry.has(context)) { | ||
| ContainerContextRegistry.set(context, /* @__PURE__ */ new Map()); | ||
| } | ||
| return ContainerContextRegistry.get(context)?.get(target); | ||
| } | ||
| function hasContainerContext(context, target) { | ||
| if (!ContainerContextRegistry.has(context)) { | ||
| ContainerContextRegistry.set(context, /* @__PURE__ */ new Map()); | ||
| } | ||
| return ContainerContextRegistry.get(context)?.has(target) ?? false; | ||
| } | ||
| function registerTypeToken(token, target) { | ||
| TokenTypeRegistry.set(token, target); | ||
| } | ||
| function getTypeToken(token) { | ||
| return TokenTypeRegistry.get(token); | ||
| } | ||
| function hasToken(token) { | ||
| return TokenTypeRegistry.has(token); | ||
| } | ||
| function clearRegistries() { | ||
| ScopeRegistry.clear(); | ||
| SingletonRegistry.clear(); | ||
| ContainerContextRegistry.clear(); | ||
| TokenTypeRegistry.clear(); | ||
| } | ||
| // src/scope.enum.ts | ||
| var INJECTION_SCOPE = { | ||
| SINGLETON: 0, | ||
| TRANSIENT: 1, | ||
| CACHED: 2 | ||
| }; | ||
| // src/fixture.ts | ||
| function Fixture(arg) { | ||
| if (arg !== void 0 && typeof arg !== "number") { | ||
| registerScope(arg, INJECTION_SCOPE.CACHED); | ||
| return; | ||
| // src/container.ts | ||
| var Container = class _Container { | ||
| constructor(parent) { | ||
| this.bindings = /* @__PURE__ */ new Map(); | ||
| this.instances = /* @__PURE__ */ new Map(); | ||
| this.scopedInstances = /* @__PURE__ */ new Map(); | ||
| this.children = /* @__PURE__ */ new Set(); | ||
| if (parent !== void 0) { | ||
| this.parent = parent; | ||
| } | ||
| } | ||
| return (target) => { | ||
| registerScope(target, arg ?? INJECTION_SCOPE.CACHED); | ||
| }; | ||
| } | ||
| // src/get-constructor.ts | ||
| function getConstructor(target) { | ||
| if (target && "constructor" in target) { | ||
| return target.constructor; | ||
| // Registration methods | ||
| register(identifier, binding) { | ||
| const fullBinding = { | ||
| scope: "transient" /* TRANSIENT */, | ||
| tags: [], | ||
| ...binding | ||
| }; | ||
| this.bindings.set(identifier, fullBinding); | ||
| return this; | ||
| } | ||
| throw new Error(`Cannot get constructor for ${target}`); | ||
| } | ||
| // src/inject.ts | ||
| var Inject = { | ||
| /** | ||
| * Decorator factory which defines the Type of the property to inject. This | ||
| * information will be used at class construction to automatically inject | ||
| * that property with the appropriate type. If the type is class which | ||
| * has not been marked as a `Fixture` then the dependency will be treated | ||
| * as cached - meaning once created, the same instance will be used for | ||
| * all subsequent injections. However the target class can be | ||
| * defined as a `Singleton` or `Transient` fixture to override this behavior. | ||
| */ | ||
| class: (cls) => { | ||
| return function(target, propertyKey) { | ||
| metadata(getConstructor(target)).set({ | ||
| key: propertyKey, | ||
| class: cls | ||
| }); | ||
| registerClass(target, options = {}) { | ||
| const propertyDeps = this.normalizePropertyOptions(options.props); | ||
| const binding = { | ||
| type: "class", | ||
| target, | ||
| scope: options.scope || "transient" /* TRANSIENT */, | ||
| tags: options.tags || [], | ||
| deps: options.deps || [], | ||
| ...propertyDeps.length > 0 ? { props: propertyDeps } : {} | ||
| }; | ||
| }, | ||
| /** | ||
| * Decorator factory which defines a factory function that will | ||
| * be used to inject the property. The factory function will be | ||
| * called once per injection, and it's return value will be | ||
| * used as the value of the property. Currently only synchronous | ||
| * factory functions are supported. | ||
| * @param factory | ||
| * @returns | ||
| */ | ||
| factory: (factory) => { | ||
| return function(target, propertyKey) { | ||
| metadata(getConstructor(target)).set({ | ||
| key: propertyKey, | ||
| factory | ||
| }); | ||
| this.bindings.set(target, binding); | ||
| return this; | ||
| } | ||
| registerValue(identifier, value, options = {}) { | ||
| const binding = { | ||
| type: "value", | ||
| value, | ||
| scope: options.scope || "singleton" /* SINGLETON */, | ||
| tags: options.tags || [] | ||
| }; | ||
| }, | ||
| /** | ||
| * Decorator factory which defines a value to inject into the property. | ||
| * The value will be injected directly into the property without any | ||
| * further processing. Equivalent to simply assigning the value to the | ||
| * property. | ||
| * | ||
| * @param value | ||
| * @returns | ||
| */ | ||
| value: (value) => { | ||
| return function(target, propertyKey) { | ||
| metadata(getConstructor(target)).set({ | ||
| key: propertyKey, | ||
| value | ||
| }); | ||
| this.bindings.set(identifier, binding); | ||
| return this; | ||
| } | ||
| registerFactory(identifier, factory, options = {}) { | ||
| const binding = { | ||
| type: "factory", | ||
| factory, | ||
| scope: options.scope || "transient" /* TRANSIENT */, | ||
| tags: options.tags || [] | ||
| }; | ||
| this.bindings.set(identifier, binding); | ||
| return this; | ||
| } | ||
| }; | ||
| // src/token.ts | ||
| var InjectionToken = class { | ||
| constructor(name) { | ||
| this.name = name; | ||
| registerToken(token, target, options = {}) { | ||
| const binding = { | ||
| type: "token", | ||
| token, | ||
| target, | ||
| scope: options.scope || "transient" /* TRANSIENT */, | ||
| tags: options.tags || [] | ||
| }; | ||
| this.bindings.set(token, binding); | ||
| return this; | ||
| } | ||
| }; | ||
| var tokenMap = /* @__PURE__ */ new Map(); | ||
| function Token(name) { | ||
| if (!tokenMap.has(name)) { | ||
| const token = new InjectionToken(name); | ||
| tokenMap.set(name, token); | ||
| // Resolution methods | ||
| resolve(identifier) { | ||
| const context = { | ||
| path: /* @__PURE__ */ new Set(), | ||
| depth: 0, | ||
| maxDepth: 50 | ||
| }; | ||
| return this.resolveWithContext(identifier, context); | ||
| } | ||
| return tokenMap.get(name); | ||
| } | ||
| var DisposeMethod = Symbol("DisposeMethod"); | ||
| var DisposeGlobalMethod = Symbol("DisposeGlobalMethod"); | ||
| function DisposeTagFilter(tagFilter) { | ||
| return function(_, __, descriptor) { | ||
| const original = descriptor.value; | ||
| descriptor.value = function(tags, isTagMatch) { | ||
| if (isTagMatch(tags, tagFilter)) { | ||
| return original.apply(this); | ||
| resolveAll(identifier) { | ||
| const results = []; | ||
| for (const [key, binding] of this.bindings.entries()) { | ||
| if (this.identifierMatches(key, identifier) || this.bindingHasMatchingTag(binding, identifier)) { | ||
| try { | ||
| const instance = this.resolve(key); | ||
| results.push(instance); | ||
| } catch { | ||
| } | ||
| } | ||
| }; | ||
| }; | ||
| } | ||
| // src/constructor.ts | ||
| function Constructor(...args) { | ||
| return function(target) { | ||
| metadata(target).custom(AutometaSymbol.CONSTRUCTOR, args); | ||
| }; | ||
| } | ||
| // src/container.ts | ||
| var _disposables, _globalDisposables, _throwOnSingletonTokenClash, throwOnSingletonTokenClash_fn, _assembleTarget, assembleTarget_fn, _getConstructorArgs, getConstructorArgs_fn; | ||
| var Container = class { | ||
| constructor(reference) { | ||
| this.reference = reference; | ||
| __privateAdd(this, _throwOnSingletonTokenClash); | ||
| __privateAdd(this, _assembleTarget); | ||
| __privateAdd(this, _getConstructorArgs); | ||
| __privateAdd(this, _disposables, /* @__PURE__ */ new Set()); | ||
| __privateAdd(this, _globalDisposables, /* @__PURE__ */ new Set()); | ||
| } | ||
| registerSingleton(token, type) { | ||
| registerScope(token, INJECTION_SCOPE.SINGLETON); | ||
| if (token instanceof InjectionToken && type) { | ||
| registerTypeToken(token, type); | ||
| } | ||
| return this; | ||
| } | ||
| registerCached(token, type) { | ||
| registerScope(token, INJECTION_SCOPE.CACHED); | ||
| if (token instanceof InjectionToken && type) { | ||
| registerTypeToken(token, type); | ||
| if (this.parent) { | ||
| results.push(...this.parent.resolveAll(identifier)); | ||
| } | ||
| return this; | ||
| return results; | ||
| } | ||
| registerTransient(target, type) { | ||
| __privateMethod(this, _throwOnSingletonTokenClash, throwOnSingletonTokenClash_fn).call(this, target); | ||
| registerScope(target, INJECTION_SCOPE.TRANSIENT); | ||
| if (target instanceof InjectionToken && type) { | ||
| registerTypeToken(target, type); | ||
| tryResolve(identifier) { | ||
| try { | ||
| return this.resolve(identifier); | ||
| } catch { | ||
| return void 0; | ||
| } | ||
| return this; | ||
| } | ||
| registerSingletonValue(identifier, value) { | ||
| registerSingleton(Token(identifier), value); | ||
| return this; | ||
| // Introspection | ||
| isRegistered(identifier) { | ||
| return this.bindings.has(identifier) || (this.parent?.isRegistered(identifier) ?? false); | ||
| } | ||
| registerCachedValue(identifier, value) { | ||
| __privateMethod(this, _throwOnSingletonTokenClash, throwOnSingletonTokenClash_fn).call(this, Token(identifier)); | ||
| registerScope(Token(identifier), INJECTION_SCOPE.CACHED); | ||
| registerContainerContext(this.reference, Token(identifier), value); | ||
| return this; | ||
| getBinding(identifier) { | ||
| const binding = this.bindings.get(identifier); | ||
| return binding || this.parent?.getBinding(identifier); | ||
| } | ||
| get(target) { | ||
| target = getRealTarget(target); | ||
| if (hasSingleton(target)) { | ||
| return getSingleton(target); | ||
| // Container hierarchy | ||
| createChild() { | ||
| const child = new _Container(this); | ||
| this.children.add(child); | ||
| return child; | ||
| } | ||
| // Tagged resolution | ||
| resolveByTag(tag) { | ||
| const results = []; | ||
| for (const [identifier, binding] of this.bindings.entries()) { | ||
| if (binding.tags.includes(tag)) { | ||
| try { | ||
| const instance = this.resolve(identifier); | ||
| results.push(instance); | ||
| } catch { | ||
| } | ||
| } | ||
| } | ||
| const scope = getScope(target); | ||
| if (!hasScope(target)) { | ||
| registerScope(target, INJECTION_SCOPE.CACHED); | ||
| if (this.parent) { | ||
| results.push(...this.parent.resolveByTag(tag)); | ||
| } | ||
| const type = getTypeToken(target) ?? target; | ||
| if (scope === INJECTION_SCOPE.SINGLETON) { | ||
| const instance = __privateMethod(this, _assembleTarget, assembleTarget_fn).call(this, type); | ||
| registerSingleton(target, instance); | ||
| return results; | ||
| } | ||
| // Lifecycle | ||
| async dispose() { | ||
| await Promise.all([...this.children].map((child) => child.dispose())); | ||
| this.children.clear(); | ||
| for (const instance of this.instances.values()) { | ||
| if (instance && typeof instance === "object" && "dispose" in instance) { | ||
| const disposable = instance; | ||
| await disposable.dispose(); | ||
| } | ||
| } | ||
| this.instances.clear(); | ||
| this.scopedInstances.clear(); | ||
| this.bindings.clear(); | ||
| } | ||
| // Private resolution implementation | ||
| resolveWithContext(identifier, context) { | ||
| if (context.path.has(identifier)) { | ||
| throw new CircularDependencyError(identifier, context); | ||
| } | ||
| if (context.depth >= context.maxDepth) { | ||
| throw new Error( | ||
| `Maximum resolution depth exceeded (${context.maxDepth})` | ||
| ); | ||
| } | ||
| const binding = this.getBindingInternal(identifier); | ||
| if (!binding) { | ||
| throw new UnregisteredDependencyError(identifier); | ||
| } | ||
| if (binding.scope === "singleton" /* SINGLETON */ && this.instances.has(identifier)) { | ||
| return this.instances.get(identifier); | ||
| } | ||
| const scopedCache = this.getScopedCache(binding.scope); | ||
| if (scopedCache?.has(identifier)) { | ||
| return scopedCache.get(identifier); | ||
| } | ||
| context.path.add(identifier); | ||
| context.depth++; | ||
| try { | ||
| const instance = this.createInstance(binding, context); | ||
| if (binding.scope === "singleton" /* SINGLETON */) { | ||
| this.instances.set(identifier, instance); | ||
| } else if (scopedCache) { | ||
| scopedCache.set(identifier, instance); | ||
| } | ||
| return instance; | ||
| } finally { | ||
| context.path.delete(identifier); | ||
| context.depth--; | ||
| } | ||
| if (scope === INJECTION_SCOPE.CACHED) { | ||
| if (hasContainerContext(this.reference, target)) { | ||
| return getContainerContexts(this.reference, target); | ||
| } | ||
| getBindingInternal(identifier) { | ||
| const binding = this.bindings.get(identifier); | ||
| return binding || this.parent?.getBindingInternal?.(identifier); | ||
| } | ||
| createInstance(binding, context) { | ||
| switch (binding.type) { | ||
| case "value": | ||
| return binding.value; | ||
| case "factory": { | ||
| const contextAwareContainer = this.createContextAwareContainer(context); | ||
| return binding.factory(contextAwareContainer); | ||
| } | ||
| const assembled = __privateMethod(this, _assembleTarget, assembleTarget_fn).call(this, type); | ||
| return registerContainerContext(this.reference, target, assembled); | ||
| case "class": | ||
| return this.instantiateClass( | ||
| binding.target, | ||
| context | ||
| ); | ||
| case "token": { | ||
| if (typeof binding.target === "function") { | ||
| if (this.isConstructor(binding.target)) { | ||
| return this.instantiateClass( | ||
| binding.target, | ||
| context | ||
| ); | ||
| } else { | ||
| const contextAwareContainer = this.createContextAwareContainer(context); | ||
| return binding.target( | ||
| contextAwareContainer | ||
| ); | ||
| } | ||
| } | ||
| throw new Error( | ||
| `Invalid token binding target for ${binding.token.toString()}` | ||
| ); | ||
| } | ||
| default: | ||
| throw new Error(`Unknown binding type: ${binding.type}`); | ||
| } | ||
| return __privateMethod(this, _assembleTarget, assembleTarget_fn).call(this, type); | ||
| } | ||
| async disposeAll(tags, isTagsMatch) { | ||
| for (const disposable of __privateGet(this, _disposables)) { | ||
| await disposable[DisposeMethod](tags, isTagsMatch); | ||
| instantiateClass(constructor, context) { | ||
| const binding = this.getBindingInternal(constructor); | ||
| if (!binding || binding.type !== "class") { | ||
| throw new Error( | ||
| `No class binding found for constructor: ${constructor.name}` | ||
| ); | ||
| } | ||
| const constructorArgs = (binding.deps || []).map((dep) => { | ||
| return this.resolveWithContext(dep, context); | ||
| }); | ||
| const instance = new constructor(...constructorArgs); | ||
| if (binding.props) { | ||
| for (const prop of binding.props) { | ||
| if (prop.lazy) { | ||
| Object.defineProperty(instance, prop.property, { | ||
| configurable: true, | ||
| enumerable: true, | ||
| get: () => { | ||
| const resolved = this.resolveWithContext(prop.token, context); | ||
| Object.defineProperty(instance, prop.property, { | ||
| configurable: true, | ||
| enumerable: true, | ||
| writable: true, | ||
| value: resolved | ||
| }); | ||
| return resolved; | ||
| } | ||
| }); | ||
| continue; | ||
| } | ||
| instance[prop.property] = this.resolveWithContext( | ||
| prop.token, | ||
| context | ||
| ); | ||
| } | ||
| } | ||
| return instance; | ||
| } | ||
| async disposeGlobal(tags, isTagsMatch) { | ||
| for (const disposable of __privateGet(this, _globalDisposables)) { | ||
| await disposable[DisposeMethod](tags, isTagsMatch); | ||
| isConstructor(fn) { | ||
| return typeof fn === "function" && fn.prototype !== void 0; | ||
| } | ||
| createContextAwareContainer(context) { | ||
| return { | ||
| register: (identifier, binding) => this.register(identifier, binding), | ||
| registerClass: (target, options) => this.registerClass(target, options), | ||
| registerValue: (identifier, value, options) => this.registerValue(identifier, value, options), | ||
| registerFactory: (identifier, factory, options) => this.registerFactory(identifier, factory, options), | ||
| registerToken: (token, target, options) => this.registerToken(token, target, options), | ||
| resolve: (identifier) => { | ||
| return this.resolveWithContext(identifier, context); | ||
| }, | ||
| resolveAll: (identifier) => this.resolveAll(identifier), | ||
| tryResolve: (identifier) => this.tryResolve(identifier), | ||
| isRegistered: (identifier) => this.isRegistered(identifier), | ||
| getBinding: (identifier) => this.getBinding(identifier), | ||
| createChild: () => this.createChild(), | ||
| resolveByTag: (tag) => this.resolveByTag(tag), | ||
| dispose: () => this.dispose() | ||
| }; | ||
| } | ||
| getScopedCache(scope) { | ||
| if (scope === "singleton" /* SINGLETON */ || scope === "transient" /* TRANSIENT */) { | ||
| return void 0; | ||
| } | ||
| if (!this.scopedInstances.has(scope)) { | ||
| this.scopedInstances.set(scope, /* @__PURE__ */ new Map()); | ||
| } | ||
| return this.scopedInstances.get(scope); | ||
| } | ||
| }; | ||
| _disposables = new WeakMap(); | ||
| _globalDisposables = new WeakMap(); | ||
| _throwOnSingletonTokenClash = new WeakSet(); | ||
| throwOnSingletonTokenClash_fn = function(token) { | ||
| if (hasSingleton(token)) { | ||
| throw new Error( | ||
| `Singleton token ${token.name} is already registered. Use a different token or register a cached dependency` | ||
| ); | ||
| identifierMatches(a, b) { | ||
| return a === b; | ||
| } | ||
| }; | ||
| _assembleTarget = new WeakSet(); | ||
| assembleTarget_fn = function(target) { | ||
| const constructor = __privateMethod(this, _getConstructorArgs, getConstructorArgs_fn).call(this, target); | ||
| const args = constructor.map((arg) => this.get(arg)); | ||
| const instance = new target(...args); | ||
| const meta = metadata(target); | ||
| const keys = meta.keys; | ||
| for (const key of keys) { | ||
| const info = meta.get(key); | ||
| if (!info) { | ||
| throw new Error( | ||
| `No metadata found for ${key} in ${target.name}. Did you forget to decorate it? | ||
| Use the \`@Inject.class\`, \`@Inject.factory\` or \`@Inject.value\` decorator to register a dependency type or value` | ||
| ); | ||
| bindingHasMatchingTag(binding, identifier) { | ||
| if (typeof identifier !== "string") { | ||
| return false; | ||
| } | ||
| if (info && "class" in info) { | ||
| const dependency = this.get(info.class); | ||
| instance[key] = dependency; | ||
| return binding.tags.includes(identifier); | ||
| } | ||
| normalizePropertyOptions(props) { | ||
| if (!props) { | ||
| return []; | ||
| } | ||
| if (info && "factory" in info) { | ||
| const dependency = info.factory(); | ||
| instance[key] = dependency; | ||
| if (Array.isArray(props)) { | ||
| return props.map((prop) => ({ ...prop })); | ||
| } | ||
| if (info && "value" in info) { | ||
| const dependency = info.value; | ||
| instance[key] = dependency; | ||
| const map = props; | ||
| const normalized = []; | ||
| const descriptorMap = map; | ||
| for (const key of Reflect.ownKeys(descriptorMap)) { | ||
| const descriptor = descriptorMap[key]; | ||
| if (!descriptor) { | ||
| continue; | ||
| } | ||
| if (!this.isPropertyInjectionObject(descriptor)) { | ||
| normalized.push({ | ||
| property: key, | ||
| token: descriptor | ||
| }); | ||
| continue; | ||
| } | ||
| normalized.push({ | ||
| property: key, | ||
| token: descriptor.token, | ||
| ...descriptor.lazy ? { lazy: descriptor.lazy } : {} | ||
| }); | ||
| } | ||
| return normalized; | ||
| } | ||
| if (DisposeMethod in instance && typeof instance[DisposeMethod] === "function") { | ||
| __privateGet(this, _disposables).add(instance); | ||
| isPropertyInjectionObject(descriptor) { | ||
| return typeof descriptor === "object" && descriptor !== null && "token" in descriptor; | ||
| } | ||
| return instance; | ||
| }; | ||
| _getConstructorArgs = new WeakSet(); | ||
| getConstructorArgs_fn = function(target) { | ||
| return metadata(target).getCustom(AutometaSymbol.CONSTRUCTOR) ?? []; | ||
| }; | ||
| function getRealTarget(target) { | ||
| if (typeof target === "string") { | ||
| return Token(target); | ||
| function createContainer() { | ||
| return new Container(); | ||
| } | ||
| function createChildContainer(parent) { | ||
| return parent.createChild(); | ||
| } | ||
| var INJECT_PARAM_KEY = "autometa:inject_param"; | ||
| var INJECT_PROP_KEY = "autometa:inject_prop"; | ||
| function ensureInjectableTarget(value, decorator) { | ||
| if (typeof value !== "function") { | ||
| throw new TypeError( | ||
| `[${decorator}] can only be used on classes. Received ${typeof value}.` | ||
| ); | ||
| } | ||
| if (target instanceof InjectionToken) { | ||
| return target; | ||
| } | ||
| function createDecorators(container) { | ||
| function registerPropertyDependency(target, propertyKey, token, lazy) { | ||
| const existing = Reflect.getMetadata(INJECT_PROP_KEY, target) || []; | ||
| const filtered = existing.filter((dep) => dep.property !== propertyKey); | ||
| filtered.push({ property: propertyKey, token, lazy }); | ||
| Reflect.defineMetadata(INJECT_PROP_KEY, filtered, target); | ||
| } | ||
| return target; | ||
| function Injectable(options = {}) { | ||
| return (target) => { | ||
| ensureInjectableTarget(target, "Injectable"); | ||
| const ctor = target; | ||
| const deps = options.deps || []; | ||
| const props = Reflect.getMetadata(INJECT_PROP_KEY, ctor.prototype) || []; | ||
| const identifier = ctor; | ||
| const binding = { | ||
| type: "class", | ||
| target: ctor, | ||
| scope: options.scope || "transient" /* TRANSIENT */, | ||
| tags: [], | ||
| deps, | ||
| props | ||
| }; | ||
| container.register(identifier, binding); | ||
| }; | ||
| } | ||
| function Inject(token) { | ||
| return (...args) => { | ||
| const [target, propertyKey, parameterIndex] = args; | ||
| if (typeof parameterIndex === "number") { | ||
| ensureInjectableTarget(target, "Inject parameter"); | ||
| const ctor = target; | ||
| const paramTokens = Reflect.getMetadata(INJECT_PARAM_KEY, ctor) || /* @__PURE__ */ new Map(); | ||
| paramTokens.set(parameterIndex, token); | ||
| Reflect.defineMetadata(INJECT_PARAM_KEY, paramTokens, ctor); | ||
| return; | ||
| } | ||
| registerPropertyDependency(target, propertyKey, token, false); | ||
| }; | ||
| } | ||
| function LazyInject(token) { | ||
| return (target, propertyKey) => { | ||
| registerPropertyDependency(target, propertyKey, token, true); | ||
| }; | ||
| } | ||
| return { Injectable, Inject, LazyInject }; | ||
| } | ||
| // src/container-context.ts | ||
| var global = Symbol.for("autometa:container:global"); | ||
| function defineContainerContext(name) { | ||
| if (name === "global") { | ||
| return global; | ||
| } | ||
| const hash = name.replace(/\s/g, "-").toLowerCase(); | ||
| return Symbol.for(`autometa:container:${hash}`); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| AutometaSymbol, | ||
| Constructor, | ||
| Container, | ||
| DisposeGlobalMethod, | ||
| DisposeMethod, | ||
| DisposeTagFilter, | ||
| Fixture, | ||
| INJECTION_SCOPE, | ||
| Inject, | ||
| InjectionToken, | ||
| Token, | ||
| clearRegistries, | ||
| defineContainerContext, | ||
| getContainerContexts, | ||
| getScope, | ||
| getSingleton, | ||
| getTypeToken, | ||
| hasContainerContext, | ||
| hasScope, | ||
| hasSingleton, | ||
| hasToken, | ||
| metadata, | ||
| registerContainerContext, | ||
| registerScope, | ||
| registerSingleton, | ||
| registerTypeToken | ||
| }); | ||
| export { CircularDependencyError, Container, DependencyInjectionError, Scope, UnregisteredDependencyError, createChildContainer, createContainer, createDecorators, createToken, getIdentifierName }; | ||
| //# sourceMappingURL=out.js.map | ||
| //# sourceMappingURL=index.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/index.ts","../src/symbol.ts","../src/metadata.ts","../src/metadata-registry.ts","../src/scope.enum.ts","../src/fixture.ts","../src/get-constructor.ts","../src/inject.ts","../src/token.ts","../src/constructor.ts","../src/container.ts","../src/container-context.ts"],"sourcesContent":["export * from \"./symbol\";\nexport * from \"./metadata\";\nexport * from \"./metadata-registry\";\nexport * from \"./scope.enum\";\nexport * from \"./fixture\";\nexport * from \"./inject\";\nexport * from \"./types\";\nexport * from \"./token\";\nexport * from \"./constructor\";\nexport * from \"./container\";\nexport * from \"./container-context\";\n// throw new Error(\"Double check exports\");\n","const META_DATA: unique symbol = Symbol(\"autometa:meta-data\");\nconst CONSTRUCTOR: unique symbol = Symbol(\"autometa:meta-data:constructor\");\nexport const AutometaSymbol = {\n META_DATA,\n CONSTRUCTOR,\n} as const;\n","import { AutometaSymbol } from \"./symbol\";\nimport { MetadataInfo } from \"./types\";\nimport { AutometaMetadata } from \"./types\";\nexport function metadata<T extends object>(target: T) {\n const withMetaData = target as T & {\n [AutometaSymbol.META_DATA]: AutometaMetadata;\n };\n if (!(AutometaSymbol.META_DATA in target)) {\n defineNonEnumerable(target, AutometaSymbol.META_DATA, {});\n }\n const metadata = withMetaData[AutometaSymbol.META_DATA];\n\n return {\n set: (info: MetadataInfo, override = true) => {\n if (!metadata[info.key]) {\n defineEnumerable(metadata, info.key, info);\n return;\n }\n if (override) {\n defineEnumerable(metadata, info.key, info);\n return;\n }\n },\n update: (key: string, updater: (info: MetadataInfo) => void) => {\n const current = metadata[key];\n if (!current) {\n const name = \"name\" in target ? target.name : target.constructor.name;\n const err = `Cannot create a constructor for ${name} as no metadata has been created for it. Try decorating it with '@Fixture'`;\n throw new Error(err);\n }\n updater(current);\n },\n custom: <T>(key: symbol, value: T, override = true) => {\n const md = withMetaData as unknown as Record<symbol, unknown>;\n if (!md[key] || override) {\n defineEnumerable(target, key, value);\n }\n return md[key] as T;\n },\n getCustom: <T>(key: symbol): T => {\n const md = withMetaData as unknown as Record<symbol, unknown>;\n return md[key] as T;\n },\n hasCustom: <T>(key: symbol): T => {\n const md = withMetaData as unknown as Record<symbol, unknown>;\n return md[key] as T;\n },\n get: (key: string): MetadataInfo => {\n return metadata[key];\n },\n get keys() {\n return Object.keys(metadata) as (keyof T)[];\n },\n };\n}\n\nfunction defineNonEnumerable<T>(\n target: T,\n key: string | symbol,\n value: unknown\n) {\n Object.defineProperty(target, key, {\n enumerable: false,\n configurable: true,\n writable: false,\n value,\n });\n}\n\nfunction defineEnumerable<T>(target: T, key: string | symbol, value: unknown) {\n Object.defineProperty(target, key, {\n enumerable: true,\n configurable: true,\n writable: true,\n value,\n });\n}\n","import { Class } from \"@autometa/types\";\nimport { InjectionScope } from \"./scope.enum\";\nimport { InjectorKey } from \"./types\";\nimport { InjectionToken } from \"./token\";\n\nconst ScopeRegistry = new Map<InjectorKey, InjectionScope>();\nconst TokenTypeRegistry = new Map<InjectionToken, Class<unknown>>();\nconst SingletonRegistry = new Map<InjectorKey, unknown>();\nconst ContainerContextRegistry = new Map<symbol, Map<InjectorKey, unknown>>();\n\nexport function registerSingleton<T extends InjectorKey>(\n target: T,\n instance: unknown\n) {\n if (SingletonRegistry.has(target)) {\n throw new Error(`Singleton already registered for ${target.name}`);\n }\n SingletonRegistry.set(target, instance);\n}\nexport function getSingleton<T extends InjectorKey>(\n target: T\n): unknown | undefined {\n return SingletonRegistry.get(target);\n}\n\nexport function hasSingleton<T extends InjectorKey>(\n target: T\n): boolean | undefined {\n return SingletonRegistry.has(target);\n}\n\nexport function registerScope<T extends InjectorKey>(\n target: T,\n scope: InjectionScope\n) {\n ScopeRegistry.set(target, scope);\n}\n\nexport function getScope<T extends InjectorKey>(\n target: T\n): InjectionScope | undefined {\n return ScopeRegistry.get(target);\n}\n\nexport function hasScope<T extends InjectorKey>(\n target: T\n): boolean | undefined {\n return ScopeRegistry.has(target);\n}\n\nexport function registerContainerContext<T extends InjectorKey>(\n context: symbol,\n target: T,\n instance: unknown\n) {\n if (!ContainerContextRegistry.has(context)) {\n ContainerContextRegistry.set(context, new Map());\n }\n ContainerContextRegistry.get(context)?.set(target, instance);\n return instance;\n}\n\nexport function getContainerContexts<T extends InjectorKey>(\n context: symbol,\n target: T\n): unknown | undefined {\n if (!ContainerContextRegistry.has(context)) {\n ContainerContextRegistry.set(context, new Map());\n }\n return ContainerContextRegistry.get(context)?.get(target);\n}\n\nexport function hasContainerContext<T extends InjectorKey>(\n context: symbol,\n target: T\n): boolean {\n if (!ContainerContextRegistry.has(context)) {\n ContainerContextRegistry.set(context, new Map());\n }\n return ContainerContextRegistry.get(context)?.has(target) ?? false;\n}\nexport function registerTypeToken<T>(token: InjectionToken, target: Class<T>) {\n TokenTypeRegistry.set(token, target);\n}\n\nexport function getTypeToken<T>(token: InjectionToken): Class<T> | undefined {\n return TokenTypeRegistry.get(token) as Class<T>;\n}\n\nexport function hasToken(token: InjectionToken): boolean {\n return TokenTypeRegistry.has(token);\n}\nexport function clearRegistries() {\n ScopeRegistry.clear();\n SingletonRegistry.clear();\n ContainerContextRegistry.clear();\n TokenTypeRegistry.clear();\n}\n","export const INJECTION_SCOPE = {\n SINGLETON: 0,\n TRANSIENT: 1,\n CACHED: 2,\n} as const;\n\nexport type InjectionScope =\n (typeof INJECTION_SCOPE)[keyof typeof INJECTION_SCOPE];\n","import { Class } from \"@autometa/types\";\nimport { INJECTION_SCOPE, InjectionScope } from \"./scope.enum\";\nimport { registerScope } from \"./metadata-registry\";\n\n/**\n * Marks a class as injectable. Optionally,\n * an Injection Scope can be defined, which determines\n * the strategy used to initialize the decorated class.\n *\n * INJECTION_SCOPE.CACHED: The class will be initialized once per container, but behave as a singleton within the container\n * INJECTION_SCOPE.SINGLETON: The class will be initialized once per container, and behave as a singleton across all containers\n * INJECTION_SCOPE.TRANSIENT: The class will be initialized once per injection, it will not be cached.\n *\n * By default if no scope is specified, the class will be cached. Once created all dependant sharing a container will share this instance.\n * @param target\n */\nexport function Fixture(target: Class<unknown>): void;\nexport function Fixture<T extends Class<unknown>>(\n scope?: InjectionScope\n): (target: T) => void;\nexport function Fixture(\n arg: InjectionScope | undefined | Class<unknown>\n): void | ((target: Class<unknown>) => void) {\n if (arg !== undefined && typeof arg !== \"number\") {\n registerScope(arg, INJECTION_SCOPE.CACHED);\n return;\n }\n return (target: Class<unknown>) => {\n registerScope(target, arg ?? INJECTION_SCOPE.CACHED);\n };\n}\n","export function getConstructor(target: unknown) {\n if (target && \"constructor\" in (target as object)) {\n return target.constructor;\n }\n throw new Error(`Cannot get constructor for ${target}`);\n}\n","import { Class } from \"@autometa/types\";\nimport { metadata } from \"./metadata\";\nimport { InjectionToken } from \"./token\";\nimport { getConstructor } from \"./get-constructor\";\n\nexport const Inject = {\n /**\n * Decorator factory which defines the Type of the property to inject. This\n * information will be used at class construction to automatically inject\n * that property with the appropriate type. If the type is class which\n * has not been marked as a `Fixture` then the dependency will be treated\n * as cached - meaning once created, the same instance will be used for\n * all subsequent injections. However the target class can be\n * defined as a `Singleton` or `Transient` fixture to override this behavior.\n */\n class: <T>(cls: Class<T> | InjectionToken) => {\n return function (target: unknown, propertyKey: string) {\n metadata(getConstructor(target)).set({\n key: propertyKey,\n class: cls,\n });\n };\n },\n /**\n * Decorator factory which defines a factory function that will\n * be used to inject the property. The factory function will be\n * called once per injection, and it's return value will be\n * used as the value of the property. Currently only synchronous\n * factory functions are supported.\n * @param factory\n * @returns\n */\n factory: <T>(factory: () => T) => {\n return function (target: unknown, propertyKey: string) {\n metadata(getConstructor(target)).set({\n key: propertyKey,\n factory: factory,\n });\n };\n },\n /**\n * Decorator factory which defines a value to inject into the property.\n * The value will be injected directly into the property without any\n * further processing. Equivalent to simply assigning the value to the\n * property.\n *\n * @param value\n * @returns\n */\n value: <T extends Class<unknown> | InjectionToken | string>(value: T) => {\n return function (target: unknown, propertyKey: string) {\n metadata(getConstructor(target)).set({\n key: propertyKey,\n value: value,\n });\n };\n },\n};\n","export class InjectionToken {\n constructor(public readonly name: string) {}\n}\nconst tokenMap = new Map<string, InjectionToken>();\n\nexport function Token(name: string): InjectionToken {\n if (!tokenMap.has(name)) {\n const token = new InjectionToken(name);\n tokenMap.set(name, token);\n }\n\n return tokenMap.get(name) as InjectionToken;\n}\n\nexport const DisposeMethod = Symbol(\"DisposeMethod\");\nexport const DisposeGlobalMethod = Symbol(\"DisposeGlobalMethod\");\n\nexport function DisposeTagFilter(tagFilter: string) {\n return function (\n _: {\n [DisposeMethod](\n tags: string[],\n isTagsMatch: (filter: string) => boolean\n ): unknown;\n },\n __: string | symbol,\n descriptor: PropertyDescriptor\n ) {\n const original = descriptor.value;\n descriptor.value = function (\n tags: string[],\n isTagMatch: (tags: string[], filter: string) => boolean\n ) {\n if (isTagMatch(tags, tagFilter)) {\n return original.apply(this);\n }\n };\n };\n}\n","import { metadata } from \"./metadata\";\nimport { AutometaSymbol } from \"./symbol\";\nimport { InjectorKey } from \"./types\";\n\n/**\n * Defines the constructor signature for an injectable class.\n * Takes a Rest Parameter of Classes or Injection Tokens which\n * match the constructor signature of the class.\n *\n * ```ts\n * @Fixture\n * @Constructor(HttpClient)\n * class MyClient {\n * constructor(\n * readonly http: HttpClient,\n * ) {}\n *\n * get() {\n * return this.http.get(\"https://example.com\");\n * }\n * }\n * ```\n *\n * The `MyClient` class is now injectable and can be used automatically\n * by adding it to the `App` with the same method.\n *\n * ```ts\n * @AppType(World)\n * @Constructor(MyClient)\n * class App {\n * constructor(\n * readonly client: MyClient,\n * ) {}\n * }\n * ```\n *\n * @param args A Rest Parameter of Classes or Injection Tokens which can be used to automatically inject new, cached or singleton dependencies into this class\n */\nexport function Constructor<T extends InjectorKey[]>(...args: T) {\n return function (target: object) {\n metadata(target).custom(AutometaSymbol.CONSTRUCTOR, args);\n };\n}\n","import { Class } from \"@autometa/types\";\nimport {\n getContainerContexts,\n getScope,\n getSingleton,\n getTypeToken,\n hasContainerContext,\n hasScope,\n hasSingleton,\n registerContainerContext,\n registerScope,\n registerSingleton,\n registerTypeToken,\n} from \"./metadata-registry\";\nimport { metadata } from \"./metadata\";\nimport { INJECTION_SCOPE } from \"./scope.enum\";\nimport { DisposeMethod, InjectionToken, Token } from \"./token\";\nimport { InjectorKey } from \"./types\";\nimport { AutometaSymbol } from \"./symbol\";\n\nexport class Container {\n #disposables = new Set<{\n [DisposeMethod](\n tags: string[],\n isTagsMatch: (tags: string[], filter: string) => boolean\n ): unknown;\n }>();\n #globalDisposables = new Set<{\n [DisposeMethod](\n tags: string[],\n isTagsMatch: (tags: string[], filter: string) => boolean\n ): unknown;\n }>();\n constructor(readonly reference: symbol) {}\n\n registerSingleton<T>(token: InjectionToken, type: Class<T>): Container;\n registerSingleton<T>(type: Class<T>): Container;\n registerSingleton<T>(token: Class<T> | InjectionToken, type?: Class<T>) {\n registerScope(token, INJECTION_SCOPE.SINGLETON);\n if (token instanceof InjectionToken && type) {\n registerTypeToken(token, type);\n }\n return this;\n }\n\n registerCached<T>(token: InjectionToken, type: Class<T>): Container;\n registerCached<T>(type: Class<T>): Container;\n registerCached<T>(token: Class<T> | InjectionToken, type?: Class<T>) {\n registerScope(token, INJECTION_SCOPE.CACHED);\n if (token instanceof InjectionToken && type) {\n registerTypeToken(token, type);\n }\n return this;\n }\n\n registerTransient<T>(target: Class<T>): Container;\n registerTransient<T>(token: InjectionToken, target: Class<T>): Container;\n registerTransient(\n target: Class<unknown> | InjectionToken,\n type?: Class<unknown>\n ) {\n this.#throwOnSingletonTokenClash(target);\n registerScope(target, INJECTION_SCOPE.TRANSIENT);\n if (target instanceof InjectionToken && type) {\n registerTypeToken(target, type);\n }\n return this;\n }\n\n registerSingletonValue(identifier: string, value: unknown) {\n registerSingleton(Token(identifier), value);\n return this;\n }\n\n registerCachedValue(identifier: string, value: unknown) {\n this.#throwOnSingletonTokenClash(Token(identifier));\n registerScope(Token(identifier), INJECTION_SCOPE.CACHED);\n registerContainerContext(this.reference, Token(identifier), value);\n return this;\n }\n\n #throwOnSingletonTokenClash(token: InjectorKey) {\n if (hasSingleton(token)) {\n throw new Error(\n `Singleton token ${token.name} is already registered. Use a different token or register a cached dependency`\n );\n }\n }\n get<T>(token: string): T;\n get<T>(token: InjectionToken): T;\n get<T>(target: Class<T>): T;\n get<T>(target: InjectorKey | string): T;\n get<T>(target: InjectorKey | string): T {\n target = getRealTarget(target);\n\n if (hasSingleton(target)) {\n return getSingleton(target) as T;\n }\n const scope = getScope(target);\n if (!hasScope(target)) {\n registerScope(target, INJECTION_SCOPE.CACHED);\n }\n const type = getTypeToken(target) ?? (target as Class<unknown>);\n if (scope === INJECTION_SCOPE.SINGLETON) {\n const instance = this.#assembleTarget(type);\n registerSingleton(target, instance);\n return instance as T;\n }\n\n if (scope === INJECTION_SCOPE.CACHED) {\n if (hasContainerContext(this.reference, target)) {\n return getContainerContexts(this.reference, target) as T;\n }\n const assembled = this.#assembleTarget(type);\n return registerContainerContext(this.reference, target, assembled) as T;\n }\n\n return this.#assembleTarget(type) as T;\n }\n\n async disposeAll(\n tags: string[],\n isTagsMatch: (tags: string[], filter: string) => boolean\n ) {\n for (const disposable of this.#disposables) {\n await disposable[DisposeMethod](tags, isTagsMatch);\n }\n }\n\n async disposeGlobal(\n tags: string[],\n isTagsMatch: (tags: string[], filter: string) => boolean\n ) {\n for (const disposable of this.#globalDisposables) {\n await disposable[DisposeMethod](tags, isTagsMatch);\n }\n }\n\n #assembleTarget<T>(target: Class<T>): T {\n const constructor = this.#getConstructorArgs<T>(target);\n const args = constructor.map((arg) => this.get(arg));\n const instance = new target(...args) as Record<string, unknown>;\n const meta = metadata(target);\n const keys = meta.keys as string[];\n for (const key of keys) {\n const info = meta.get(key);\n if (!info) {\n throw new Error(\n `No metadata found for ${key} in ${target.name}. Did you forget to decorate it? \nUse the \\`@Inject.class\\`, \\`@Inject.factory\\` or \\`@Inject.value\\` decorator to register a dependency type or value`\n );\n }\n if (info && \"class\" in info) {\n const dependency = this.get(info.class);\n instance[key] = dependency;\n }\n\n if (info && \"factory\" in info) {\n const dependency = info.factory();\n instance[key] = dependency;\n }\n\n if (info && \"value\" in info) {\n const dependency = info.value;\n instance[key] = dependency;\n }\n }\n if (\n DisposeMethod in instance &&\n typeof instance[DisposeMethod] === \"function\"\n ) {\n this.#disposables.add(instance as { [DisposeMethod](): unknown });\n }\n return instance as T;\n }\n\n #getConstructorArgs<T>(target: Class<T>) {\n return (\n metadata(target).getCustom<InjectorKey[]>(AutometaSymbol.CONSTRUCTOR) ??\n []\n );\n }\n}\n\nfunction getRealTarget(target: Class<unknown> | InjectionToken | string) {\n if (typeof target === \"string\") {\n return Token(target);\n }\n if (target instanceof InjectionToken) {\n return target;\n }\n return target;\n}\n","const global = Symbol.for(\"autometa:container:global\");\n\nexport function defineContainerContext(name: string) {\n if (name === \"global\") {\n return global;\n }\n const hash = name.replace(/\\s/g, \"-\").toLowerCase();\n return Symbol.for(`autometa:container:${hash}`);\n}\n"],"mappings":"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","names":["metadata"]} | ||
| {"version":3,"sources":["../src/types.ts","../src/container.ts","../src/decorators.ts"],"names":["Scope"],"mappings":"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","sourcesContent":["/**\n * Core types for the dependency injection framework\n */\n\n// Constructor type for classes\nexport interface Constructor<T = object> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- constructors often declare specific dependency types; we need a permissive arg signature\n new (...args: any[]): T;\n name?: string;\n prototype?: T;\n}\n\n// Token type for symbolic references\nexport type Token<T = object> = symbol & { __type?: T };\n\n// Identifier can be a constructor, token, or string\nexport type Identifier<T = object> = Constructor<T> | Token<T> | string;\n\n// Scope definitions\nexport enum Scope {\n SINGLETON = \"singleton\",\n TRANSIENT = \"transient\",\n REQUEST = \"request\",\n SESSION = \"session\",\n SCENARIO = \"scenario\",\n}\n\n// Registration options\nexport type PropertyInjectionDescriptor =\n | Identifier\n | {\n readonly token: Identifier;\n readonly lazy?: boolean;\n };\n\nexport type PropertyInjectionMap = {\n readonly [Key in string | number | symbol]?: PropertyInjectionDescriptor;\n};\n\nexport interface RegistrationOptions {\n scope?: Scope;\n tags?: string[];\n factory?: boolean;\n deps?: Identifier[];\n props?: PropertyDep[] | PropertyInjectionMap;\n}\n\n// Binding types\nexport interface ClassBinding<T = object> {\n type: \"class\";\n target: Constructor<T>;\n scope: Scope;\n tags: string[];\n deps?: Identifier[];\n props?: PropertyDep[];\n}\n\nexport interface ValueBinding<T = object> {\n type: \"value\";\n value: T;\n scope: Scope;\n tags: string[];\n}\n\nexport interface FactoryBinding<T = object> {\n type: \"factory\";\n factory: (container: IContainer) => T;\n scope: Scope;\n tags: string[];\n}\n\nexport interface TokenBinding<T = object> {\n type: \"token\";\n token: Token<T>;\n target: Constructor<T> | ((container: IContainer) => T);\n scope: Scope;\n tags: string[];\n}\n\nexport type Binding<T = object> =\n | ClassBinding<T>\n | ValueBinding<T>\n | FactoryBinding<T>\n | TokenBinding<T>;\n\n// Resolution context for circular dependency detection\nexport interface ResolutionContext {\n path: Set<Identifier>;\n depth: number;\n maxDepth: number;\n}\n\n// Container interface\nexport interface IContainer {\n // Registration methods\n register<T>(\n identifier: Identifier<T>,\n binding: Partial<Binding<T>>\n ): IContainer;\n registerClass<T>(\n target: Constructor<T>,\n options?: RegistrationOptions\n ): IContainer;\n registerValue<T>(\n identifier: Identifier<T>,\n value: T,\n options?: RegistrationOptions\n ): IContainer;\n registerFactory<T>(\n identifier: Identifier<T>,\n factory: (container: IContainer) => T,\n options?: RegistrationOptions\n ): IContainer;\n registerToken<T>(\n token: Token<T>,\n target: Constructor<T> | ((container: IContainer) => T),\n options?: RegistrationOptions\n ): IContainer;\n\n // Resolution methods\n resolve<T>(identifier: Identifier<T>): T;\n resolveAll<T>(identifier: Identifier<T>): T[];\n tryResolve<T>(identifier: Identifier<T>): T | undefined;\n\n // Introspection\n isRegistered<T>(identifier: Identifier<T>): boolean;\n getBinding<T>(identifier: Identifier<T>): Binding<T> | undefined;\n\n // Container hierarchy\n createChild(): IContainer;\n parent?: IContainer;\n\n // Lifecycle\n dispose(): Promise<void>;\n\n // Tagged resolution\n resolveByTag<T>(tag: string): T[];\n}\n\n// Dependency injection errors\nexport class DependencyInjectionError extends Error {\n constructor(\n message: string,\n public readonly identifier?: Identifier,\n public readonly context?: ResolutionContext\n ) {\n super(message);\n this.name = \"DependencyInjectionError\";\n }\n}\n\nexport class CircularDependencyError extends DependencyInjectionError {\n constructor(identifier: Identifier, context: ResolutionContext) {\n const identifierName = getIdentifierName(identifier);\n const pathNames = [...context.path].map(getIdentifierName);\n const path = pathNames.join(\" -> \");\n\n super(\n `Circular dependency detected: ${path} -> ${identifierName}`,\n identifier,\n context\n );\n this.name = \"CircularDependencyError\";\n }\n}\n\nexport class UnregisteredDependencyError extends DependencyInjectionError {\n constructor(identifier: Identifier) {\n const name = getIdentifierName(identifier);\n\n super(`No registration found for identifier: ${name}`, identifier);\n this.name = \"UnregisteredDependencyError\";\n }\n}\n\n// Helper function to get identifier name\nexport function getIdentifierName(identifier: Identifier): string {\n if (typeof identifier === \"string\") {\n return identifier;\n }\n if (typeof identifier === \"symbol\") {\n return identifier.toString();\n }\n return identifier.name || \"anonymous\";\n}\n\n// Helper to create tokens\nexport function createToken<T>(description?: string): Token<T> {\n return Symbol(description) as Token<T>;\n}\n\nexport interface PropertyDep {\n property: string | symbol;\n token: Identifier;\n lazy?: boolean;\n}\n","/**\n * Core container implementation for dependency injection\n */\n\nimport {\n IContainer,\n Identifier,\n Constructor,\n Token,\n Binding,\n ClassBinding,\n ValueBinding,\n FactoryBinding,\n TokenBinding,\n Scope,\n RegistrationOptions,\n PropertyDep,\n PropertyInjectionDescriptor,\n PropertyInjectionMap,\n ResolutionContext,\n CircularDependencyError,\n UnregisteredDependencyError,\n} from \"./types\";\n\nexport class Container implements IContainer {\n private readonly bindings = new Map<Identifier, Binding>();\n private readonly instances = new Map<Identifier, unknown>();\n private readonly scopedInstances = new Map<\n string,\n Map<Identifier, unknown>\n >();\n private readonly children = new Set<Container>();\n declare public readonly parent?: IContainer;\n\n constructor(parent?: IContainer) {\n if (parent !== undefined) {\n this.parent = parent;\n }\n }\n\n // Registration methods\n register<T>(\n identifier: Identifier<T>,\n binding: Partial<Binding<T>>\n ): IContainer {\n const fullBinding: Binding<T> = {\n scope: Scope.TRANSIENT,\n tags: [],\n ...binding,\n } as Binding<T>;\n\n this.bindings.set(identifier as Identifier, fullBinding as Binding);\n return this;\n }\n\n registerClass<T>(\n target: Constructor<T>,\n options: RegistrationOptions = {}\n ): IContainer {\n const propertyDeps = this.normalizePropertyOptions(options.props);\n const binding: ClassBinding<T> = {\n type: \"class\",\n target,\n scope: options.scope || Scope.TRANSIENT,\n tags: options.tags || [],\n deps: options.deps || [],\n ...(propertyDeps.length > 0 ? { props: propertyDeps } : {}),\n };\n\n this.bindings.set(target as Identifier, binding as Binding);\n return this;\n }\n\n registerValue<T>(\n identifier: Identifier<T>,\n value: T,\n options: RegistrationOptions = {}\n ): IContainer {\n const binding: ValueBinding<T> = {\n type: \"value\",\n value,\n scope: options.scope || Scope.SINGLETON,\n tags: options.tags || [],\n };\n\n this.bindings.set(identifier as Identifier, binding as Binding);\n return this;\n }\n\n registerFactory<T>(\n identifier: Identifier<T>,\n factory: (container: IContainer) => T,\n options: RegistrationOptions = {}\n ): IContainer {\n const binding: FactoryBinding<T> = {\n type: \"factory\",\n factory,\n scope: options.scope || Scope.TRANSIENT,\n tags: options.tags || [],\n };\n\n this.bindings.set(identifier as Identifier, binding as Binding);\n return this;\n }\n\n registerToken<T>(\n token: Token<T>,\n target: Constructor<T> | ((container: IContainer) => T),\n options: RegistrationOptions = {}\n ): IContainer {\n const binding: TokenBinding<T> = {\n type: \"token\",\n token,\n target,\n scope: options.scope || Scope.TRANSIENT,\n tags: options.tags || [],\n };\n\n this.bindings.set(token as Identifier, binding as Binding);\n return this;\n }\n\n // Resolution methods\n resolve<T>(identifier: Identifier<T>): T {\n const context: ResolutionContext = {\n path: new Set(),\n depth: 0,\n maxDepth: 50,\n };\n\n return this.resolveWithContext(identifier as Identifier, context) as T;\n }\n\n resolveAll<T>(identifier: Identifier<T>): T[] {\n const results: T[] = [];\n\n // Collect from this container\n for (const [key, binding] of this.bindings.entries()) {\n if (\n this.identifierMatches(key, identifier as Identifier) ||\n this.bindingHasMatchingTag(binding, identifier as Identifier)\n ) {\n try {\n const instance = this.resolve(key as Identifier<T>);\n results.push(instance);\n } catch {\n // Skip failed resolutions\n }\n }\n }\n\n // Collect from parent\n if (this.parent) {\n results.push(...this.parent.resolveAll(identifier));\n }\n\n return results;\n }\n\n tryResolve<T>(identifier: Identifier<T>): T | undefined {\n try {\n return this.resolve(identifier);\n } catch {\n return undefined;\n }\n }\n\n // Introspection\n isRegistered<T>(identifier: Identifier<T>): boolean {\n return (\n this.bindings.has(identifier as Identifier) ||\n (this.parent?.isRegistered(identifier) ?? false)\n );\n }\n\n getBinding<T>(identifier: Identifier<T>): Binding<T> | undefined {\n const binding = this.bindings.get(identifier as Identifier) as\n | Binding<T>\n | undefined;\n return binding || this.parent?.getBinding(identifier);\n }\n\n // Container hierarchy\n createChild(): IContainer {\n const child = new Container(this);\n this.children.add(child);\n return child;\n }\n\n // Tagged resolution\n resolveByTag<T>(tag: string): T[] {\n const results: T[] = [];\n\n for (const [identifier, binding] of this.bindings.entries()) {\n if (binding.tags.includes(tag)) {\n try {\n const instance = this.resolve(identifier as Identifier<T>);\n results.push(instance);\n } catch {\n // Skip failed resolutions\n }\n }\n }\n\n if (this.parent) {\n results.push(...this.parent.resolveByTag<T>(tag));\n }\n\n return results;\n }\n\n // Lifecycle\n async dispose(): Promise<void> {\n // Dispose children first\n await Promise.all([...this.children].map((child) => child.dispose()));\n this.children.clear();\n\n // Dispose instances that implement disposal\n for (const instance of this.instances.values()) {\n if (instance && typeof instance === \"object\" && \"dispose\" in instance) {\n const disposable = instance as { dispose(): Promise<void> | void };\n await disposable.dispose();\n }\n }\n\n // Clear all caches\n this.instances.clear();\n this.scopedInstances.clear();\n this.bindings.clear();\n }\n\n // Private resolution implementation\n private resolveWithContext<T>(\n identifier: Identifier,\n context: ResolutionContext\n ): T {\n // Check for circular dependencies\n if (context.path.has(identifier)) {\n throw new CircularDependencyError(identifier, context);\n }\n\n if (context.depth >= context.maxDepth) {\n throw new Error(\n `Maximum resolution depth exceeded (${context.maxDepth})`\n );\n }\n\n // Get binding first to check scope\n const binding = this.getBindingInternal(identifier);\n if (!binding) {\n throw new UnregisteredDependencyError(identifier);\n }\n\n // Check for cached instances based on scope\n if (binding.scope === Scope.SINGLETON && this.instances.has(identifier)) {\n return this.instances.get(identifier) as T;\n }\n\n // Check scoped cache for other scopes\n const scopedCache = this.getScopedCache(binding.scope);\n if (scopedCache?.has(identifier)) {\n return scopedCache.get(identifier) as T;\n }\n\n // Add to resolution path\n context.path.add(identifier);\n context.depth++;\n\n try {\n // Create instance\n const instance = this.createInstance(binding, context) as T;\n\n // Cache based on scope\n if (binding.scope === Scope.SINGLETON) {\n this.instances.set(identifier, instance);\n } else if (scopedCache) {\n scopedCache.set(identifier, instance);\n }\n\n return instance;\n } finally {\n // Clean up resolution path\n context.path.delete(identifier);\n context.depth--;\n }\n }\n\n private getBindingInternal<T>(\n identifier: Identifier<T>\n ): Binding<T> | undefined {\n const binding = this.bindings.get(identifier as Identifier);\n return (binding ||\n (this.parent as Container)?.getBindingInternal?.(identifier)) as\n | Binding<T>\n | undefined;\n }\n\n private createInstance<T>(\n binding: Binding<T>,\n context: ResolutionContext\n ): T {\n switch (binding.type) {\n case \"value\":\n return binding.value;\n\n case \"factory\": {\n // Create a context-aware container for factories\n const contextAwareContainer = this.createContextAwareContainer(context);\n return binding.factory(contextAwareContainer);\n }\n\n case \"class\":\n return this.instantiateClass(\n binding.target as unknown as Constructor<T & object>,\n context\n ) as T;\n\n case \"token\": {\n if (typeof binding.target === \"function\") {\n if (this.isConstructor(binding.target)) {\n return this.instantiateClass(\n binding.target as Constructor<T & object>,\n context\n );\n } else {\n // Create a context-aware container for token factories\n const contextAwareContainer =\n this.createContextAwareContainer(context);\n return (binding.target as (container: IContainer) => T)(\n contextAwareContainer\n );\n }\n }\n throw new Error(\n `Invalid token binding target for ${binding.token.toString()}`\n );\n }\n\n default:\n throw new Error(`Unknown binding type: ${(binding as Binding).type}`);\n }\n }\n\n private instantiateClass<T extends object>(\n constructor: Constructor<T>,\n context: ResolutionContext\n ): T {\n const binding = this.getBindingInternal(constructor) as ClassBinding<T>;\n if (!binding || binding.type !== \"class\") {\n throw new Error(\n `No class binding found for constructor: ${constructor.name}`\n );\n }\n\n // Resolve constructor dependencies from the 'deps' array\n const constructorArgs = (binding.deps || []).map((dep) => {\n return this.resolveWithContext(dep, context);\n });\n\n // Create the instance\n const instance = new constructor(...constructorArgs);\n\n // Resolve and set property dependencies from the 'props' array\n if (binding.props) {\n for (const prop of binding.props) {\n if (prop.lazy) {\n Object.defineProperty(instance, prop.property, {\n configurable: true,\n enumerable: true,\n get: () => {\n const resolved = this.resolveWithContext(prop.token, context);\n Object.defineProperty(instance, prop.property, {\n configurable: true,\n enumerable: true,\n writable: true,\n value: resolved,\n });\n return resolved;\n },\n });\n continue;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (instance as any)[prop.property] = this.resolveWithContext(\n prop.token,\n context\n );\n }\n }\n\n return instance;\n }\n\n private isConstructor(fn: unknown): fn is Constructor {\n return typeof fn === \"function\" && fn.prototype !== undefined;\n }\n\n private createContextAwareContainer(context: ResolutionContext): IContainer {\n return {\n register: <T>(identifier: Identifier<T>, binding: Partial<Binding<T>>) =>\n this.register(identifier, binding),\n registerClass: <T>(\n target: Constructor<T>,\n options?: RegistrationOptions\n ) => this.registerClass(target, options),\n registerValue: <T>(\n identifier: Identifier<T>,\n value: T,\n options?: RegistrationOptions\n ) => this.registerValue(identifier, value, options),\n registerFactory: <T>(\n identifier: Identifier<T>,\n factory: (container: IContainer) => T,\n options?: RegistrationOptions\n ) => this.registerFactory(identifier, factory, options),\n registerToken: <T>(\n token: Token<T>,\n target: Constructor<T> | ((container: IContainer) => T),\n options?: RegistrationOptions\n ) => this.registerToken(token, target, options),\n\n resolve: <T>(identifier: Identifier<T>): T => {\n return this.resolveWithContext(identifier as Identifier, context) as T;\n },\n\n resolveAll: <T>(identifier: Identifier<T>) => this.resolveAll(identifier),\n tryResolve: <T>(identifier: Identifier<T>) => this.tryResolve(identifier),\n isRegistered: <T>(identifier: Identifier<T>) =>\n this.isRegistered(identifier),\n getBinding: <T>(identifier: Identifier<T>) => this.getBinding(identifier),\n createChild: () => this.createChild(),\n resolveByTag: <T>(tag: string) => this.resolveByTag<T>(tag),\n dispose: () => this.dispose(),\n };\n }\n\n private getScopedCache(scope: Scope): Map<Identifier, unknown> | undefined {\n if (scope === Scope.SINGLETON || scope === Scope.TRANSIENT) {\n return undefined; // Singletons use global cache, transients are never cached\n }\n\n if (!this.scopedInstances.has(scope)) {\n this.scopedInstances.set(scope, new Map());\n }\n\n return this.scopedInstances.get(scope);\n }\n\n private identifierMatches(a: Identifier, b: Identifier): boolean {\n return a === b;\n }\n\n private bindingHasMatchingTag(\n binding: Binding,\n identifier: Identifier\n ): boolean {\n if (typeof identifier !== \"string\") {\n return false;\n }\n return binding.tags.includes(identifier);\n }\n\n private normalizePropertyOptions(\n props?: RegistrationOptions[\"props\"]\n ): PropertyDep[] {\n if (!props) {\n return [];\n }\n\n if (Array.isArray(props)) {\n return props.map((prop) => ({ ...prop }));\n }\n\n const map = props as PropertyInjectionMap;\n const normalized: PropertyDep[] = [];\n const descriptorMap = map as Record<PropertyKey, PropertyInjectionDescriptor>;\n\n for (const key of Reflect.ownKeys(descriptorMap)) {\n const descriptor = descriptorMap[key as PropertyKey];\n if (!descriptor) {\n continue;\n }\n\n if (!this.isPropertyInjectionObject(descriptor)) {\n normalized.push({\n property: key,\n token: descriptor as Identifier,\n });\n continue;\n }\n\n normalized.push({\n property: key,\n token: descriptor.token,\n ...(descriptor.lazy ? { lazy: descriptor.lazy } : {}),\n });\n }\n\n return normalized;\n }\n\n private isPropertyInjectionObject(\n descriptor: PropertyInjectionDescriptor\n ): descriptor is { token: Identifier; lazy?: boolean } {\n return typeof descriptor === \"object\" && descriptor !== null && \"token\" in descriptor;\n }\n}\n\n// Export convenience functions\nexport function createContainer(): IContainer {\n return new Container();\n}\n\nexport function createChildContainer(parent: IContainer): IContainer {\n return parent.createChild();\n}","import \"reflect-metadata\";\nimport { Scope } from \"./types\";\nimport type { Identifier, PropertyDep, IContainer } from \"./types\";\n\n// Define unique keys for storing metadata via reflect-metadata\nconst INJECT_PARAM_KEY = \"autometa:inject_param\";\nconst INJECT_PROP_KEY = \"autometa:inject_prop\";\n\nexport interface InjectableOptions {\n scope?: Scope;\n deps?: Identifier[];\n}\n\ntype InjectableTarget = new (...args: unknown[]) => object;\n\nfunction ensureInjectableTarget(value: unknown, decorator: string): asserts value is InjectableTarget {\n if (typeof value !== \"function\") {\n throw new TypeError(\n `[${decorator}] can only be used on classes. Received ${typeof value}.`\n );\n }\n}\n\n/**\n * Creates a set of decorators bound to a specific container instance.\n * This factory pattern ensures the decorators are decoupled from a global\n * container and can be used with multiple, separate containers.\n * @param container The container instance to which the decorators will register classes.\n */\nexport function createDecorators(container: IContainer) {\n function registerPropertyDependency(\n target: object,\n propertyKey: string | symbol,\n token: Identifier,\n lazy: boolean\n ): void {\n const existing =\n (Reflect.getMetadata(INJECT_PROP_KEY, target) as PropertyDep[] | undefined) || [];\n const filtered = existing.filter((dep) => dep.property !== propertyKey);\n filtered.push({ property: propertyKey, token, lazy });\n Reflect.defineMetadata(INJECT_PROP_KEY, filtered, target);\n }\n\n /**\n * A class decorator that marks a class as available for injection.\n * It gathers all dependency metadata from `@Inject` decorators and\n * `reflect-metadata` and registers the class with the container.\n */\n function Injectable(options: InjectableOptions = {}): ClassDecorator {\n return (target) => {\n ensureInjectableTarget(target, \"Injectable\");\n const ctor = target;\n // --- Constructor Injection ---\n const deps = options.deps || [];\n\n // --- Property Injection ---\n const props =\n (Reflect.getMetadata(INJECT_PROP_KEY, ctor.prototype) as PropertyDep[] | undefined) || [];\n\n // --- Registration ---\n // The container's `register` method expects an identifier and a binding object.\n const identifier = ctor as unknown as Identifier;\n const binding = {\n type: \"class\" as const,\n target: ctor,\n scope: options.scope || Scope.TRANSIENT,\n tags: [],\n deps,\n props,\n };\n\n container.register(identifier, binding);\n };\n }\n\n /**\n * A decorator that can be used on constructor parameters or class properties\n * to specify a dependency token.\n * @param token The token representing the dependency to inject.\n */\n function Inject(token: Identifier): PropertyDecorator & ParameterDecorator {\n return ((...args: [object, string | symbol, number?]) => {\n const [target, propertyKey, parameterIndex] = args;\n\n if (typeof parameterIndex === \"number\") {\n ensureInjectableTarget(target, \"Inject parameter\");\n const ctor = target;\n const paramTokens =\n (Reflect.getMetadata(INJECT_PARAM_KEY, ctor) as Map<number, Identifier> | undefined) ||\n new Map<number, Identifier>();\n paramTokens.set(parameterIndex, token);\n Reflect.defineMetadata(INJECT_PARAM_KEY, paramTokens, ctor);\n return;\n }\n\n registerPropertyDependency(target, propertyKey, token, false);\n }) as PropertyDecorator & ParameterDecorator;\n }\n\n function LazyInject(token: Identifier): PropertyDecorator {\n return (target, propertyKey) => {\n registerPropertyDependency(target, propertyKey, token, true);\n };\n }\n\n return { Injectable, Inject, LazyInject };\n}\n"]} |
+13
-11
| { | ||
| "name": "@autometa/injection", | ||
| "version": "0.1.5", | ||
| "version": "1.0.0-rc.0", | ||
| "description": "", | ||
| "type": "module", | ||
| "main": "dist/index.js", | ||
| "module": "dist/esm/index.js", | ||
| "main": "dist/index.cjs", | ||
| "module": "dist/index.js", | ||
| "types": "dist/index.d.ts", | ||
| "exports": { | ||
| "import": "./dist/esm/index.js", | ||
| "require": "./dist/index.js", | ||
| "default": "./dist/esm/index.js", | ||
| "import": "./dist/index.js", | ||
| "require": "./dist/index.cjs", | ||
| "default": "./dist/index.js", | ||
| "types": "./dist/index.d.ts" | ||
@@ -28,10 +28,11 @@ }, | ||
| "vitest": "^1.4.0", | ||
| "tsconfig": "0.7.0", | ||
| "eslint-config-custom": "0.6.0" | ||
| "eslint-config-custom": "0.6.0", | ||
| "tsup-config": "0.1.0", | ||
| "tsconfig": "0.7.0" | ||
| }, | ||
| "dependencies": { | ||
| "@autometa/types": "^0.4.1" | ||
| "reflect-metadata": "^0.1.13" | ||
| }, | ||
| "scripts": { | ||
| "test": "vitest run --passWithNoTests", | ||
| "test": "vitest run src/__tests__/integration/mixed-injection.test.ts", | ||
| "prettify": "prettier --config .prettierrc 'src/**/*.ts' --write", | ||
@@ -41,5 +42,6 @@ "lint": "eslint . --max-warnings 0", | ||
| "clean": "rimraf dist", | ||
| "build": "tsup", | ||
| "build": "tsup && pnpm run build:types", | ||
| "build:types": "rimraf tsconfig.types.tsbuildinfo && tsc --build tsconfig.types.json", | ||
| "build:watch": "tsup --watch" | ||
| } | ||
| } |
+5
-12
@@ -1,14 +0,7 @@ | ||
| import { defineConfig } from "tsup"; | ||
| import { createTsupConfig } from "tsup-config"; | ||
| export default defineConfig({ | ||
| clean: true, // clean up the dist folder | ||
| format: ["cjs", "esm"], // generate cjs and esm files | ||
| dts: true, | ||
| sourcemap: true, // generate sourcemaps | ||
| skipNodeModulesBundle: true, | ||
| entryPoints: ["src/index.ts"], | ||
| target: "es2020", | ||
| outDir: "dist", | ||
| legacyOutput: true, | ||
| external: ["dist"], | ||
| export default createTsupConfig({ | ||
| tsconfig: "./tsconfig.bundle.json", | ||
| dts: false, | ||
| external: ["reflect-metadata"], | ||
| }); |
| > @autometa/injection@0.1.3 lint:fix /Users/ben.aherne/Documents/GitHub/autometa/packages/injection | ||
| > eslint . --fix "--max-warnings=0" | ||
| > @autometa/injection@0.1.3 prettify /Users/ben.aherne/Documents/GitHub/autometa/packages/injection | ||
| > prettier --config .prettierrc 'src/**/*.ts' --write | ||
| [error] Invalid configuration file `src/constructor.ts`: ENOENT: no such file or directory, open '/Users/ben.aherne/Documents/GitHub/autometa/packages/injection/.prettierrc' | ||
| ELIFECYCLE Command failed with exit code 2. |
| var __accessCheck = (obj, member, msg) => { | ||
| if (!member.has(obj)) | ||
| throw TypeError("Cannot " + msg); | ||
| }; | ||
| var __privateGet = (obj, member, getter) => { | ||
| __accessCheck(obj, member, "read from private field"); | ||
| return getter ? getter.call(obj) : member.get(obj); | ||
| }; | ||
| var __privateAdd = (obj, member, value) => { | ||
| if (member.has(obj)) | ||
| throw TypeError("Cannot add the same private member more than once"); | ||
| member instanceof WeakSet ? member.add(obj) : member.set(obj, value); | ||
| }; | ||
| var __privateMethod = (obj, member, method) => { | ||
| __accessCheck(obj, member, "access private method"); | ||
| return method; | ||
| }; | ||
| // src/symbol.ts | ||
| var META_DATA = Symbol("autometa:meta-data"); | ||
| var CONSTRUCTOR = Symbol("autometa:meta-data:constructor"); | ||
| var AutometaSymbol = { | ||
| META_DATA, | ||
| CONSTRUCTOR | ||
| }; | ||
| // src/metadata.ts | ||
| function metadata(target) { | ||
| const withMetaData = target; | ||
| if (!(AutometaSymbol.META_DATA in target)) { | ||
| defineNonEnumerable(target, AutometaSymbol.META_DATA, {}); | ||
| } | ||
| const metadata2 = withMetaData[AutometaSymbol.META_DATA]; | ||
| return { | ||
| set: (info, override = true) => { | ||
| if (!metadata2[info.key]) { | ||
| defineEnumerable(metadata2, info.key, info); | ||
| return; | ||
| } | ||
| if (override) { | ||
| defineEnumerable(metadata2, info.key, info); | ||
| return; | ||
| } | ||
| }, | ||
| update: (key, updater) => { | ||
| const current = metadata2[key]; | ||
| if (!current) { | ||
| const name = "name" in target ? target.name : target.constructor.name; | ||
| const err = `Cannot create a constructor for ${name} as no metadata has been created for it. Try decorating it with '@Fixture'`; | ||
| throw new Error(err); | ||
| } | ||
| updater(current); | ||
| }, | ||
| custom: (key, value, override = true) => { | ||
| const md = withMetaData; | ||
| if (!md[key] || override) { | ||
| defineEnumerable(target, key, value); | ||
| } | ||
| return md[key]; | ||
| }, | ||
| getCustom: (key) => { | ||
| const md = withMetaData; | ||
| return md[key]; | ||
| }, | ||
| hasCustom: (key) => { | ||
| const md = withMetaData; | ||
| return md[key]; | ||
| }, | ||
| get: (key) => { | ||
| return metadata2[key]; | ||
| }, | ||
| get keys() { | ||
| return Object.keys(metadata2); | ||
| } | ||
| }; | ||
| } | ||
| function defineNonEnumerable(target, key, value) { | ||
| Object.defineProperty(target, key, { | ||
| enumerable: false, | ||
| configurable: true, | ||
| writable: false, | ||
| value | ||
| }); | ||
| } | ||
| function defineEnumerable(target, key, value) { | ||
| Object.defineProperty(target, key, { | ||
| enumerable: true, | ||
| configurable: true, | ||
| writable: true, | ||
| value | ||
| }); | ||
| } | ||
| // src/metadata-registry.ts | ||
| var ScopeRegistry = /* @__PURE__ */ new Map(); | ||
| var TokenTypeRegistry = /* @__PURE__ */ new Map(); | ||
| var SingletonRegistry = /* @__PURE__ */ new Map(); | ||
| var ContainerContextRegistry = /* @__PURE__ */ new Map(); | ||
| function registerSingleton(target, instance) { | ||
| if (SingletonRegistry.has(target)) { | ||
| throw new Error(`Singleton already registered for ${target.name}`); | ||
| } | ||
| SingletonRegistry.set(target, instance); | ||
| } | ||
| function getSingleton(target) { | ||
| return SingletonRegistry.get(target); | ||
| } | ||
| function hasSingleton(target) { | ||
| return SingletonRegistry.has(target); | ||
| } | ||
| function registerScope(target, scope) { | ||
| ScopeRegistry.set(target, scope); | ||
| } | ||
| function getScope(target) { | ||
| return ScopeRegistry.get(target); | ||
| } | ||
| function hasScope(target) { | ||
| return ScopeRegistry.has(target); | ||
| } | ||
| function registerContainerContext(context, target, instance) { | ||
| if (!ContainerContextRegistry.has(context)) { | ||
| ContainerContextRegistry.set(context, /* @__PURE__ */ new Map()); | ||
| } | ||
| ContainerContextRegistry.get(context)?.set(target, instance); | ||
| return instance; | ||
| } | ||
| function getContainerContexts(context, target) { | ||
| if (!ContainerContextRegistry.has(context)) { | ||
| ContainerContextRegistry.set(context, /* @__PURE__ */ new Map()); | ||
| } | ||
| return ContainerContextRegistry.get(context)?.get(target); | ||
| } | ||
| function hasContainerContext(context, target) { | ||
| if (!ContainerContextRegistry.has(context)) { | ||
| ContainerContextRegistry.set(context, /* @__PURE__ */ new Map()); | ||
| } | ||
| return ContainerContextRegistry.get(context)?.has(target) ?? false; | ||
| } | ||
| function registerTypeToken(token, target) { | ||
| TokenTypeRegistry.set(token, target); | ||
| } | ||
| function getTypeToken(token) { | ||
| return TokenTypeRegistry.get(token); | ||
| } | ||
| function hasToken(token) { | ||
| return TokenTypeRegistry.has(token); | ||
| } | ||
| function clearRegistries() { | ||
| ScopeRegistry.clear(); | ||
| SingletonRegistry.clear(); | ||
| ContainerContextRegistry.clear(); | ||
| TokenTypeRegistry.clear(); | ||
| } | ||
| // src/scope.enum.ts | ||
| var INJECTION_SCOPE = { | ||
| SINGLETON: 0, | ||
| TRANSIENT: 1, | ||
| CACHED: 2 | ||
| }; | ||
| // src/fixture.ts | ||
| function Fixture(arg) { | ||
| if (arg !== void 0 && typeof arg !== "number") { | ||
| registerScope(arg, INJECTION_SCOPE.CACHED); | ||
| return; | ||
| } | ||
| return (target) => { | ||
| registerScope(target, arg ?? INJECTION_SCOPE.CACHED); | ||
| }; | ||
| } | ||
| // src/get-constructor.ts | ||
| function getConstructor(target) { | ||
| if (target && "constructor" in target) { | ||
| return target.constructor; | ||
| } | ||
| throw new Error(`Cannot get constructor for ${target}`); | ||
| } | ||
| // src/inject.ts | ||
| var Inject = { | ||
| /** | ||
| * Decorator factory which defines the Type of the property to inject. This | ||
| * information will be used at class construction to automatically inject | ||
| * that property with the appropriate type. If the type is class which | ||
| * has not been marked as a `Fixture` then the dependency will be treated | ||
| * as cached - meaning once created, the same instance will be used for | ||
| * all subsequent injections. However the target class can be | ||
| * defined as a `Singleton` or `Transient` fixture to override this behavior. | ||
| */ | ||
| class: (cls) => { | ||
| return function(target, propertyKey) { | ||
| metadata(getConstructor(target)).set({ | ||
| key: propertyKey, | ||
| class: cls | ||
| }); | ||
| }; | ||
| }, | ||
| /** | ||
| * Decorator factory which defines a factory function that will | ||
| * be used to inject the property. The factory function will be | ||
| * called once per injection, and it's return value will be | ||
| * used as the value of the property. Currently only synchronous | ||
| * factory functions are supported. | ||
| * @param factory | ||
| * @returns | ||
| */ | ||
| factory: (factory) => { | ||
| return function(target, propertyKey) { | ||
| metadata(getConstructor(target)).set({ | ||
| key: propertyKey, | ||
| factory | ||
| }); | ||
| }; | ||
| }, | ||
| /** | ||
| * Decorator factory which defines a value to inject into the property. | ||
| * The value will be injected directly into the property without any | ||
| * further processing. Equivalent to simply assigning the value to the | ||
| * property. | ||
| * | ||
| * @param value | ||
| * @returns | ||
| */ | ||
| value: (value) => { | ||
| return function(target, propertyKey) { | ||
| metadata(getConstructor(target)).set({ | ||
| key: propertyKey, | ||
| value | ||
| }); | ||
| }; | ||
| } | ||
| }; | ||
| // src/token.ts | ||
| var InjectionToken = class { | ||
| constructor(name) { | ||
| this.name = name; | ||
| } | ||
| }; | ||
| var tokenMap = /* @__PURE__ */ new Map(); | ||
| function Token(name) { | ||
| if (!tokenMap.has(name)) { | ||
| const token = new InjectionToken(name); | ||
| tokenMap.set(name, token); | ||
| } | ||
| return tokenMap.get(name); | ||
| } | ||
| var DisposeMethod = Symbol("DisposeMethod"); | ||
| var DisposeGlobalMethod = Symbol("DisposeGlobalMethod"); | ||
| function DisposeTagFilter(tagFilter) { | ||
| return function(_, __, descriptor) { | ||
| const original = descriptor.value; | ||
| descriptor.value = function(tags, isTagMatch) { | ||
| if (isTagMatch(tags, tagFilter)) { | ||
| return original.apply(this); | ||
| } | ||
| }; | ||
| }; | ||
| } | ||
| // src/constructor.ts | ||
| function Constructor(...args) { | ||
| return function(target) { | ||
| metadata(target).custom(AutometaSymbol.CONSTRUCTOR, args); | ||
| }; | ||
| } | ||
| // src/container.ts | ||
| var _disposables, _globalDisposables, _throwOnSingletonTokenClash, throwOnSingletonTokenClash_fn, _assembleTarget, assembleTarget_fn, _getConstructorArgs, getConstructorArgs_fn; | ||
| var Container = class { | ||
| constructor(reference) { | ||
| this.reference = reference; | ||
| __privateAdd(this, _throwOnSingletonTokenClash); | ||
| __privateAdd(this, _assembleTarget); | ||
| __privateAdd(this, _getConstructorArgs); | ||
| __privateAdd(this, _disposables, /* @__PURE__ */ new Set()); | ||
| __privateAdd(this, _globalDisposables, /* @__PURE__ */ new Set()); | ||
| } | ||
| registerSingleton(token, type) { | ||
| registerScope(token, INJECTION_SCOPE.SINGLETON); | ||
| if (token instanceof InjectionToken && type) { | ||
| registerTypeToken(token, type); | ||
| } | ||
| return this; | ||
| } | ||
| registerCached(token, type) { | ||
| registerScope(token, INJECTION_SCOPE.CACHED); | ||
| if (token instanceof InjectionToken && type) { | ||
| registerTypeToken(token, type); | ||
| } | ||
| return this; | ||
| } | ||
| registerTransient(target, type) { | ||
| __privateMethod(this, _throwOnSingletonTokenClash, throwOnSingletonTokenClash_fn).call(this, target); | ||
| registerScope(target, INJECTION_SCOPE.TRANSIENT); | ||
| if (target instanceof InjectionToken && type) { | ||
| registerTypeToken(target, type); | ||
| } | ||
| return this; | ||
| } | ||
| registerSingletonValue(identifier, value) { | ||
| registerSingleton(Token(identifier), value); | ||
| return this; | ||
| } | ||
| registerCachedValue(identifier, value) { | ||
| __privateMethod(this, _throwOnSingletonTokenClash, throwOnSingletonTokenClash_fn).call(this, Token(identifier)); | ||
| registerScope(Token(identifier), INJECTION_SCOPE.CACHED); | ||
| registerContainerContext(this.reference, Token(identifier), value); | ||
| return this; | ||
| } | ||
| get(target) { | ||
| target = getRealTarget(target); | ||
| if (hasSingleton(target)) { | ||
| return getSingleton(target); | ||
| } | ||
| const scope = getScope(target); | ||
| if (!hasScope(target)) { | ||
| registerScope(target, INJECTION_SCOPE.CACHED); | ||
| } | ||
| const type = getTypeToken(target) ?? target; | ||
| if (scope === INJECTION_SCOPE.SINGLETON) { | ||
| const instance = __privateMethod(this, _assembleTarget, assembleTarget_fn).call(this, type); | ||
| registerSingleton(target, instance); | ||
| return instance; | ||
| } | ||
| if (scope === INJECTION_SCOPE.CACHED) { | ||
| if (hasContainerContext(this.reference, target)) { | ||
| return getContainerContexts(this.reference, target); | ||
| } | ||
| const assembled = __privateMethod(this, _assembleTarget, assembleTarget_fn).call(this, type); | ||
| return registerContainerContext(this.reference, target, assembled); | ||
| } | ||
| return __privateMethod(this, _assembleTarget, assembleTarget_fn).call(this, type); | ||
| } | ||
| async disposeAll(tags, isTagsMatch) { | ||
| for (const disposable of __privateGet(this, _disposables)) { | ||
| await disposable[DisposeMethod](tags, isTagsMatch); | ||
| } | ||
| } | ||
| async disposeGlobal(tags, isTagsMatch) { | ||
| for (const disposable of __privateGet(this, _globalDisposables)) { | ||
| await disposable[DisposeMethod](tags, isTagsMatch); | ||
| } | ||
| } | ||
| }; | ||
| _disposables = new WeakMap(); | ||
| _globalDisposables = new WeakMap(); | ||
| _throwOnSingletonTokenClash = new WeakSet(); | ||
| throwOnSingletonTokenClash_fn = function(token) { | ||
| if (hasSingleton(token)) { | ||
| throw new Error( | ||
| `Singleton token ${token.name} is already registered. Use a different token or register a cached dependency` | ||
| ); | ||
| } | ||
| }; | ||
| _assembleTarget = new WeakSet(); | ||
| assembleTarget_fn = function(target) { | ||
| const constructor = __privateMethod(this, _getConstructorArgs, getConstructorArgs_fn).call(this, target); | ||
| const args = constructor.map((arg) => this.get(arg)); | ||
| const instance = new target(...args); | ||
| const meta = metadata(target); | ||
| const keys = meta.keys; | ||
| for (const key of keys) { | ||
| const info = meta.get(key); | ||
| if (!info) { | ||
| throw new Error( | ||
| `No metadata found for ${key} in ${target.name}. Did you forget to decorate it? | ||
| Use the \`@Inject.class\`, \`@Inject.factory\` or \`@Inject.value\` decorator to register a dependency type or value` | ||
| ); | ||
| } | ||
| if (info && "class" in info) { | ||
| const dependency = this.get(info.class); | ||
| instance[key] = dependency; | ||
| } | ||
| if (info && "factory" in info) { | ||
| const dependency = info.factory(); | ||
| instance[key] = dependency; | ||
| } | ||
| if (info && "value" in info) { | ||
| const dependency = info.value; | ||
| instance[key] = dependency; | ||
| } | ||
| } | ||
| if (DisposeMethod in instance && typeof instance[DisposeMethod] === "function") { | ||
| __privateGet(this, _disposables).add(instance); | ||
| } | ||
| return instance; | ||
| }; | ||
| _getConstructorArgs = new WeakSet(); | ||
| getConstructorArgs_fn = function(target) { | ||
| return metadata(target).getCustom(AutometaSymbol.CONSTRUCTOR) ?? []; | ||
| }; | ||
| function getRealTarget(target) { | ||
| if (typeof target === "string") { | ||
| return Token(target); | ||
| } | ||
| if (target instanceof InjectionToken) { | ||
| return target; | ||
| } | ||
| return target; | ||
| } | ||
| // src/container-context.ts | ||
| var global = Symbol.for("autometa:container:global"); | ||
| function defineContainerContext(name) { | ||
| if (name === "global") { | ||
| return global; | ||
| } | ||
| const hash = name.replace(/\s/g, "-").toLowerCase(); | ||
| return Symbol.for(`autometa:container:${hash}`); | ||
| } | ||
| export { | ||
| AutometaSymbol, | ||
| Constructor, | ||
| Container, | ||
| DisposeGlobalMethod, | ||
| DisposeMethod, | ||
| DisposeTagFilter, | ||
| Fixture, | ||
| INJECTION_SCOPE, | ||
| Inject, | ||
| InjectionToken, | ||
| Token, | ||
| clearRegistries, | ||
| defineContainerContext, | ||
| getContainerContexts, | ||
| getScope, | ||
| getSingleton, | ||
| getTypeToken, | ||
| hasContainerContext, | ||
| hasScope, | ||
| hasSingleton, | ||
| hasToken, | ||
| metadata, | ||
| registerContainerContext, | ||
| registerScope, | ||
| registerSingleton, | ||
| registerTypeToken | ||
| }; | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"sources":["../../src/symbol.ts","../../src/metadata.ts","../../src/metadata-registry.ts","../../src/scope.enum.ts","../../src/fixture.ts","../../src/get-constructor.ts","../../src/inject.ts","../../src/token.ts","../../src/constructor.ts","../../src/container.ts","../../src/container-context.ts"],"sourcesContent":["const META_DATA: unique symbol = Symbol(\"autometa:meta-data\");\nconst CONSTRUCTOR: unique symbol = Symbol(\"autometa:meta-data:constructor\");\nexport const AutometaSymbol = {\n META_DATA,\n CONSTRUCTOR,\n} as const;\n","import { AutometaSymbol } from \"./symbol\";\nimport { MetadataInfo } from \"./types\";\nimport { AutometaMetadata } from \"./types\";\nexport function metadata<T extends object>(target: T) {\n const withMetaData = target as T & {\n [AutometaSymbol.META_DATA]: AutometaMetadata;\n };\n if (!(AutometaSymbol.META_DATA in target)) {\n defineNonEnumerable(target, AutometaSymbol.META_DATA, {});\n }\n const metadata = withMetaData[AutometaSymbol.META_DATA];\n\n return {\n set: (info: MetadataInfo, override = true) => {\n if (!metadata[info.key]) {\n defineEnumerable(metadata, info.key, info);\n return;\n }\n if (override) {\n defineEnumerable(metadata, info.key, info);\n return;\n }\n },\n update: (key: string, updater: (info: MetadataInfo) => void) => {\n const current = metadata[key];\n if (!current) {\n const name = \"name\" in target ? target.name : target.constructor.name;\n const err = `Cannot create a constructor for ${name} as no metadata has been created for it. Try decorating it with '@Fixture'`;\n throw new Error(err);\n }\n updater(current);\n },\n custom: <T>(key: symbol, value: T, override = true) => {\n const md = withMetaData as unknown as Record<symbol, unknown>;\n if (!md[key] || override) {\n defineEnumerable(target, key, value);\n }\n return md[key] as T;\n },\n getCustom: <T>(key: symbol): T => {\n const md = withMetaData as unknown as Record<symbol, unknown>;\n return md[key] as T;\n },\n hasCustom: <T>(key: symbol): T => {\n const md = withMetaData as unknown as Record<symbol, unknown>;\n return md[key] as T;\n },\n get: (key: string): MetadataInfo => {\n return metadata[key];\n },\n get keys() {\n return Object.keys(metadata) as (keyof T)[];\n },\n };\n}\n\nfunction defineNonEnumerable<T>(\n target: T,\n key: string | symbol,\n value: unknown\n) {\n Object.defineProperty(target, key, {\n enumerable: false,\n configurable: true,\n writable: false,\n value,\n });\n}\n\nfunction defineEnumerable<T>(target: T, key: string | symbol, value: unknown) {\n Object.defineProperty(target, key, {\n enumerable: true,\n configurable: true,\n writable: true,\n value,\n });\n}\n","import { Class } from \"@autometa/types\";\nimport { InjectionScope } from \"./scope.enum\";\nimport { InjectorKey } from \"./types\";\nimport { InjectionToken } from \"./token\";\n\nconst ScopeRegistry = new Map<InjectorKey, InjectionScope>();\nconst TokenTypeRegistry = new Map<InjectionToken, Class<unknown>>();\nconst SingletonRegistry = new Map<InjectorKey, unknown>();\nconst ContainerContextRegistry = new Map<symbol, Map<InjectorKey, unknown>>();\n\nexport function registerSingleton<T extends InjectorKey>(\n target: T,\n instance: unknown\n) {\n if (SingletonRegistry.has(target)) {\n throw new Error(`Singleton already registered for ${target.name}`);\n }\n SingletonRegistry.set(target, instance);\n}\nexport function getSingleton<T extends InjectorKey>(\n target: T\n): unknown | undefined {\n return SingletonRegistry.get(target);\n}\n\nexport function hasSingleton<T extends InjectorKey>(\n target: T\n): boolean | undefined {\n return SingletonRegistry.has(target);\n}\n\nexport function registerScope<T extends InjectorKey>(\n target: T,\n scope: InjectionScope\n) {\n ScopeRegistry.set(target, scope);\n}\n\nexport function getScope<T extends InjectorKey>(\n target: T\n): InjectionScope | undefined {\n return ScopeRegistry.get(target);\n}\n\nexport function hasScope<T extends InjectorKey>(\n target: T\n): boolean | undefined {\n return ScopeRegistry.has(target);\n}\n\nexport function registerContainerContext<T extends InjectorKey>(\n context: symbol,\n target: T,\n instance: unknown\n) {\n if (!ContainerContextRegistry.has(context)) {\n ContainerContextRegistry.set(context, new Map());\n }\n ContainerContextRegistry.get(context)?.set(target, instance);\n return instance;\n}\n\nexport function getContainerContexts<T extends InjectorKey>(\n context: symbol,\n target: T\n): unknown | undefined {\n if (!ContainerContextRegistry.has(context)) {\n ContainerContextRegistry.set(context, new Map());\n }\n return ContainerContextRegistry.get(context)?.get(target);\n}\n\nexport function hasContainerContext<T extends InjectorKey>(\n context: symbol,\n target: T\n): boolean {\n if (!ContainerContextRegistry.has(context)) {\n ContainerContextRegistry.set(context, new Map());\n }\n return ContainerContextRegistry.get(context)?.has(target) ?? false;\n}\nexport function registerTypeToken<T>(token: InjectionToken, target: Class<T>) {\n TokenTypeRegistry.set(token, target);\n}\n\nexport function getTypeToken<T>(token: InjectionToken): Class<T> | undefined {\n return TokenTypeRegistry.get(token) as Class<T>;\n}\n\nexport function hasToken(token: InjectionToken): boolean {\n return TokenTypeRegistry.has(token);\n}\nexport function clearRegistries() {\n ScopeRegistry.clear();\n SingletonRegistry.clear();\n ContainerContextRegistry.clear();\n TokenTypeRegistry.clear();\n}\n","export const INJECTION_SCOPE = {\n SINGLETON: 0,\n TRANSIENT: 1,\n CACHED: 2,\n} as const;\n\nexport type InjectionScope =\n (typeof INJECTION_SCOPE)[keyof typeof INJECTION_SCOPE];\n","import { Class } from \"@autometa/types\";\nimport { INJECTION_SCOPE, InjectionScope } from \"./scope.enum\";\nimport { registerScope } from \"./metadata-registry\";\n\n/**\n * Marks a class as injectable. Optionally,\n * an Injection Scope can be defined, which determines\n * the strategy used to initialize the decorated class.\n *\n * INJECTION_SCOPE.CACHED: The class will be initialized once per container, but behave as a singleton within the container\n * INJECTION_SCOPE.SINGLETON: The class will be initialized once per container, and behave as a singleton across all containers\n * INJECTION_SCOPE.TRANSIENT: The class will be initialized once per injection, it will not be cached.\n *\n * By default if no scope is specified, the class will be cached. Once created all dependant sharing a container will share this instance.\n * @param target\n */\nexport function Fixture(target: Class<unknown>): void;\nexport function Fixture<T extends Class<unknown>>(\n scope?: InjectionScope\n): (target: T) => void;\nexport function Fixture(\n arg: InjectionScope | undefined | Class<unknown>\n): void | ((target: Class<unknown>) => void) {\n if (arg !== undefined && typeof arg !== \"number\") {\n registerScope(arg, INJECTION_SCOPE.CACHED);\n return;\n }\n return (target: Class<unknown>) => {\n registerScope(target, arg ?? INJECTION_SCOPE.CACHED);\n };\n}\n","export function getConstructor(target: unknown) {\n if (target && \"constructor\" in (target as object)) {\n return target.constructor;\n }\n throw new Error(`Cannot get constructor for ${target}`);\n}\n","import { Class } from \"@autometa/types\";\nimport { metadata } from \"./metadata\";\nimport { InjectionToken } from \"./token\";\nimport { getConstructor } from \"./get-constructor\";\n\nexport const Inject = {\n /**\n * Decorator factory which defines the Type of the property to inject. This\n * information will be used at class construction to automatically inject\n * that property with the appropriate type. If the type is class which\n * has not been marked as a `Fixture` then the dependency will be treated\n * as cached - meaning once created, the same instance will be used for\n * all subsequent injections. However the target class can be\n * defined as a `Singleton` or `Transient` fixture to override this behavior.\n */\n class: <T>(cls: Class<T> | InjectionToken) => {\n return function (target: unknown, propertyKey: string) {\n metadata(getConstructor(target)).set({\n key: propertyKey,\n class: cls,\n });\n };\n },\n /**\n * Decorator factory which defines a factory function that will\n * be used to inject the property. The factory function will be\n * called once per injection, and it's return value will be\n * used as the value of the property. Currently only synchronous\n * factory functions are supported.\n * @param factory\n * @returns\n */\n factory: <T>(factory: () => T) => {\n return function (target: unknown, propertyKey: string) {\n metadata(getConstructor(target)).set({\n key: propertyKey,\n factory: factory,\n });\n };\n },\n /**\n * Decorator factory which defines a value to inject into the property.\n * The value will be injected directly into the property without any\n * further processing. Equivalent to simply assigning the value to the\n * property.\n *\n * @param value\n * @returns\n */\n value: <T extends Class<unknown> | InjectionToken | string>(value: T) => {\n return function (target: unknown, propertyKey: string) {\n metadata(getConstructor(target)).set({\n key: propertyKey,\n value: value,\n });\n };\n },\n};\n","export class InjectionToken {\n constructor(public readonly name: string) {}\n}\nconst tokenMap = new Map<string, InjectionToken>();\n\nexport function Token(name: string): InjectionToken {\n if (!tokenMap.has(name)) {\n const token = new InjectionToken(name);\n tokenMap.set(name, token);\n }\n\n return tokenMap.get(name) as InjectionToken;\n}\n\nexport const DisposeMethod = Symbol(\"DisposeMethod\");\nexport const DisposeGlobalMethod = Symbol(\"DisposeGlobalMethod\");\n\nexport function DisposeTagFilter(tagFilter: string) {\n return function (\n _: {\n [DisposeMethod](\n tags: string[],\n isTagsMatch: (filter: string) => boolean\n ): unknown;\n },\n __: string | symbol,\n descriptor: PropertyDescriptor\n ) {\n const original = descriptor.value;\n descriptor.value = function (\n tags: string[],\n isTagMatch: (tags: string[], filter: string) => boolean\n ) {\n if (isTagMatch(tags, tagFilter)) {\n return original.apply(this);\n }\n };\n };\n}\n","import { metadata } from \"./metadata\";\nimport { AutometaSymbol } from \"./symbol\";\nimport { InjectorKey } from \"./types\";\n\n/**\n * Defines the constructor signature for an injectable class.\n * Takes a Rest Parameter of Classes or Injection Tokens which\n * match the constructor signature of the class.\n *\n * ```ts\n * @Fixture\n * @Constructor(HttpClient)\n * class MyClient {\n * constructor(\n * readonly http: HttpClient,\n * ) {}\n *\n * get() {\n * return this.http.get(\"https://example.com\");\n * }\n * }\n * ```\n *\n * The `MyClient` class is now injectable and can be used automatically\n * by adding it to the `App` with the same method.\n *\n * ```ts\n * @AppType(World)\n * @Constructor(MyClient)\n * class App {\n * constructor(\n * readonly client: MyClient,\n * ) {}\n * }\n * ```\n *\n * @param args A Rest Parameter of Classes or Injection Tokens which can be used to automatically inject new, cached or singleton dependencies into this class\n */\nexport function Constructor<T extends InjectorKey[]>(...args: T) {\n return function (target: object) {\n metadata(target).custom(AutometaSymbol.CONSTRUCTOR, args);\n };\n}\n","import { Class } from \"@autometa/types\";\nimport {\n getContainerContexts,\n getScope,\n getSingleton,\n getTypeToken,\n hasContainerContext,\n hasScope,\n hasSingleton,\n registerContainerContext,\n registerScope,\n registerSingleton,\n registerTypeToken,\n} from \"./metadata-registry\";\nimport { metadata } from \"./metadata\";\nimport { INJECTION_SCOPE } from \"./scope.enum\";\nimport { DisposeMethod, InjectionToken, Token } from \"./token\";\nimport { InjectorKey } from \"./types\";\nimport { AutometaSymbol } from \"./symbol\";\n\nexport class Container {\n #disposables = new Set<{\n [DisposeMethod](\n tags: string[],\n isTagsMatch: (tags: string[], filter: string) => boolean\n ): unknown;\n }>();\n #globalDisposables = new Set<{\n [DisposeMethod](\n tags: string[],\n isTagsMatch: (tags: string[], filter: string) => boolean\n ): unknown;\n }>();\n constructor(readonly reference: symbol) {}\n\n registerSingleton<T>(token: InjectionToken, type: Class<T>): Container;\n registerSingleton<T>(type: Class<T>): Container;\n registerSingleton<T>(token: Class<T> | InjectionToken, type?: Class<T>) {\n registerScope(token, INJECTION_SCOPE.SINGLETON);\n if (token instanceof InjectionToken && type) {\n registerTypeToken(token, type);\n }\n return this;\n }\n\n registerCached<T>(token: InjectionToken, type: Class<T>): Container;\n registerCached<T>(type: Class<T>): Container;\n registerCached<T>(token: Class<T> | InjectionToken, type?: Class<T>) {\n registerScope(token, INJECTION_SCOPE.CACHED);\n if (token instanceof InjectionToken && type) {\n registerTypeToken(token, type);\n }\n return this;\n }\n\n registerTransient<T>(target: Class<T>): Container;\n registerTransient<T>(token: InjectionToken, target: Class<T>): Container;\n registerTransient(\n target: Class<unknown> | InjectionToken,\n type?: Class<unknown>\n ) {\n this.#throwOnSingletonTokenClash(target);\n registerScope(target, INJECTION_SCOPE.TRANSIENT);\n if (target instanceof InjectionToken && type) {\n registerTypeToken(target, type);\n }\n return this;\n }\n\n registerSingletonValue(identifier: string, value: unknown) {\n registerSingleton(Token(identifier), value);\n return this;\n }\n\n registerCachedValue(identifier: string, value: unknown) {\n this.#throwOnSingletonTokenClash(Token(identifier));\n registerScope(Token(identifier), INJECTION_SCOPE.CACHED);\n registerContainerContext(this.reference, Token(identifier), value);\n return this;\n }\n\n #throwOnSingletonTokenClash(token: InjectorKey) {\n if (hasSingleton(token)) {\n throw new Error(\n `Singleton token ${token.name} is already registered. Use a different token or register a cached dependency`\n );\n }\n }\n get<T>(token: string): T;\n get<T>(token: InjectionToken): T;\n get<T>(target: Class<T>): T;\n get<T>(target: InjectorKey | string): T;\n get<T>(target: InjectorKey | string): T {\n target = getRealTarget(target);\n\n if (hasSingleton(target)) {\n return getSingleton(target) as T;\n }\n const scope = getScope(target);\n if (!hasScope(target)) {\n registerScope(target, INJECTION_SCOPE.CACHED);\n }\n const type = getTypeToken(target) ?? (target as Class<unknown>);\n if (scope === INJECTION_SCOPE.SINGLETON) {\n const instance = this.#assembleTarget(type);\n registerSingleton(target, instance);\n return instance as T;\n }\n\n if (scope === INJECTION_SCOPE.CACHED) {\n if (hasContainerContext(this.reference, target)) {\n return getContainerContexts(this.reference, target) as T;\n }\n const assembled = this.#assembleTarget(type);\n return registerContainerContext(this.reference, target, assembled) as T;\n }\n\n return this.#assembleTarget(type) as T;\n }\n\n async disposeAll(\n tags: string[],\n isTagsMatch: (tags: string[], filter: string) => boolean\n ) {\n for (const disposable of this.#disposables) {\n await disposable[DisposeMethod](tags, isTagsMatch);\n }\n }\n\n async disposeGlobal(\n tags: string[],\n isTagsMatch: (tags: string[], filter: string) => boolean\n ) {\n for (const disposable of this.#globalDisposables) {\n await disposable[DisposeMethod](tags, isTagsMatch);\n }\n }\n\n #assembleTarget<T>(target: Class<T>): T {\n const constructor = this.#getConstructorArgs<T>(target);\n const args = constructor.map((arg) => this.get(arg));\n const instance = new target(...args) as Record<string, unknown>;\n const meta = metadata(target);\n const keys = meta.keys as string[];\n for (const key of keys) {\n const info = meta.get(key);\n if (!info) {\n throw new Error(\n `No metadata found for ${key} in ${target.name}. Did you forget to decorate it? \nUse the \\`@Inject.class\\`, \\`@Inject.factory\\` or \\`@Inject.value\\` decorator to register a dependency type or value`\n );\n }\n if (info && \"class\" in info) {\n const dependency = this.get(info.class);\n instance[key] = dependency;\n }\n\n if (info && \"factory\" in info) {\n const dependency = info.factory();\n instance[key] = dependency;\n }\n\n if (info && \"value\" in info) {\n const dependency = info.value;\n instance[key] = dependency;\n }\n }\n if (\n DisposeMethod in instance &&\n typeof instance[DisposeMethod] === \"function\"\n ) {\n this.#disposables.add(instance as { [DisposeMethod](): unknown });\n }\n return instance as T;\n }\n\n #getConstructorArgs<T>(target: Class<T>) {\n return (\n metadata(target).getCustom<InjectorKey[]>(AutometaSymbol.CONSTRUCTOR) ??\n []\n );\n }\n}\n\nfunction getRealTarget(target: Class<unknown> | InjectionToken | string) {\n if (typeof target === \"string\") {\n return Token(target);\n }\n if (target instanceof InjectionToken) {\n return target;\n }\n return target;\n}\n","const global = Symbol.for(\"autometa:container:global\");\n\nexport function defineContainerContext(name: string) {\n if (name === \"global\") {\n return global;\n }\n const hash = name.replace(/\\s/g, \"-\").toLowerCase();\n return Symbol.for(`autometa:container:${hash}`);\n}\n"],"mappings":"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","names":["metadata"]} |
-184
| import { Class } from '@autometa/types'; | ||
| declare const META_DATA: unique symbol; | ||
| declare const CONSTRUCTOR: unique symbol; | ||
| declare const AutometaSymbol: { | ||
| readonly META_DATA: typeof META_DATA; | ||
| readonly CONSTRUCTOR: typeof CONSTRUCTOR; | ||
| }; | ||
| declare class InjectionToken { | ||
| readonly name: string; | ||
| constructor(name: string); | ||
| } | ||
| declare function Token(name: string): InjectionToken; | ||
| declare const DisposeMethod: unique symbol; | ||
| declare const DisposeGlobalMethod: unique symbol; | ||
| declare function DisposeTagFilter(tagFilter: string): (_: { | ||
| [DisposeMethod](tags: string[], isTagsMatch: (filter: string) => boolean): unknown; | ||
| }, __: string | symbol, descriptor: PropertyDescriptor) => void; | ||
| type BaseMetadata = { | ||
| key: string; | ||
| custom?: Record<string, unknown>; | ||
| }; | ||
| type InjectValueMetadata = BaseMetadata & { | ||
| value: unknown; | ||
| custom?: Record<string, unknown>; | ||
| }; | ||
| type InjectClassMetadata = BaseMetadata & { | ||
| class: Class<unknown> | InjectionToken; | ||
| custom?: Record<string, unknown>; | ||
| }; | ||
| type InjectFactoryMetadata = BaseMetadata & { | ||
| factory: () => unknown; | ||
| custom?: Record<string, unknown>; | ||
| }; | ||
| type InjectTokenMetadata = BaseMetadata & { | ||
| token: InjectionToken; | ||
| custom?: Record<string, unknown>; | ||
| }; | ||
| type MetadataInfo = InjectClassMetadata | InjectValueMetadata | InjectFactoryMetadata | InjectTokenMetadata; | ||
| type AutometaMetadata = { | ||
| [key: string]: MetadataInfo; | ||
| }; | ||
| type InjectorKey = Class<unknown> | InjectionToken; | ||
| declare function metadata<T extends object>(target: T): { | ||
| set: (info: MetadataInfo, override?: boolean) => void; | ||
| update: (key: string, updater: (info: MetadataInfo) => void) => void; | ||
| custom: <T_1>(key: symbol, value: T_1, override?: boolean) => T_1; | ||
| getCustom: <T_2>(key: symbol) => T_2; | ||
| hasCustom: <T_3>(key: symbol) => T_3; | ||
| get: (key: string) => MetadataInfo; | ||
| readonly keys: (keyof T)[]; | ||
| }; | ||
| declare const INJECTION_SCOPE: { | ||
| readonly SINGLETON: 0; | ||
| readonly TRANSIENT: 1; | ||
| readonly CACHED: 2; | ||
| }; | ||
| type InjectionScope = (typeof INJECTION_SCOPE)[keyof typeof INJECTION_SCOPE]; | ||
| declare function registerSingleton<T extends InjectorKey>(target: T, instance: unknown): void; | ||
| declare function getSingleton<T extends InjectorKey>(target: T): unknown | undefined; | ||
| declare function hasSingleton<T extends InjectorKey>(target: T): boolean | undefined; | ||
| declare function registerScope<T extends InjectorKey>(target: T, scope: InjectionScope): void; | ||
| declare function getScope<T extends InjectorKey>(target: T): InjectionScope | undefined; | ||
| declare function hasScope<T extends InjectorKey>(target: T): boolean | undefined; | ||
| declare function registerContainerContext<T extends InjectorKey>(context: symbol, target: T, instance: unknown): unknown; | ||
| declare function getContainerContexts<T extends InjectorKey>(context: symbol, target: T): unknown | undefined; | ||
| declare function hasContainerContext<T extends InjectorKey>(context: symbol, target: T): boolean; | ||
| declare function registerTypeToken<T>(token: InjectionToken, target: Class<T>): void; | ||
| declare function getTypeToken<T>(token: InjectionToken): Class<T> | undefined; | ||
| declare function hasToken(token: InjectionToken): boolean; | ||
| declare function clearRegistries(): void; | ||
| /** | ||
| * Marks a class as injectable. Optionally, | ||
| * an Injection Scope can be defined, which determines | ||
| * the strategy used to initialize the decorated class. | ||
| * | ||
| * INJECTION_SCOPE.CACHED: The class will be initialized once per container, but behave as a singleton within the container | ||
| * INJECTION_SCOPE.SINGLETON: The class will be initialized once per container, and behave as a singleton across all containers | ||
| * INJECTION_SCOPE.TRANSIENT: The class will be initialized once per injection, it will not be cached. | ||
| * | ||
| * By default if no scope is specified, the class will be cached. Once created all dependant sharing a container will share this instance. | ||
| * @param target | ||
| */ | ||
| declare function Fixture(target: Class<unknown>): void; | ||
| declare function Fixture<T extends Class<unknown>>(scope?: InjectionScope): (target: T) => void; | ||
| declare const Inject: { | ||
| /** | ||
| * Decorator factory which defines the Type of the property to inject. This | ||
| * information will be used at class construction to automatically inject | ||
| * that property with the appropriate type. If the type is class which | ||
| * has not been marked as a `Fixture` then the dependency will be treated | ||
| * as cached - meaning once created, the same instance will be used for | ||
| * all subsequent injections. However the target class can be | ||
| * defined as a `Singleton` or `Transient` fixture to override this behavior. | ||
| */ | ||
| class: <T>(cls: InjectionToken | Class<T>) => (target: unknown, propertyKey: string) => void; | ||
| /** | ||
| * Decorator factory which defines a factory function that will | ||
| * be used to inject the property. The factory function will be | ||
| * called once per injection, and it's return value will be | ||
| * used as the value of the property. Currently only synchronous | ||
| * factory functions are supported. | ||
| * @param factory | ||
| * @returns | ||
| */ | ||
| factory: <T_1>(factory: () => T_1) => (target: unknown, propertyKey: string) => void; | ||
| /** | ||
| * Decorator factory which defines a value to inject into the property. | ||
| * The value will be injected directly into the property without any | ||
| * further processing. Equivalent to simply assigning the value to the | ||
| * property. | ||
| * | ||
| * @param value | ||
| * @returns | ||
| */ | ||
| value: <T_2 extends string | InjectionToken | Class<unknown>>(value: T_2) => (target: unknown, propertyKey: string) => void; | ||
| }; | ||
| /** | ||
| * Defines the constructor signature for an injectable class. | ||
| * Takes a Rest Parameter of Classes or Injection Tokens which | ||
| * match the constructor signature of the class. | ||
| * | ||
| * ```ts | ||
| * @Fixture | ||
| * @Constructor(HttpClient) | ||
| * class MyClient { | ||
| * constructor( | ||
| * readonly http: HttpClient, | ||
| * ) {} | ||
| * | ||
| * get() { | ||
| * return this.http.get("https://example.com"); | ||
| * } | ||
| * } | ||
| * ``` | ||
| * | ||
| * The `MyClient` class is now injectable and can be used automatically | ||
| * by adding it to the `App` with the same method. | ||
| * | ||
| * ```ts | ||
| * @AppType(World) | ||
| * @Constructor(MyClient) | ||
| * class App { | ||
| * constructor( | ||
| * readonly client: MyClient, | ||
| * ) {} | ||
| * } | ||
| * ``` | ||
| * | ||
| * @param args A Rest Parameter of Classes or Injection Tokens which can be used to automatically inject new, cached or singleton dependencies into this class | ||
| */ | ||
| declare function Constructor<T extends InjectorKey[]>(...args: T): (target: object) => void; | ||
| declare class Container { | ||
| #private; | ||
| readonly reference: symbol; | ||
| constructor(reference: symbol); | ||
| registerSingleton<T>(token: InjectionToken, type: Class<T>): Container; | ||
| registerSingleton<T>(type: Class<T>): Container; | ||
| registerCached<T>(token: InjectionToken, type: Class<T>): Container; | ||
| registerCached<T>(type: Class<T>): Container; | ||
| registerTransient<T>(target: Class<T>): Container; | ||
| registerTransient<T>(token: InjectionToken, target: Class<T>): Container; | ||
| registerSingletonValue(identifier: string, value: unknown): this; | ||
| registerCachedValue(identifier: string, value: unknown): this; | ||
| get<T>(token: string): T; | ||
| get<T>(token: InjectionToken): T; | ||
| get<T>(target: Class<T>): T; | ||
| get<T>(target: InjectorKey | string): T; | ||
| disposeAll(tags: string[], isTagsMatch: (tags: string[], filter: string) => boolean): Promise<void>; | ||
| disposeGlobal(tags: string[], isTagsMatch: (tags: string[], filter: string) => boolean): Promise<void>; | ||
| } | ||
| declare function defineContainerContext(name: string): symbol; | ||
| export { AutometaMetadata, AutometaSymbol, BaseMetadata, Constructor, Container, DisposeGlobalMethod, DisposeMethod, DisposeTagFilter, Fixture, INJECTION_SCOPE, Inject, InjectClassMetadata, InjectFactoryMetadata, InjectTokenMetadata, InjectValueMetadata, InjectionScope, InjectionToken, InjectorKey, MetadataInfo, Token, clearRegistries, defineContainerContext, getContainerContexts, getScope, getSingleton, getTypeToken, hasContainerContext, hasScope, hasSingleton, hasToken, metadata, registerContainerContext, registerScope, registerSingleton, registerTypeToken }; |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
139130
37.8%20
25%14
7.69%1083
-1.63%1
Infinity%+ Added
+ Added
- Removed
- Removed