🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@autometa/injection

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@autometa/injection - npm Package Compare versions

Comparing version
0.1.5
to
1.0.0-rc.0
+23
.turbo/turbo-build.log

> @autometa/injection@0.1.5 build /Users/ben.aherne/Documents/GitHub/autometa/packages/injection
> tsup && pnpm run build:types
CLI Building entry: src/index.ts
CLI Using tsconfig: tsconfig.bundle.json
CLI tsup v7.2.0
CLI Using tsup config: /Users/ben.aherne/Documents/GitHub/autometa/packages/injection/tsup.config.ts
CLI Target: es2020
CLI Cleaning output folder
CJS Build start
ESM Build start
CJS dist/index.cjs 13.94 KB
CJS dist/index.cjs.map 32.43 KB
CJS ⚡️ Build success in 386ms
ESM dist/index.js 13.66 KB
ESM dist/index.js.map 32.43 KB
ESM ⚡️ 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;
};
'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"]}
/**
* 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
 RUN  v1.4.0 /Users/ben.aherne/Documents/GitHub/autometa/packages/injection
✓ 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 · Mixed Injection Tests (3)
· should resolve a service with both constructor and property injection
· should resolve a complex dependency graph
· should resolve ServiceCImpl directly
[?25l[?25l ✓ Mixed Injection Tests (3)
✓ should resolve a service with both constructor and property injection
✓ should resolve a complex dependency graph
✓ should resolve ServiceCImpl directly
[?25l ✓ src/__tests__/integration/mixed-injection.test.ts (3)
✓ Mixed Injection Tests (3)
✓ should resolve a service with both constructor and property injection
✓ should resolve a complex dependency graph
✓ 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)
 Test Files  1 passed (1)
 Tests  3 passed (3)
 Start at  01:06:24
 Duration  3.13s (transform 326ms, setup 0ms, collect 509ms, tests 6ms, environment 0ms, prepare 649ms)
[?25h[?25h
# @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 @@

@@ -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';

@@ -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"]}
{
"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"
}
}

@@ -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"]}
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