API Reference
Complete API documentation for @noneforge/ioc.
Container
Constructor
new Container<TMetadata>(
providers?: Provider<unknown, TMetadata>[],
parent?: Container<TMetadata>,
options?: ContainerOptions<TMetadata>
)Type Parameters:
TMetadata- Type for metadata keys/values, enables autocomplete inwhencallbacks
Parameters:
providers- Initial providers to registerparent- Parent container for hierarchical resolutionoptions- Container configuration options
ContainerOptions
interface ContainerOptions<TMetadata extends object = Record<string, unknown>> {
strict?: boolean; // Throw on missing providers (default: false)
debug?: boolean; // Enable debug logging (default: false)
lazyLoad?: boolean; // Defer instantiation (default: false)
maxCacheSize?: number; // Maximum singleton cache size
autoDispose?: boolean; // Auto-dispose on process exit
defaultMetadata?: TMetadata; // Default metadata for all resolutions
}The defaultMetadata is merged with per-call metadata and available in when callbacks:
interface MyMetadata {
environment: 'development' | 'production';
tenant?: string;
}
const container = new Container<MyMetadata>(providers, undefined, {
defaultMetadata: { environment: 'production' }
});createContainer()
function createContainer(...providers: Provider[]): ContainerFactory function to create a new container.
Methods
get()
get<T>(token: Token<T>, options?: ContainerGetOptions): TSynchronously resolve a dependency.
Parameters:
token- Token to resolveoptions- Resolution options
Returns: Resolved instance
Throws: NoProviderError if not found and not optional
getAsync()
getAsync<T>(token: Token<T>, options?: ContainerGetOptions): Promise<T>Asynchronously resolve a dependency.
getAll()
getAll<T>(token: Token<T>): T[]Get all instances for a multi-provider token.
has()
has(token: Token): booleanCheck if a provider is registered (includes global registry).
hasProvider()
hasProvider<T>(token: Token<T>): booleanCheck if a provider is registered in this container or parent.
addProvider()
addProvider(provider: Provider): voidRegister a provider.
loadModule()
loadModule(ModuleClass: Constructor): voidLoad a module and its providers.
createChild()
createChild(providers?: Provider[]): ContainerCreate a child container.
validate()
validate(): ValidationResult
interface ValidationResult {
valid: boolean;
errors: string[];
warnings: string[];
}Validate all providers and dependencies.
dispose()
dispose(): Promise<void>Dispose container and call onDestroy hooks.
getStatistics()
getStatistics(): ContainerStatistics
interface ContainerStatistics {
resolutions: number;
creates: number;
cacheHits: number;
errors: number;
}Get resolution statistics.
getDependencyGraph()
getDependencyGraph(): DependencyGraphGet the dependency graph for analysis and validation.
ContainerGetOptions
interface ContainerGetOptions {
optional?: boolean; // Return null if not found
skipSelf?: boolean; // Skip this container, search parent
self?: boolean; // Only this container, don't search parent
lazy?: boolean; // Return lazy proxy
proxy?: boolean; // Same as lazy
requestId?: string | symbol; // For request scope
metadata?: Record<string, unknown>;
}Note:
skipSelfandselfare mutually exclusive.skipSelfis evaluated first. Using both together results in searching only the root container.
InjectionToken
Constructor
new InjectionToken<T>(
description: string,
options?: InjectionTokenOptions<T>
)InjectionTokenOptions
interface InjectionTokenOptions<T> {
providedIn?: 'root' | 'platform' | 'any' | null;
factory?: () => T;
multi?: boolean;
scope?: ProviderScope;
validator?: (value: unknown) => boolean;
transformer?: (value: any) => T;
}Methods
toString()
toString(): stringGet string representation.
validate()
validate(value: unknown): booleanValidate a value (if validator provided).
transform()
transform(value: any): TTransform a value (if transformer provided).
Providers
ClassProvider
interface ClassProvider<T, TMetadata extends object = Record<string, unknown>> {
provide: Token<T>;
useClass: Constructor<T> | ForwardRef<T>;
scope?: ProviderScope;
lazy?: boolean;
multi?: boolean;
when?: (ctx: InjectionContext<TMetadata>) => boolean;
interceptors?: InterceptorLike[];
metadata?: Record<string, unknown>;
tags?: string[];
}ValueProvider
interface ValueProvider<T, TMetadata extends object = Record<string, unknown>> {
provide: Token<T>;
useValue: T;
multi?: boolean;
when?: (ctx: InjectionContext<TMetadata>) => boolean;
metadata?: Record<string, unknown>;
tags?: string[];
}FactoryProvider
interface FactoryProvider<T, TMetadata extends object = Record<string, unknown>> {
provide: Token<T>;
useFactory: (...deps: any[]) => T | Promise<T>;
inject?: (Token | ForwardRef)[];
scope?: ProviderScope;
lazy?: boolean;
multi?: boolean;
when?: (ctx: InjectionContext<TMetadata>) => boolean;
interceptors?: InterceptorLike[];
metadata?: Record<string, unknown>;
tags?: string[];
}ExistingProvider
interface ExistingProvider<T, TMetadata extends object = Record<string, unknown>> {
provide: Token<T>;
useExisting: Token<T> | ForwardRef<T>;
multi?: boolean;
when?: (ctx: InjectionContext<TMetadata>) => boolean;
metadata?: Record<string, unknown>;
tags?: string[];
}AsyncProvider
interface AsyncProvider<T, TMetadata extends object = Record<string, unknown>> {
provide: Token<T>;
useAsync: () => Promise<T>;
scope?: ProviderScope;
multi?: boolean;
when?: (ctx: InjectionContext<TMetadata>) => boolean;
metadata?: Record<string, unknown>;
tags?: string[];
}Note: Unlike
FactoryProvider,AsyncProviderdoes not supportinjectfor dependencies. UseFactoryProviderwith async factory if you need dependency injection.
ProviderScope
type ProviderScope =
| 'singleton' // One per container
| 'transient' // New every time
| 'request' // One per requestId
| 'prototype' // New with shared prototype
| 'scoped'; // Custom scopeDecorators
@Injectable()
@Injectable(options?: InjectableOptions)
interface InjectableOptions {
providedIn?: 'root' | 'platform' | 'any' | null;
scope?: ProviderScope;
tags?: string[];
}@Inject()
@Inject(token: Token)@Optional()
@Optional()@Lazy()
@Lazy()@Module()
@Module(options: ModuleOptions)
interface ModuleOptions {
imports?: Constructor[];
providers?: Provider[];
exports?: (Token | Constructor)[];
}AOP Decorators
@Cached(ttl?: number)
@Log(tag?: string)
@Transactional()inject() Functions
inject()
function inject<T>(
token: Token<T> | ForwardRef<T>,
options?: InjectOptions
): TinjectOptional()
function injectOptional<T>(
token: Token<T> | ForwardRef<T>,
options?: Omit<InjectOptions, 'optional'>
): T | nullinjectLazy()
function injectLazy<T>(
token: Token<T> | ForwardRef<T>,
options?: Omit<InjectOptions, 'lazy'>
): T & LazyProxy<T>injectAll()
function injectAll<T>(
token: Token<T> | ForwardRef<T>
): T[]InjectOptions
interface InjectOptions {
optional?: boolean; // Return null if not found
skipSelf?: boolean; // Skip this container, search parent
self?: boolean; // Only this container, don't search parent
lazy?: boolean; // Return lazy proxy
multi?: boolean; // Get all multi-providers
}Note:
skipSelfandselfare mutually exclusive. See ContainerGetOptions.
LazyProxy
interface LazyProxy<T> {
readonly value: T;
readonly isResolved: boolean;
resolve(): T;
resolveAsync(): Promise<T>;
reset(): void;
}Interceptors
Interceptor Interface
interface Interceptor {
intercept<T>(
context: InjectionContext,
next: () => T | Promise<T>
): T | Promise<T>;
}InterceptorFn
Functional interceptor type:
type InterceptorFn = (
context: InjectionContext,
next: () => unknown
) => unknown;InterceptorLike
Union type for both class-based and functional interceptors:
type InterceptorLike = Interceptor | InterceptorFn;Interceptor Helpers
createInterceptor()
Create an interceptor from pre/post hooks:
function createInterceptor(options: CreateInterceptorOptions): InterceptorFn
interface CreateInterceptorOptions {
pre?: (context: InjectionContext) => void | Promise<void>;
post?: (context: InjectionContext, result: unknown) => unknown;
}composeInterceptors()
Compose multiple interceptors into a single interceptor:
function composeInterceptors(...interceptors: InterceptorLike[]): InterceptorFnwhen()
Create a conditional interceptor:
function when(
predicate: (context: InjectionContext) => boolean,
interceptor: InterceptorLike
): InterceptorFnType Guards
function isClassInterceptor(value: InterceptorLike): value is Interceptor
function isFunctionalInterceptor(value: InterceptorLike): value is InterceptorFnBuilt-in Interceptors
class CachingInterceptor implements Interceptor {
constructor(ttl?: number)
}
class LoggingInterceptor implements Interceptor {
constructor(logger?: Logger)
}
class RetryInterceptor implements Interceptor {
constructor(maxRetries?: number, delay?: number)
}
class ValidationInterceptor implements Interceptor {
constructor(
validator: (value: unknown) => boolean,
errorMessage?: string
)
}Logger
Interface for LoggingInterceptor:
interface Logger {
log(message: string, context?: unknown): void;
error(message: string, error?: unknown): void;
warn(message: string, context?: unknown): void;
}InterceptorChain
class InterceptorChain {
add(interceptor: Interceptor): void;
execute<T>(context: InjectionContext, factory: () => T): T;
executeAsync<T>(context: InjectionContext, factory: () => Promise<T>): Promise<T>;
}Middleware System
Middleware
Interface for middleware:
interface Middleware {
priority: number;
pre?(context: InjectionContext): void | Promise<void>;
post?<T>(context: InjectionContext, instance: T): T | Promise<T>;
}MiddlewareRunner
Runner for executing middleware chain:
class MiddlewareRunner {
add(middleware: Middleware): void;
runPre(context: InjectionContext): Promise<void>;
runPost<T>(context: InjectionContext, instance: T): Promise<T>;
}Plugin System
ContainerPlugin
interface ContainerPlugin {
name: string;
version?: string;
install(container: unknown): void | Promise<void>;
uninstall?(container: unknown): void | Promise<void>;
}PluginManager
class PluginManager {
install(plugin: ContainerPlugin, container: unknown): Promise<void>;
uninstall(pluginName: string, container: unknown): Promise<void>;
getPlugin(name: string): ContainerPlugin | undefined;
listPlugins(): ContainerPlugin[];
hasPlugin(name: string): boolean;
}See Plugin System for complete documentation and examples.
Testing
TestContainer
class TestContainer extends Container {
override<T>(token: Token<T>, value: T | Provider<T>): void;
mock<T>(token: Token<T>, partial: Partial<T>): T;
spy<T>(token: Token<T>): T;
reset(): void;
snapshot(): { providers: Map<Token, Provider>; restore(): void };
}Helper Functions
function createTestContainer(...providers: Provider[]): TestContainer;
function createMockProvider<T>(token: Token<T>, mock: Partial<T>): Provider<T>;
function createSpyProvider<T>(token: Token<T>, impl: T): Provider<T>;Lifecycle Interfaces
interface OnInit {
onInit(): void | Promise<void>;
}
interface OnDestroy {
onDestroy(): void | Promise<void>;
}
interface OnInject {
onInject(context: InjectionContext): void | Promise<void>;
}
interface OnRequest {
onRequest(requestId: string | symbol): void | Promise<void>;
}
interface Disposable {
dispose(): void | Promise<void>;
}ScopeManager
Manager for custom scopes:
class ScopeManager {
createScope(name: string): void;
deleteScope(name: string): void;
setInScope(name: string, token: Token, value: unknown): void;
getFromScope(name: string, token: Token): unknown;
hasScope(name: string): boolean;
clearScope(name: string): Promise<void>;
listScopes(): string[];
}Bootstrap
async function bootstrap<T extends object>(
RootModule: Constructor<T>,
options?: BootstrapOptions
): Promise<{ app: T; container: Container }>
function createApplication<T extends object>(
RootModule: Constructor<T>,
options?: BootstrapOptions
): Container
interface BootstrapOptions {
providers?: Provider[];
strict?: boolean;
validate?: boolean;
debug?: boolean;
}Module Functions
function createDynamicModule(config: DynamicModuleConfig): Constructor;
interface DynamicModuleConfig {
module: Constructor;
imports?: Constructor[];
providers?: Provider[];
exports?: (Token | Constructor)[];
}
function createConfigurableModule<T>(
factory: (options: T) => ModuleConfig
): {
forRoot(options: T): Constructor;
forChild(options: Partial<T>): Constructor;
}Forward References
function forwardRef<T>(fn: () => Token<T>): ForwardRef<T>;
function resolveForwardRef<T>(token: Token<T> | ForwardRef<T>): Token<T>;
function isForwardRef<T>(token: unknown): token is ForwardRef<T>;
interface ForwardRef<T = unknown> {
forwardRef: () => Token<T>;
__forward_ref__: true;
}Provider Helpers
function createProvider<T>(
token: Token<T>,
implementation: Constructor<T>,
options?: Partial<ClassProvider<T>>
): ClassProvider<T>;
function createAsyncProvider<T>(
token: Token<T>,
factory: () => Promise<T>,
options?: Partial<AsyncProvider<T>>
): AsyncProvider<T>;
function provideIf<T>(
condition: boolean,
provider: Provider<T>
): Provider<T> | null;
function provideForEnvironment<T>(
environment: string,
provider: Provider<T>
): Provider<T> | null;Context Types
InjectionContext
interface InjectionContext<TMetadata extends object = Record<string, unknown>> {
container: ContainerLike;
token?: Token;
requestId?: string | symbol;
metadata: TypedMetadataMap<TMetadata>;
depth: number;
path: Token[];
strategy: ResolutionStrategy;
}TypedMetadataMap
Typed Map that provides autocomplete for known metadata keys:
interface TypedMetadataMap<TMetadata extends object = Record<string, unknown>> {
get<K extends keyof TMetadata>(key: K): TMetadata[K];
get(key: string): unknown;
set<K extends keyof TMetadata>(key: K, value: TMetadata[K]): this;
set(key: string, value: unknown): this;
has(key: keyof TMetadata | string): boolean;
delete(key: keyof TMetadata | string): boolean;
clear(): void;
forEach(callbackfn: (value: unknown, key: string) => void): void;
readonly size: number;
entries(): IterableIterator<[string, unknown]>;
keys(): IterableIterator<string>;
values(): IterableIterator<unknown>;
}Token
type Token<T = unknown> =
| Constructor<T & object>
| Abstract<T & object>
| InjectionToken<T>
| string
| symbol;Errors
class InjectionError extends Error {
constructor(message: string, token?: Token);
}
class NoProviderError extends InjectionError {
constructor(token: Token);
}
class CircularDependencyError extends InjectionError {
constructor(path: Token[]);
}
class ScopeError extends InjectionError {
constructor(message: string, token?: Token);
}
class ValidationError extends InjectionError {
constructor(message: string, token: Token, value: unknown);
}EnhancedCache
class EnhancedCache<K, V> {
constructor(options?: CacheOptions<K>);
set(
key: K,
value: V,
options?: CacheSetOptions
): void;
get(key: K): V | undefined;
has(key: K): boolean;
delete(key: K): Promise<void>;
clear(): Promise<void>;
get size(): number;
getStatistics(): CacheStatistics;
}
interface CacheOptions<K> {
maxSize?: number; // Maximum entries (default: 1000)
evictionPolicy?: CacheEvictionPolicy; // 'lru' | 'lfu' | 'fifo' (default: 'lru')
onDisposeError?: (error: unknown, key: K) => void; // Error handler for dispose callbacks
}
interface CacheSetOptions {
ttl?: number; // Time to live in milliseconds
dispose?: () => void | Promise<void>; // Cleanup callback on eviction
}
interface CacheStatistics {
size: number;
hits: number;
misses: number;
evictions: number;
}
type CacheEvictionPolicy = 'lru' | 'lfu' | 'fifo';Type Guards
function hasOnInit(obj: unknown): obj is OnInit;
function hasOnDestroy(obj: unknown): obj is OnDestroy;
function hasOnInject(obj: unknown): obj is OnInject;
function hasOnRequest(obj: unknown): obj is OnRequest;
function isConstructor(value: unknown): value is Constructor;
function isProvider(value: unknown): value is Provider;
function isDefined<T>(value: T | null | undefined): value is T;