@illuma/core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/README.md +164 -0
- package/dist/index.cjs +1089 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +378 -0
- package/dist/index.d.ts +378 -0
- package/dist/index.js +1045 -0
- package/dist/index.js.map +1 -0
- package/dist/injection-CSxu56ds.d.cts +57 -0
- package/dist/injection-Y_bVmBSk.d.ts +57 -0
- package/dist/plugin-container-CwkVlVS4.d.ts +136 -0
- package/dist/plugin-container-D8Zwpigq.d.cts +136 -0
- package/dist/plugins.cjs +80 -0
- package/dist/plugins.cjs.map +1 -0
- package/dist/plugins.d.cts +9 -0
- package/dist/plugins.d.ts +9 -0
- package/dist/plugins.js +54 -0
- package/dist/plugins.js.map +1 -0
- package/dist/providers-D9YA8L_g.d.cts +153 -0
- package/dist/providers-D9YA8L_g.d.ts +153 -0
- package/dist/testkit.cjs +995 -0
- package/dist/testkit.cjs.map +1 -0
- package/dist/testkit.d.cts +44 -0
- package/dist/testkit.d.ts +44 -0
- package/dist/testkit.js +970 -0
- package/dist/testkit.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/lib/errors.ts","../src/lib/api/token.ts","../src/lib/api/decorator.ts","../src/lib/plugins/core/plugin-container.ts","../src/lib/context/context.ts","../src/lib/api/injection.ts","../src/lib/plugins/diagnostics/default-impl.ts","../src/lib/provider/extractor.ts","../src/lib/provider/proto.ts","../src/lib/provider/tree-node.ts","../src/lib/provider/resolver.ts","../src/lib/utils/injector.ts","../src/lib/utils/inheritance.ts","../src/lib/container/container.ts"],"sourcesContent":["export * from \"./lib/api\";\nexport * from \"./lib/container\";\nexport * from \"./lib/context\";\nexport * from \"./lib/errors\";\nexport * from \"./lib/types\";\nexport * from \"./lib/utils\";\n","import { NodeBase } from \"./api\";\nimport type { Ctor } from \"./types\";\n\nexport class InjectionError extends Error {\n constructor(\n public readonly code: number,\n message: string,\n ) {\n super(`[i${code}] ${message}`);\n this.name = \"InjectionError\";\n }\n\n // Provider errors\n public static duplicate(token: NodeBase<unknown>): InjectionError {\n return new InjectionError(\n 100,\n `Duplicate provider for token \"${token.toString()}\" detected.`,\n );\n }\n public static duplicateFactory(token: NodeBase<unknown>): InjectionError {\n return new InjectionError(\n 101,\n `Tried to re-provide factory for token \"${token.toString()}\" detected.`,\n );\n }\n\n public static invalidCtor(ctor: Ctor<unknown>): InjectionError {\n return new InjectionError(\n 102,\n `Cannot use constructor for token \"${ctor.name}\". Please make sure to use @nodeInjectable() decorator`,\n );\n }\n\n public static invalidProvider(provider: string): InjectionError {\n return new InjectionError(\n 103,\n `Cannot use provider as it is neither a NodeToken nor MultiNodeToken nor a valid constructor.:\\n${provider}`,\n );\n }\n\n // Alias errors\n public static invalidAlias(alias: unknown): InjectionError {\n const aliasStr =\n typeof alias === \"function\" ? (alias as any).name || \"Unknown\" : String(alias);\n return new InjectionError(\n 200,\n `Invalid alias target \"${aliasStr}\". Alias must be a NodeToken, MultiNodeToken, or a class decorated with @NodeInjectable().`,\n );\n }\n\n public static loopAlias(alias: NodeBase<unknown>): InjectionError {\n return new InjectionError(\n 201,\n `Token \"${alias.toString()}\" cannot alias itself in a loop.`,\n );\n }\n\n // Bootstrap errors\n public static notBootstrapped(): InjectionError {\n return new InjectionError(\n 300,\n \"Cannot retrieve providers before the container has been bootstrapped.\",\n );\n }\n\n public static bootstrapped(): InjectionError {\n return new InjectionError(\n 301,\n \"Cannot modify providers after the container has been bootstrapped.\",\n );\n }\n\n public static doubleBootstrap(): InjectionError {\n return new InjectionError(\n 302,\n \"Container has already been bootstrapped and cannot be bootstrapped again.\",\n );\n }\n\n // Retrieval errors\n public static notFound(token: NodeBase<unknown>): InjectionError {\n return new InjectionError(400, `No provider found for \"${token.toString()}\".`);\n }\n\n public static circularDependency(\n provider: NodeBase<unknown> | Ctor<unknown>,\n path: (NodeBase<unknown> | Ctor<unknown>)[],\n ): InjectionError {\n const providerStr =\n provider instanceof NodeBase ? provider.toString() : provider.name;\n const pathStr = path\n .map((p) => (p instanceof NodeBase ? p.toString() : p.name))\n .join(\" -> \");\n\n return new InjectionError(\n 401,\n `Circular dependency detected while resolving \"${providerStr}\":\\n${pathStr}`,\n );\n }\n\n // Instantiation errors\n public static untracked(\n token: NodeBase<unknown> | Ctor<unknown>,\n parent: NodeBase<unknown> | Ctor<unknown>,\n ): InjectionError {\n const tokenStr = token instanceof NodeBase ? token.toString() : token.name;\n const parentStr = parent instanceof NodeBase ? parent.toString() : parent.name;\n return new InjectionError(\n 500,\n `Cannot instantiate ${parentStr} because it depends on untracked injection ${tokenStr}. Please make sure all injections are properly tracked.`,\n );\n }\n\n public static outsideContext(token: NodeBase<unknown> | Ctor<unknown>): InjectionError {\n const tokenStr = token instanceof NodeBase ? token.toString() : token.name;\n return new InjectionError(\n 501,\n `Cannot inject \"${tokenStr}\" outside of an injection context.`,\n );\n }\n\n public static calledUtilsOutsideContext(): InjectionError {\n return new InjectionError(\n 502,\n \"Cannot call injection utilities outside of an injection context.\",\n );\n }\n\n public static instanceAccessFailed(token: NodeBase<unknown>): InjectionError {\n return new InjectionError(\n 503,\n `Failed to access instance for token \"${token.toString()}\". It was not properly instantiated.`,\n );\n }\n\n public static accessFailed(): InjectionError {\n return new InjectionError(\n 504,\n \"Failed to access the requested instance due to an unknown error.\",\n );\n }\n}\n","import { InjectionError } from \"../errors\";\nimport type {\n Ctor,\n iNodeAliasProvider,\n iNodeClassProvider,\n iNodeFactoryProvider,\n iNodeTokenBaseOptions,\n iNodeValueProvider,\n Token,\n} from \"../types\";\nimport { getInjectableToken, isInjectable } from \"./decorator\";\n\n/**\n * Base class for dependency injection tokens.\n * This class should not be instantiated directly. Use {@link NodeToken} or {@link MultiNodeToken} instead.\n *\n * @template T - The type of value this token represents\n */\nexport class NodeBase<T> {\n constructor(\n public readonly name: string,\n public readonly opts?: iNodeTokenBaseOptions<T>,\n ) {}\n\n /** Provides this token with a value */\n public withValue(value: T): iNodeValueProvider<T> {\n return {\n provide: this,\n value,\n };\n }\n\n /** Provides this token using a factory function */\n public withFactory(factory: () => T): iNodeFactoryProvider<T> {\n return {\n provide: this,\n factory,\n };\n }\n\n /** Provides this token using a class constructor */\n public withClass(ctor: Ctor<T>): iNodeClassProvider<T> {\n return {\n provide: this,\n useClass: ctor,\n };\n }\n\n /** Creates an alias to another token */\n public withAlias<K extends T>(alias: Token<K>): iNodeAliasProvider<T> {\n return {\n provide: this,\n alias,\n };\n }\n\n public toString(): string {\n return `Token[${this.name}]`;\n }\n}\n/**\n * A token that represents a single dependency in the dependency injection system.\n * Use this to define injectable dependencies that have exactly one provider.\n *\n * @template T - The type of value this token represents\n *\n * @example\n * ```typescript\n * const LoggerToken = new NodeToken<Logger>('Logger');\n * container.provide({ provide: LoggerToken, useClass: ConsoleLogger });\n * const logger = container.get(LoggerToken);\n * ```\n */\nexport class NodeToken<T> extends NodeBase<T> {\n public readonly multi = false as const;\n\n public override toString(): string {\n return `NodeToken[${this.name}]`;\n }\n}\n\n/**\n * A token that represents multiple dependencies in the dependency injection system.\n * Use this to define injectable dependencies that can have multiple providers.\n * When retrieved, returns an array of all registered providers.\n *\n * @template T - The type of value this token represents\n *\n * @example\n * ```typescript\n * const PluginToken = new MultiNodeToken<Plugin>('Plugins');\n * container.provide({ provide: PluginToken, useClass: PluginA });\n * container.provide({ provide: PluginToken, useClass: PluginB });\n * const plugins = container.get(PluginToken); // [PluginA instance, PluginB instance]\n * ```\n */\nexport class MultiNodeToken<T> extends NodeBase<T> {\n public readonly multi = true as const;\n\n public override toString(): string {\n return `MultiNodeToken[${this.name}]`;\n }\n}\n\n/**\n * Type guard to check if a value is a valid dependency injection token.\n *\n * @template T - The type of value the token represents\n * @param specimen - The value to check\n * @returns True if the specimen is a NodeToken or MultiNodeToken, false otherwise\n * @internal\n */\nexport function isNodeBase<T>(\n specimen: unknown,\n): specimen is NodeToken<T> | MultiNodeToken<T> {\n return specimen instanceof NodeToken || specimen instanceof MultiNodeToken;\n}\n\n/**\n * Extracts a valid NodeBase token from a given provider.\n * If the provider is a class constructor decorated with @NodeInjectable, it retrieves the associated token.\n * If the provider is already a NodeBase token, it returns it directly.\n * Throws an InjectionError if the provider is invalid.\n *\n * @template T - The type of value the token represents\n * @param provider - The provider to extract the token from\n * @param isAlias - Whether the provider is being used as an alias\n * @returns The extracted NodeBase token\n * @throws {InjectionError} If the provider is invalid\n * @internal\n */\nexport function extractToken<T>(\n provider: Token<T>,\n isAlias = false,\n): NodeToken<T> | MultiNodeToken<T> {\n let token: NodeBase<T> | null = null;\n if (isInjectable<T>(provider)) {\n token = getInjectableToken<T>(provider);\n } else if (isNodeBase<T>(provider)) token = provider;\n\n if (!token || !isNodeBase<T>(token)) {\n if (isAlias) throw InjectionError.invalidAlias(provider);\n throw InjectionError.invalidProvider(JSON.stringify(provider));\n }\n\n return token;\n}\n","import type { Ctor } from \"../types\";\nimport { NodeToken } from \"./token\";\n\n/**\n * Symbol used to mark classes as injectable and store their associated token.\n * @internal\n */\nexport const INJECTION_SYMBOL = Symbol(\"Injectable\");\n\n/**\n * Decorator that marks a class as injectable in the dependency injection system.\n * Automatically creates and associates a NodeToken with the class.\n *\n * @template T - The type of the class being decorated\n * @returns A class decorator function\n *\n * @example\n * ```typescript\n * @NodeInjectable()\n * class UserService {\n * public getUser() {\n * return { id: 1, name: 'John' };\n * }\n * }\n *\n * container.provide(UserService);\n * container.bootstrap();\n * const service = container.get(UserService);\n * ```\n */\nexport function NodeInjectable<T>() {\n return (ctor: Ctor<T>): Ctor<T> => {\n const nodeToken = new NodeToken<T>(`_${ctor.name}`, {\n factory: () => new ctor(),\n });\n\n (ctor as any)[INJECTION_SYMBOL] = nodeToken;\n return ctor;\n };\n}\n\n/**\n * Alternative function to mark a class as injectable in the dependency injection system for environments\n * that do not support decorators.\n * @param ctor\n * @returns\n *\n * @example\n * ```typescript\n * import { makeInjectable } from '@illuma/core';\n *\n * class _UserService {\n * public getUser() {\n * return { id: 1, name: \"John Doe\" };\n * }\n * }\n *\n * export type UserService = _UserService;\n * export const UserService = makeInjectable(_UserService);\n * ```\n */\nexport function makeInjectable<T>(ctor: Ctor<T>): Ctor<T> {\n const nodeToken = new NodeToken<T>(`_${ctor.name}`, {\n factory: () => new ctor(),\n });\n\n (ctor as any)[INJECTION_SYMBOL] = nodeToken;\n return ctor;\n}\n\n/** @internal */\nexport function isInjectable<T>(ctor: unknown): ctor is Ctor<T> & {\n [INJECTION_SYMBOL]: NodeToken<T>;\n} {\n return (\n typeof ctor === \"function\" &&\n isConstructor(ctor) &&\n INJECTION_SYMBOL in ctor &&\n ctor[INJECTION_SYMBOL] instanceof NodeToken\n );\n}\n\n/** @internal */\nexport function getInjectableToken<T>(\n ctor: Ctor<T> & { [INJECTION_SYMBOL]: NodeToken<T> },\n): NodeToken<T> {\n return ctor[INJECTION_SYMBOL];\n}\n\nexport function isConstructor(fn: unknown): fn is Ctor<any> {\n return typeof fn === \"function\" && fn.prototype && fn.prototype.constructor === fn;\n}\n","import type { iContextScanner } from \"../context\";\nimport type { iDiagnosticsModule, iDiagnosticsReport } from \"../diagnostics/types\";\n\n/**\n * Global plugin container for managing core plugins such as diagnostics and context scanners.\n */\nexport abstract class Illuma {\n private static readonly _diagnostics = [] as iDiagnosticsModule[];\n private static readonly _scanners = [] as iContextScanner[];\n\n /** @internal */\n public static get contextScanners(): ReadonlyArray<iContextScanner> {\n return Illuma._scanners;\n }\n\n /**\n * Extends the diagnostics with a new diagnostics module.\n * These will be run on diagnostics reports after container bootstrap.\n *\n * @param m - The diagnostics module instance to add\n */\n public static extendDiagnostics(m: iDiagnosticsModule): void {\n Illuma._diagnostics.push(m);\n }\n\n /**\n * Extends the context scanners with a new context scanner.\n * These will be run in injection context scans to detect additional injections (alongside `nodeInject` calls).\n *\n * @param scanner - The context scanner instance to add\n */\n public static extendContextScanner(scanner: iContextScanner): void {\n Illuma._scanners.push(scanner);\n }\n\n protected static onReport(report: iDiagnosticsReport): void {\n for (const diag of Illuma._diagnostics) diag.onReport(report);\n }\n}\n","import type { NodeBase } from \"../api/token\";\nimport { InjectionError } from \"../errors\";\nimport { Illuma } from \"../plugins/core/plugin-container\";\nimport type { iInjectionNode } from \"./node\";\n\n/** @internal */\nexport type InjectorFn = (token: NodeBase<any>, optional?: boolean) => any;\n\n/**\n * Internal context manager for tracking dependency injections during factory execution.\n * This class manages the injection context lifecycle and tracks all injection calls.\n *\n * @internal\n */\nexport abstract class InjectionContext {\n public static contextOpen = false;\n public static readonly _calls = new Set<iInjectionNode<any>>();\n public static injector: InjectorFn | null = null;\n private static readonly _scanners = Illuma.contextScanners;\n\n /**\n * Adds a dependency to the current injection context.\n * Called by `nodeInject` when a dependency is requested.\n *\n * @param node - The injection node representing the dependency\n * @throws {InjectionError} If called outside of an active injection context\n */\n public static addDep(node: iInjectionNode<any>): void {\n if (!InjectionContext.contextOpen) {\n throw InjectionError.calledUtilsOutsideContext();\n }\n\n InjectionContext._calls.add(node);\n }\n\n /**\n * Opens a new injection context.\n * Resets the calls set and sets the injector if provided.\n *\n * @param injector - Optional injector function to use for resolving dependencies\n */\n /**\n * Scans a factory function for dependencies.\n * Executes the factory in a dry-run mode to capture `nodeInject` calls.\n * Also runs registered context scanners.\n *\n * @param factory - The factory function to scan\n * @returns A set of detected injection nodes\n */\n public static open(injector?: InjectorFn): void {\n InjectionContext._calls.clear();\n InjectionContext.contextOpen = true;\n InjectionContext.injector = injector || null;\n }\n\n public static scan(factory: any): Set<iInjectionNode<any>> {\n if (typeof factory !== \"function\") return new Set();\n InjectionContext.open();\n\n try {\n factory();\n } catch {\n // No-op\n }\n\n const scanners = InjectionContext._scanners;\n for (const scanner of scanners) {\n /**\n * Instantiates a value using a factory function within an injection context.\n *\n * @template T - The type of the value being instantiated\n * @param factory - The factory function to execute\n * @param injector - The injector function to resolve dependencies\n * @returns The instantiated value\n */\n const scanned = scanner.scan(factory);\n for (const node of scanned) InjectionContext._calls.add(node);\n }\n\n const injections = InjectionContext.closeAndReport();\n return injections;\n }\n\n public static instantiate<T>(factory: () => T, injector: InjectorFn): T {\n /**\n * Closes the current injection context.\n * Resets the context state and returns the collected dependencies.\n *\n * @returns A set of injection nodes collected during the context session\n */\n InjectionContext.open(injector);\n try {\n return factory();\n } finally {\n InjectionContext.closeAndReport();\n }\n }\n\n public static closeAndReport(): Set<iInjectionNode<any>> {\n const calls = new Set(InjectionContext._calls);\n\n InjectionContext.contextOpen = false;\n InjectionContext._calls.clear();\n InjectionContext.injector = null;\n\n return calls;\n }\n}\n","import { InjectionContext } from \"../context\";\nimport { InjectionError } from \"../errors\";\nimport type { ExtractInjectedType, iNodeInjectorOptions } from \"../types\";\nimport { getInjectableToken, isInjectable } from \"./decorator\";\nimport type { MultiNodeToken, NodeToken } from \"./token\";\nimport { isNodeBase } from \"./token\";\n\n/**\n * Injects a dependency within a factory function or constructor.\n * This function must be called within an injection context (during provider instantiation).\n *\n * @template N - The token or constructor type\n * @param token - The token or class to inject\n * @param options - Optional configuration for the injection\n * @returns The injected instance(s). For MultiNodeToken returns an array, for NodeToken returns a single instance.\n * When optional is true, may return null if the dependency is not found, type-safely.\n * @throws {InjectionError} If called outside an injection context or if a required dependency is not found\n *\n * @example\n * ```typescript\n * const LoggerToken = new NodeToken<Logger>('Logger');\n * const ConfigToken = new NodeToken<Config>('Config');\n *\n * container.provide({\n * provide: UserServiceToken,\n * factory: () => {\n * const logger = nodeInject(LoggerToken);\n * const config = nodeInject(ConfigToken, { optional: true });\n * return new UserService(logger, config);\n * }\n * });\n * ```\n */\nexport function nodeInject<N>(\n token: N,\n options: iNodeInjectorOptions & { optional: true },\n): N extends MultiNodeToken<infer V>\n ? V[]\n : N extends NodeToken<infer U>\n ? U | null\n : N extends new (\n ...args: any[]\n ) => infer T\n ? T | null\n : never;\nexport function nodeInject<N>(\n token: N,\n options?: iNodeInjectorOptions,\n): N extends MultiNodeToken<infer V>\n ? V[]\n : N extends NodeToken<infer U>\n ? U\n : N extends new (\n ...args: any\n ) => infer T\n ? T\n : never;\nexport function nodeInject<N extends NodeToken<unknown> | MultiNodeToken<unknown>>(\n token: N,\n options?: iNodeInjectorOptions,\n): ExtractInjectedType<N>;\nexport function nodeInject<\n N extends\n | NodeToken<unknown>\n | MultiNodeToken<unknown>\n | (new (\n ...args: any[]\n ) => unknown) = NodeToken<unknown>,\n>(provider: N, options?: iNodeInjectorOptions) {\n let token: any = provider;\n if (isInjectable(provider)) token = getInjectableToken(provider);\n\n if (!InjectionContext.contextOpen) {\n throw InjectionError.outsideContext(token);\n }\n\n if (!isNodeBase(token)) throw InjectionError.invalidProvider(String(token));\n\n const injection = { token, optional: options?.optional ?? false };\n InjectionContext.addDep(injection);\n\n if (InjectionContext.injector) {\n return InjectionContext.injector(token, options?.optional);\n }\n\n return injection;\n}\n\n/**\n * Type of the {@link nodeInject} function.\n * @internal\n */\nexport type NodeInjectFn = typeof nodeInject;\n","import type { iDiagnosticsModule, iDiagnosticsReport } from \"./types\";\n\nexport class DiagnosticsDefaultReporter implements iDiagnosticsModule {\n public onReport(report: iDiagnosticsReport): void {\n console.log(\"[Illuma] 🧹 Diagnostics:\");\n console.log(` Total: ${report.totalNodes} node(s)`);\n console.log(` ${report.unusedNodes.length} were not used while bootstrap:`);\n for (const node of report.unusedNodes) console.log(` - ${node.toString()}`);\n }\n}\n","import type { NodeBase } from \"../api\";\nimport { extractToken } from \"../api\";\nimport { InjectionError } from \"../errors\";\nimport type { iNodeProvider } from \"../types\";\n\nexport function extractProvider<T>(provider: iNodeProvider<T>): NodeBase<T> | (() => T) {\n if (\"value\" in provider) return () => provider.value;\n if (\"factory\" in provider) return provider.factory;\n if (\"useClass\" in provider) return () => new provider.useClass();\n if (\"alias\" in provider) return extractToken(provider.alias, true);\n\n throw InjectionError.invalidProvider(JSON.stringify(provider));\n}\n","import type { NodeBase } from \"../api\";\nimport { MultiNodeToken, NodeToken } from \"../api\";\nimport type { iInjectionNode } from \"../context\";\nimport { InjectionContext } from \"../context\";\nimport { InjectionError } from \"../errors\";\n\nexport class ProtoNodeSingle<T = any> {\n // Metadata\n public readonly token: NodeToken<T>;\n public readonly injections: Set<iInjectionNode<any>>;\n\n // Instantiation\n public factory: (() => T) | null = null;\n\n constructor(token: NodeToken<T>, factory?: () => T) {\n this.token = token;\n this.factory = factory ?? null;\n this.injections = factory ? InjectionContext.scan(factory) : new Set();\n }\n\n public hasFactory(): boolean {\n return typeof this.factory === \"function\";\n }\n\n public setFactory(factory: () => T): void {\n if (this.factory) throw InjectionError.duplicateFactory(this.token);\n this.factory = factory;\n\n const scanned = InjectionContext.scan(factory);\n for (const injection of scanned) {\n this.injections.add(injection);\n }\n }\n\n public toString(): string {\n return `ProtoNodeSingle<${this.token.toString()}>`;\n }\n}\n\nexport class ProtoNodeTransparent<T = any> {\n public readonly factory: () => T;\n public readonly injections: Set<iInjectionNode<any>>;\n\n constructor(\n public readonly parent: ProtoNodeSingle<T> | ProtoNodeMulti<T>,\n factory: () => T,\n ) {\n this.factory = factory;\n this.injections = InjectionContext.scan(factory);\n }\n\n public toString(): string {\n return `ProtoNodeTransparent<${this.factory.name || \"anonymous\"}>`;\n }\n}\n\nexport class ProtoNodeMulti<T = any> {\n public readonly token: MultiNodeToken<T>;\n public readonly singleNodes = new Set<NodeToken<T>>();\n public readonly multiNodes = new Set<MultiNodeToken<T>>();\n public readonly transparentNodes = new Set<ProtoNodeTransparent<T>>();\n\n constructor(token: MultiNodeToken<T>) {\n this.token = token;\n }\n\n public addProvider(retriever: NodeBase<T> | (() => T)): void {\n if (retriever instanceof NodeToken) {\n this.singleNodes.add(retriever);\n } else if (retriever instanceof MultiNodeToken) {\n this.multiNodes.add(retriever);\n } else if (typeof retriever === \"function\") {\n const transparentProto = new ProtoNodeTransparent<T>(this, retriever);\n this.transparentNodes.add(transparentProto);\n }\n }\n\n public toString(): string {\n return `ProtoNodeMulti<${this.token.toString()}>`;\n }\n}\n\nexport type ProtoNode<T = any> =\n | ProtoNodeSingle<T>\n | ProtoNodeMulti<T>\n | ProtoNodeTransparent<T>;\n\nexport function isNotTransparentProto(\n proto: ProtoNode,\n): proto is ProtoNodeSingle | ProtoNodeMulti {\n return !(proto instanceof ProtoNodeTransparent);\n}\n","import type { NodeBase } from \"../api\";\nimport { InjectionContext } from \"../context\";\nimport { InjectionError } from \"../errors\";\nimport type { ProtoNodeMulti, ProtoNodeSingle, ProtoNodeTransparent } from \"./proto\";\n\nexport type DependencyPool = Map<NodeBase<any>, TreeNode<any>>;\n\nfunction retrieverFactory<T>(\n node: NodeBase<T>,\n deps: DependencyPool,\n transparentDeps: Set<TreeNodeTransparent>,\n) {\n return (token: NodeBase<T>, optional: boolean | undefined): T | null => {\n const depNode = deps.get(token);\n if (!depNode && !optional) {\n const transparent = Array.from(transparentDeps).find(\n (n) => \"proto\" in n && n.proto.parent.token === token,\n );\n if (transparent) return transparent.instance;\n throw InjectionError.untracked(token, node);\n }\n\n return depNode?.instance ?? null;\n };\n}\n\n// Tree Nodes\nexport class TreeRootNode {\n private readonly _deps: Set<TreeNode<any>> = new Set();\n private readonly _treePool: DependencyPool = new Map();\n\n public get dependencies(): Set<TreeNode<any>> {\n return this._deps;\n }\n\n public addDependency(node: TreeNode<any>): void {\n this._deps.add(node);\n }\n\n public instantiate(): void {\n for (const dep of this._deps) {\n dep.instantiate(this._treePool);\n if (\"token\" in dep.proto) this._treePool.set(dep.proto.token, dep);\n }\n }\n\n public find<T>(token: NodeBase<T>): TreeNode<T> | null {\n const node = this._treePool.get(token);\n if (!node) return null;\n return node as TreeNode<T>;\n }\n\n public toString(): string {\n return \"TreeRootNode\";\n }\n}\n\nexport class TreeNodeSingle<T = any> {\n private readonly _transparent: Set<TreeNodeTransparent> = new Set();\n private readonly _deps: DependencyPool = new Map();\n private _instance: T | null = null;\n private _resolved = false;\n public allocations = 0;\n\n public get instance(): T {\n if (!this._resolved) {\n throw InjectionError.instanceAccessFailed(this.proto.token);\n }\n\n return this._instance as T;\n }\n\n constructor(public readonly proto: ProtoNodeSingle<T>) {}\n\n public addDependency(node: TreeNode<any>): void {\n if (node instanceof TreeNodeTransparent) this._transparent.add(node);\n else this._deps.set(node.proto.token, node);\n node.allocations++;\n }\n\n public instantiate(pool?: DependencyPool): void {\n if (this._resolved) return;\n\n for (const node of this._deps.values()) node.instantiate(pool);\n for (const dep of this._transparent) dep.instantiate(pool);\n\n const retriever = retrieverFactory(this.proto.token, this._deps, this._transparent);\n const factory = this.proto.factory ?? this.proto.token.opts?.factory;\n if (!factory) throw InjectionError.notFound(this.proto.token);\n this._instance = InjectionContext.instantiate(factory, retriever);\n\n this._resolved = true;\n if (pool) pool.set(this.proto.token, this);\n }\n\n public toString(): string {\n return `TreeNodeSingle<${this.proto.token.toString()}>`;\n }\n}\n\nexport class TreeNodeTransparent<T = any> {\n private readonly _transparent = new Set<TreeNodeTransparent>();\n private readonly _deps: DependencyPool = new Map();\n private _instance: T | null = null;\n private _resolved = false;\n public allocations = 0;\n\n public get instance(): T {\n if (!this._resolved) throw InjectionError.accessFailed();\n return this._instance as T;\n }\n\n constructor(public readonly proto: ProtoNodeTransparent<T>) {}\n\n public addDependency(node: TreeNode<any>): void {\n if (node instanceof TreeNodeTransparent) this._transparent.add(node);\n else this._deps.set(node.proto.token, node);\n\n node.allocations++;\n }\n\n public instantiate(pool?: DependencyPool): void {\n if (this._resolved) return;\n\n for (const dep of this._transparent) dep.instantiate(pool);\n for (const node of this._deps.values()) node.instantiate(pool);\n\n const retriever = retrieverFactory(\n this.proto.parent.token,\n this._deps,\n this._transparent,\n );\n\n this._instance = InjectionContext.instantiate(this.proto.factory, retriever);\n this._resolved = true;\n }\n\n public toString(): string {\n return `TreeNodeTransparent<${this.proto.parent.token.toString()}>`;\n }\n}\n\nexport class TreeNodeMulti<T = any> {\n private readonly _deps = new Set<TreeNode<any>>();\n public readonly instance: T[] = [];\n private _resolved = false;\n public allocations = 0;\n\n constructor(public readonly proto: ProtoNodeMulti<T>) {}\n\n public instantiate(pool?: DependencyPool): void {\n if (this._resolved) return;\n\n for (const dep of this._deps) {\n dep.instantiate(pool);\n\n if (dep instanceof TreeNodeSingle) {\n this.instance.push(dep.instance);\n } else if (dep instanceof TreeNodeMulti) {\n this.instance.push(...dep.instance);\n } else if (dep instanceof TreeNodeTransparent) {\n this.instance.push(dep.instance);\n }\n }\n\n this._resolved = true;\n if (pool) pool.set(this.proto.token, this);\n }\n\n public addDependency(...nodes: TreeNode[]): void {\n for (const node of nodes) {\n this._deps.add(node);\n node.allocations++;\n }\n }\n\n public toString(): string {\n return `TreeNodeMulti<${this.proto.token.toString()}>`;\n }\n}\n\nexport type TreeNode<T = any> =\n | TreeNodeSingle<T>\n | TreeNodeMulti<T>\n | TreeNodeTransparent<T>;\n","import type { NodeBase } from \"../api\";\nimport { getInjectableToken, isInjectable, MultiNodeToken, NodeToken } from \"../api\";\nimport { InjectionError } from \"../errors\";\nimport type { Token } from \"../types\";\nimport type { ProtoNode } from \"./proto\";\nimport {\n isNotTransparentProto,\n ProtoNodeMulti,\n ProtoNodeSingle,\n ProtoNodeTransparent,\n} from \"./proto\";\nimport type { TreeNode } from \"./tree-node\";\nimport { TreeNodeMulti, TreeNodeSingle, TreeNodeTransparent } from \"./tree-node\";\n\nexport type UpstreamGetter = <T>(token: Token<T>) => TreeNode<T> | null;\ninterface StackFrame {\n readonly proto: ProtoNode;\n readonly node: TreeNode;\n processed: boolean;\n}\n\nfunction createTreeNode(p: ProtoNode): TreeNode {\n if (p instanceof ProtoNodeSingle) return new TreeNodeSingle(p);\n if (p instanceof ProtoNodeMulti) return new TreeNodeMulti(p);\n if (p instanceof ProtoNodeTransparent) return new TreeNodeTransparent(p);\n throw new Error(\"Unknown ProtoNode type\");\n}\n\nexport function resolveTreeNode<T>(\n rootProto: ProtoNode<T>,\n cache: Map<ProtoNode, TreeNode>,\n singleNodes: Map<NodeToken<any>, ProtoNodeSingle>,\n multiNodes: Map<MultiNodeToken<any>, ProtoNodeMulti>,\n upstreamGetter?: UpstreamGetter,\n): TreeNode<T> {\n const inCache = cache.get(rootProto);\n if (inCache) return inCache;\n\n const rootNode = createTreeNode(rootProto);\n\n const stack: StackFrame[] = [{ proto: rootProto, node: rootNode, processed: false }];\n const visiting = new Set<ProtoNode>();\n\n while (stack.length > 0) {\n const frame = stack[stack.length - 1];\n const { proto, node } = frame;\n\n if (frame.processed) {\n stack.pop();\n visiting.delete(proto);\n cache.set(proto, node);\n continue;\n }\n\n if (visiting.has(proto) && isNotTransparentProto(proto)) {\n const path = stack.map((f) => f.proto).filter((p) => isNotTransparentProto(p));\n const index = path.indexOf(proto);\n const cycle = path.slice(index);\n const cycleTokens = cycle.map((p) => p.token);\n throw InjectionError.circularDependency(proto.token, cycleTokens);\n }\n\n visiting.add(proto);\n frame.processed = true;\n\n const deps: (ProtoNode | TreeNode)[] = [];\n\n function addDependency(token: Token<any>, optional = false) {\n if (token instanceof NodeToken) {\n const p = singleNodes.get(token);\n if (p) {\n deps.push(p);\n return;\n }\n } else if (token instanceof MultiNodeToken) {\n const p = multiNodes.get(token);\n if (p) {\n deps.push(p);\n return;\n }\n }\n\n const upstream = upstreamGetter?.(token);\n if (upstream) {\n deps.push(upstream);\n return;\n }\n\n if (!optional) {\n if (isInjectable(token)) {\n const nodeToken = getInjectableToken(token);\n throw InjectionError.notFound(nodeToken);\n }\n\n throw InjectionError.notFound(token as NodeBase<any>);\n }\n }\n\n if (proto instanceof ProtoNodeSingle || proto instanceof ProtoNodeTransparent) {\n for (const injection of proto.injections) {\n addDependency(injection.token, injection.optional);\n }\n }\n\n if (proto instanceof ProtoNodeMulti) {\n const parentNodes = upstreamGetter?.(proto.token);\n if (parentNodes instanceof TreeNodeMulti) {\n node.addDependency(parentNodes);\n }\n\n for (const single of proto.singleNodes) {\n let p = singleNodes.get(single);\n if (!p) {\n p = new ProtoNodeSingle(single);\n singleNodes.set(single, p);\n }\n\n deps.push(p);\n }\n\n for (const multi of proto.multiNodes) {\n let p = multiNodes.get(multi);\n if (!p) {\n p = new ProtoNodeMulti(multi);\n multiNodes.set(multi, p);\n }\n deps.push(p);\n }\n\n for (const transparent of proto.transparentNodes) {\n deps.push(transparent);\n }\n }\n\n for (const dep of deps) {\n if (\n dep instanceof TreeNodeSingle ||\n dep instanceof TreeNodeMulti ||\n dep instanceof TreeNodeTransparent\n ) {\n node.addDependency(dep);\n continue;\n }\n\n const depProto = dep as ProtoNode;\n\n const cached = cache.get(depProto);\n if (cached) {\n node.addDependency(cached);\n continue;\n }\n\n if (visiting.has(depProto) && isNotTransparentProto(depProto)) {\n const path = stack.map((f) => f.proto).filter((p) => isNotTransparentProto(p));\n const index = path.indexOf(depProto);\n const cycle = [...path.slice(index), depProto];\n const cycleTokens = cycle.map((p) => p.token);\n\n throw InjectionError.circularDependency(depProto.token, cycleTokens);\n }\n\n const childNode = createTreeNode(depProto);\n node.addDependency(childNode);\n stack.push({ proto: depProto, node: childNode, processed: false });\n }\n }\n\n return rootNode;\n}\n","import type { MultiNodeToken } from \"../api\";\nimport { NodeToken } from \"../api/token\";\nimport type { Ctor, iDIContainer, Token } from \"../types\";\n\nexport interface iInjector {\n /** The DI container associated with this injector */\n readonly container: iDIContainer;\n\n /**\n * Retrieves an instance for the given token.\n * @template T - The type of value being retrieved\n * @param token - The token or constructor to retrieve\n * @returns The resolved instance\n */\n get<T>(token: MultiNodeToken<T>): T[];\n get<T>(token: NodeToken<T>): T;\n get<T>(token: Ctor<T>): T;\n\n /**\n * Instantiates a class with injections in runtime using current context.\n * Useful when creating an object that requires injections in runtime.\n * Class does not get registered in the container and cannot be retrieved via {@link get} or {@link nodeInject}.\n *\n * @template T - The type of the class being instantiated\n * @param ctor - The constructor of the class to instantiate\n * @returns A new instance of the class with dependencies injected\n * @throws {InjectionError} If called before bootstrap or if the constructor is invalid\n * Must be called after {@link bootstrap}.\n */\n produce<T>(fn: Ctor<T> | (() => T)): T;\n}\n\n/**\n * Injector implementation that allows retrieving instances from the parent DI container.\n */\nexport class InjectorImpl implements iInjector {\n constructor(public readonly container: iDIContainer) {}\n\n public get<T>(token: MultiNodeToken<T>): T[];\n public get<T>(token: NodeToken<T>): T;\n public get<T>(token: Ctor<T>): T;\n public get<T>(token: Token<T>): T | T[] {\n return this.container.get<T>(token as any);\n }\n\n public produce<T>(fn: Ctor<T> | (() => T)): T {\n return this.container.produce<T>(fn);\n }\n}\n\n/**\n * Injector node that is used to access provider outside of injection context.\n * @example\n * ```typescript\n * import { Injector, nodeInject, NodeInjectable, NodeContainer } from \"@illuma/core\";\n *\n * @NodeInjectable()\n * class MyService {\n * private readonly _injector = nodeInject(Injector);\n * public doSomething() {\n * const otherService = this._injector.get(OtherService);\n * // Use otherService...\n * }\n * }\n * ```\n */\nexport const Injector = new NodeToken<iInjector>(\"Injector\");\n","import type { MultiNodeToken, NodeToken } from \"../api\";\nimport { extractToken, nodeInject } from \"../api\";\nimport { NodeContainer } from \"../container\";\nimport type { Ctor, Provider, Token } from \"../types\";\nimport type { iInjector } from \"./injector\";\nimport { Injector } from \"./injector\";\n\ntype MaybeAsyncFactory<T> = () => T | Promise<T>;\ninterface iInjectionOptions {\n /**\n * Whether to cache the result of the injection function\n * Prevents multiple invocations from creating multiple sub-containers or injections\n * @default true\n */\n withCache?: boolean;\n /**\n * Overrides to provide to the sub-container\n * These will be provided in addition to the main injection\n * @default []\n */\n overrides?: Provider[];\n}\n\n/**\n * Creates an async function that injects a group of dependencies as a sub-container.\n * The returned function, when called, will create a new sub-container, provide the given dependencies,\n * bootstrap it, and return its injector.\n *\n * @note\n * `injectGroupAsync` should be called within an injection context where the parent container is accessible.\n *\n * @param fn - A function that returns an array of providers or a promise resolving to one\n * @returns A function that returns a promise resolving to the injector of the sub-container\n */\nexport function injectGroupAsync(\n fn: MaybeAsyncFactory<Provider[]>,\n opts?: iInjectionOptions,\n): () => Promise<iInjector> {\n const { container: parent } = nodeInject(Injector);\n const factory = async () => {\n const providers = await fn();\n\n const subContainer = new NodeContainer({ parent });\n\n if (opts?.overrides) subContainer.provide(opts.overrides);\n subContainer.provide(providers);\n subContainer.bootstrap();\n\n return subContainer.get(Injector);\n };\n\n const withCache = opts?.withCache ?? true;\n if (!withCache) return factory;\n\n let cache: Promise<iInjector> | null = null;\n return () => {\n cache ??= factory();\n return cache;\n };\n}\n\n/**\n * Creates an async function that injects a dependency for the given token or constructor.\n * The returned function, when called, will create a new sub-container,\n * provide the token or constructor, bootstrap it, and return the resolved instance(s).\n *\n * @note\n * `injectAsync` should be called within an injection context where the parent container is accessible.\n *\n * @template T - The type of value being injected\n * @param fn - A function that returns a token, constructor, or a promise resolving to one\n * @returns A function that returns a promise resolving to the injected instance(s)\n */\nexport function injectAsync<T>(\n fn: MaybeAsyncFactory<MultiNodeToken<T>>,\n opts?: iInjectionOptions,\n): () => Promise<T[]>;\nexport function injectAsync<T>(\n fn: MaybeAsyncFactory<NodeToken<T>>,\n opts?: iInjectionOptions,\n): () => Promise<T>;\nexport function injectAsync<T>(\n fn: MaybeAsyncFactory<Ctor<T>>,\n opts?: iInjectionOptions,\n): () => Promise<T>;\nexport function injectAsync<T>(\n fn: MaybeAsyncFactory<Token<T>>,\n opts?: iInjectionOptions,\n): () => Promise<T | T[]> {\n const { container: parent } = nodeInject(Injector);\n const factory = (async () => {\n const token = await fn();\n const tempContainer = new NodeContainer({ parent });\n\n if (opts?.overrides) tempContainer.provide(opts.overrides);\n tempContainer.provide(token);\n tempContainer.bootstrap();\n\n return tempContainer.get(extractToken(token) as any);\n }) as () => Promise<T | T[]>;\n\n const withCache = opts?.withCache ?? true;\n if (!withCache) return factory;\n\n let cache: Promise<T | T[]> | null = null;\n return () => {\n cache ??= factory();\n return cache;\n };\n}\n\nexport interface iEntrypointConfig<T extends Token<any>> {\n readonly entrypoint: T;\n readonly providers: Provider[];\n}\n\n/**\n * Creates an async function that injects a sub-container with a specific entrypoint.\n * The returned function, when called, will create a new sub-container,\n * provide the given providers, bootstrap it, and return the resolved instance(s) of the entrypoint.\n *\n * @note\n * `injectEntryAsync` should be called within an injection context where the parent container is accessible.\n *\n * @template T - The type of the entrypoint token\n * @param fn - A function that returns an entrypoint configuration or a promise resolving to one\n * @returns A function that returns a promise resolving to the injected instance(s) of the entrypoint\n */\nexport function injectEntryAsync<T>(\n fn: MaybeAsyncFactory<iEntrypointConfig<NodeToken<T>>>,\n opts?: iInjectionOptions,\n): () => Promise<T[]>;\nexport function injectEntryAsync<T>(\n fn: MaybeAsyncFactory<iEntrypointConfig<Ctor<T>>>,\n opts?: iInjectionOptions,\n): () => Promise<T>;\nexport function injectEntryAsync<T>(\n fn: MaybeAsyncFactory<iEntrypointConfig<MultiNodeToken<T>>>,\n opts?: iInjectionOptions,\n): () => Promise<T>;\nexport function injectEntryAsync<T>(\n fn: MaybeAsyncFactory<iEntrypointConfig<Token<T>>>,\n opts?: iInjectionOptions,\n): () => Promise<T | T[]> {\n const { container: parent } = nodeInject(Injector);\n const factory = (async () => {\n const { entrypoint, providers } = await fn();\n\n const subContainer = new NodeContainer({ parent });\n\n if (opts?.overrides) subContainer.provide(opts.overrides);\n subContainer.provide(providers);\n subContainer.bootstrap();\n\n return subContainer.get(extractToken(entrypoint) as any);\n }) as () => Promise<T | T[]>;\n\n const withCache = opts?.withCache ?? true;\n if (!withCache) return factory;\n\n let cache: Promise<T | T[]> | null = null;\n return () => {\n cache ??= factory();\n return cache;\n };\n}\n","import type { NodeBase } from \"../api\";\nimport {\n extractToken,\n getInjectableToken,\n isInjectable,\n isNodeBase,\n MultiNodeToken,\n NodeToken,\n nodeInject,\n} from \"../api\";\nimport { isConstructor } from \"../api/decorator\";\nimport { InjectionContext } from \"../context\";\nimport { InjectionError } from \"../errors\";\nimport { Illuma } from \"../plugins/core/plugin-container\";\nimport { DiagnosticsDefaultReporter } from \"../plugins/diagnostics/default-impl\";\nimport type { ProtoNode, TreeNode, UpstreamGetter } from \"../provider\";\nimport {\n extractProvider,\n ProtoNodeMulti,\n ProtoNodeSingle,\n resolveTreeNode,\n TreeRootNode,\n} from \"../provider\";\nimport type { Ctor, iDIContainer, iNodeProvider, Provider, Token } from \"../types\";\nimport { Injector, InjectorImpl } from \"../utils\";\n\n/**\n * Configuration options for the NodeContainer.\n */\nexport interface iContainerOptions {\n /**\n * When true, logs the bootstrap time to the console based on performance.now()\n * difference before and after bootstrap.\n * @default false\n */\n measurePerformance?: boolean;\n diagnostics?: boolean;\n parent?: iDIContainer;\n}\n\nexport class NodeContainer extends Illuma implements iDIContainer {\n private _bootstrapped = false;\n private _rootNode?: TreeRootNode;\n\n private readonly _parent?: iDIContainer;\n private readonly _protoNodes = new Map<NodeToken<any>, ProtoNodeSingle<any>>();\n private readonly _multiProtoNodes = new Map<MultiNodeToken<any>, ProtoNodeMulti<any>>();\n\n constructor(private readonly _opts?: iContainerOptions) {\n super();\n\n this._parent = _opts?.parent;\n if (_opts?.diagnostics) {\n Illuma.extendDiagnostics(new DiagnosticsDefaultReporter());\n }\n }\n\n /**\n * Registers a provider in the container.\n * Must be called before {@link bootstrap}.\n *\n * @template T - The type of value being provided\n * @param provider - The provider configuration (token, class, or provider object)\n * @throws {InjectionError} If called after bootstrap or if a duplicate provider is detected\n *\n * @example\n * ```typescript\n * // Provide a value\n * container.provide({ provide: CONFIG_TOKEN, value: { apiKey: '123' } });\n *\n * // Provide a factory\n * container.provide({ provide: LOGGER_TOKEN, factory: () => new ConsoleLogger() });\n *\n * // Provide an injectable class directly\n * container.provide(UserService);\n *\n * // Provide a class override\n * container.provide({ provide: ServiceClass, useClass: ServiceOverride });\n * ```\n */\n public provide<T>(provider: Provider<T>): void {\n if (this._bootstrapped) {\n throw InjectionError.bootstrapped();\n }\n\n if (Array.isArray(provider)) {\n for (const item of provider) this.provide(item);\n return;\n }\n\n // Handle node token declarations\n if (provider instanceof MultiNodeToken) {\n if (this._multiProtoNodes.has(provider)) {\n throw InjectionError.duplicate(provider);\n }\n\n const newProto = new ProtoNodeMulti<T>(provider);\n this._multiProtoNodes.set(provider, newProto);\n return;\n }\n\n // Handle multi node token declarations\n if (provider instanceof NodeToken) {\n if (this._protoNodes.has(provider)) {\n throw InjectionError.duplicate(provider);\n }\n\n const proto = new ProtoNodeSingle<T>(provider);\n this._protoNodes.set(provider, proto);\n return;\n }\n\n // Handle constructors\n if (typeof provider === \"function\") {\n if (!isInjectable<T>(provider)) throw InjectionError.invalidCtor(provider);\n\n const token = getInjectableToken<T>(provider);\n if (!(token instanceof NodeToken)) throw InjectionError.invalidCtor(provider);\n\n const existing = this._protoNodes.get(token);\n if (existing?.hasFactory()) throw InjectionError.duplicate(token);\n\n const factory = token.opts?.factory ?? (() => new provider());\n if (existing) {\n existing.setFactory(factory);\n return;\n }\n\n const proto = new ProtoNodeSingle<T>(token, factory);\n this._protoNodes.set(token, proto);\n return;\n }\n\n // Extract token and retriever from provider object or constructor\n const obj = provider as iNodeProvider<T>;\n const token = extractToken(obj.provide);\n const retriever = extractProvider<T>(obj);\n\n if (token instanceof MultiNodeToken) {\n const multiProto = this._multiProtoNodes.get(token);\n if (multiProto) {\n multiProto.addProvider(retriever);\n return;\n }\n\n const newProto = new ProtoNodeMulti<T>(token);\n this._multiProtoNodes.set(token, newProto);\n newProto.addProvider(retriever);\n return;\n }\n\n if (token instanceof NodeToken) {\n const existing = this._protoNodes.get(token);\n if (existing?.hasFactory()) throw InjectionError.duplicate(token);\n\n let factory: (() => T) | undefined;\n if (typeof retriever === \"function\") factory = retriever;\n if (isNodeBase<T>(retriever)) {\n if (retriever === token) throw InjectionError.loopAlias(token);\n factory = () => nodeInject<NodeBase<T>>(retriever);\n }\n\n if (existing && factory) {\n existing.setFactory(factory);\n return;\n }\n\n const proto = new ProtoNodeSingle<T>(token, factory);\n this._protoNodes.set(token, proto);\n return;\n }\n\n throw InjectionError.invalidProvider(JSON.stringify(provider));\n }\n\n public findNode<T>(token: Token<T>): TreeNode<T> | null {\n if (!this._rootNode) return null;\n if (!this._bootstrapped) return null;\n\n if (isInjectable<T>(token)) {\n const node = getInjectableToken<T>(token);\n return this._rootNode.find(node);\n }\n\n const treeNode = this._rootNode.find(token as NodeBase<T>);\n return treeNode;\n }\n\n private _getFromParent<T>(token: Token<T>): TreeNode<T> | null {\n if (!this._parent) return null;\n const parentNode = this._parent as NodeContainer;\n return parentNode.findNode(token);\n }\n\n private _buildInjectionTree(): TreeRootNode {\n const root = new TreeRootNode();\n const cache = new Map<ProtoNode, TreeNode>();\n\n const nodes: ProtoNode[] = [\n ...this._protoNodes.values(),\n ...this._multiProtoNodes.values(),\n ];\n\n const upstreamGetter: UpstreamGetter = this._getFromParent.bind(this);\n\n for (const node of nodes) {\n if (cache.has(node)) continue;\n\n const treeNode = resolveTreeNode(\n node,\n cache,\n this._protoNodes,\n this._multiProtoNodes,\n upstreamGetter,\n );\n\n root.addDependency(treeNode);\n }\n\n cache.clear();\n this._protoNodes.clear();\n this._multiProtoNodes.clear();\n\n return root;\n }\n\n /**\n * Bootstraps the container by resolving the dependency trees and instantiating all providers.\n * This must be called after all providers are registered and before calling {@link get}.\n *\n * The bootstrap process:\n * 1. Validates all provider registrations\n * 2. Builds dependency injection trees\n * 3. Detects circular dependencies in each tree\n * 4. Instantiates all dependencies in the correct order\n *\n * @throws {InjectionError} If the container is already bootstrapped or if circular dependencies are detected\n *\n * @example\n * ```typescript\n * const container = new NodeContainer();\n * container.provide(UserService);\n * container.provide(LoggerService);\n * container.bootstrap(); // Resolves and instantiates all dependencies\n * ```\n */\n public bootstrap(): void {\n if (this._bootstrapped) throw InjectionError.doubleBootstrap();\n\n const start = performance.now();\n\n this.provide({\n provide: Injector,\n value: new InjectorImpl(this),\n });\n\n this._rootNode = this._buildInjectionTree();\n this._rootNode.instantiate();\n this._bootstrapped = true;\n\n const end = performance.now();\n const duration = end - start;\n if (this._opts?.measurePerformance) {\n console.log(`[Illuma] 🚀 Bootstrapped in ${duration.toFixed(2)} ms`);\n }\n\n if (this._opts?.diagnostics) {\n const allNodes = this._rootNode.dependencies.size;\n const unusedNodes = Array.from(this._rootNode.dependencies)\n .filter((node) => node.allocations === 0)\n .filter((node) => {\n if (!(node.proto instanceof ProtoNodeSingle)) return true;\n return node.proto.token !== Injector;\n });\n\n Illuma.onReport({\n totalNodes: allNodes,\n unusedNodes: unusedNodes,\n bootstrapDuration: duration,\n });\n }\n }\n\n /**\n * Retrieves an instance from the container.\n * Must be called after {@link bootstrap}.\n *\n * @template T - The type of value being retrieved (typically inferred)\n * @param token - The token or class to retrieve\n * @returns For NodeToken: a single instance. For MultiNodeToken: an array of instances.\n * @throws {InjectionError} If called before bootstrap or if the token is not found\n *\n * @example\n * ```typescript\n * // Get a single provider\n * const logger = container.get(LoggerToken);\n *\n * // Get a decorated class\n * const service = container.get(UserService);\n *\n * // Get multiple providers\n * const plugins = container.get(PluginToken); // Returns array\n * ```\n */\n public get<T>(token: MultiNodeToken<T>): T[];\n public get<T>(token: NodeToken<T>): T;\n public get<T>(token: Ctor<T>): T;\n public get<T>(provider: Token<T>): T | T[] {\n if (!this._bootstrapped || !this._rootNode) {\n throw InjectionError.notBootstrapped();\n }\n\n let token: NodeBase<T> | null = null;\n if (typeof provider === \"function\") {\n if (!isInjectable<T>(provider)) throw InjectionError.invalidCtor(provider);\n token = getInjectableToken<T>(provider);\n }\n\n if (isNodeBase<T>(provider)) token = provider;\n\n if (!token) {\n throw InjectionError.invalidProvider(JSON.stringify(provider));\n }\n\n const treeNode = this._rootNode.find(token);\n if (!treeNode) {\n const upstream = this._getFromParent(token);\n if (upstream) return upstream.instance;\n\n if (token instanceof MultiNodeToken) return [];\n throw InjectionError.notFound(token);\n }\n\n return treeNode.instance;\n }\n\n /**\n * Instantiates a class outside injection context. Primarily used to create instances via Injector.\n * Class does not get registered in the container and cannot be retrieved via {@link get} or {@link nodeInject}.\n * Must be called after {@link bootstrap}.\n *\n * @template T - The type of the class being instantiated\n * @param factory - Factory or class constructor to instantiate\n * @returns A new instance of the class with dependencies injected\n * @throws {InjectionError} If called before bootstrap or if the constructor is invalid\n */\n public produce<T>(fn: Ctor<T> | (() => T)): T {\n if (!this._bootstrapped || !this._rootNode) {\n throw InjectionError.notBootstrapped();\n }\n\n if (typeof fn !== \"function\") throw InjectionError.invalidCtor(fn);\n if (isConstructor(fn) && !isInjectable<T>(fn)) {\n throw InjectionError.invalidCtor(fn);\n }\n\n const factory = isInjectable<T>(fn) ? () => new fn() : (fn as () => T);\n\n return InjectionContext.instantiate(factory, (t, optional) => {\n if (!this._rootNode) throw InjectionError.notBootstrapped();\n const node = this._rootNode.find<T>(t);\n if (!node && !optional) throw InjectionError.notFound(t);\n\n return node ? node.instance : null;\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;ACGO,IAAMA,iBAAN,MAAMA,wBAAuBC,MAAAA;EAHpC,OAGoCA;;;;EAClC,YACkBC,MAChBC,SACA;AACA,UAAM,KAAKD,IAAAA,KAASC,OAAAA,EAAS,GAAA,KAHbD,OAAAA;AAIhB,SAAKE,OAAO;EACd;;EAGA,OAAcC,UAAUC,OAA0C;AAChE,WAAO,IAAIN,gBACT,KACA,iCAAiCM,MAAMC,SAAQ,CAAA,aAAe;EAElE;EACA,OAAcC,iBAAiBF,OAA0C;AACvE,WAAO,IAAIN,gBACT,KACA,0CAA0CM,MAAMC,SAAQ,CAAA,aAAe;EAE3E;EAEA,OAAcE,YAAYC,MAAqC;AAC7D,WAAO,IAAIV,gBACT,KACA,qCAAqCU,KAAKN,IAAI,wDAAwD;EAE1G;EAEA,OAAcO,gBAAgBC,UAAkC;AAC9D,WAAO,IAAIZ,gBACT,KACA;EAAkGY,QAAAA,EAAU;EAEhH;;EAGA,OAAcC,aAAaC,OAAgC;AACzD,UAAMC,WACJ,OAAOD,UAAU,aAAcA,MAAcV,QAAQ,YAAYY,OAAOF,KAAAA;AAC1E,WAAO,IAAId,gBACT,KACA,yBAAyBe,QAAAA,4FAAoG;EAEjI;EAEA,OAAcE,UAAUH,OAA0C;AAChE,WAAO,IAAId,gBACT,KACA,UAAUc,MAAMP,SAAQ,CAAA,kCAAoC;EAEhE;;EAGA,OAAcW,kBAAkC;AAC9C,WAAO,IAAIlB,gBACT,KACA,uEAAA;EAEJ;EAEA,OAAcmB,eAA+B;AAC3C,WAAO,IAAInB,gBACT,KACA,oEAAA;EAEJ;EAEA,OAAcoB,kBAAkC;AAC9C,WAAO,IAAIpB,gBACT,KACA,2EAAA;EAEJ;;EAGA,OAAcqB,SAASf,OAA0C;AAC/D,WAAO,IAAIN,gBAAe,KAAK,0BAA0BM,MAAMC,SAAQ,CAAA,IAAM;EAC/E;EAEA,OAAce,mBACZV,UACAW,MACgB;AAChB,UAAMC,cACJZ,oBAAoBa,WAAWb,SAASL,SAAQ,IAAKK,SAASR;AAChE,UAAMsB,UAAUH,KACbI,IAAI,CAACC,MAAOA,aAAaH,WAAWG,EAAErB,SAAQ,IAAKqB,EAAExB,IAAI,EACzDyB,KAAK,MAAA;AAER,WAAO,IAAI7B,gBACT,KACA,iDAAiDwB,WAAAA;EAAkBE,OAAAA,EAAS;EAEhF;;EAGA,OAAcI,UACZxB,OACAyB,QACgB;AAChB,UAAMC,WAAW1B,iBAAiBmB,WAAWnB,MAAMC,SAAQ,IAAKD,MAAMF;AACtE,UAAM6B,YAAYF,kBAAkBN,WAAWM,OAAOxB,SAAQ,IAAKwB,OAAO3B;AAC1E,WAAO,IAAIJ,gBACT,KACA,sBAAsBiC,SAAAA,8CAAuDD,QAAAA,yDAAiE;EAElJ;EAEA,OAAcE,eAAe5B,OAA0D;AACrF,UAAM0B,WAAW1B,iBAAiBmB,WAAWnB,MAAMC,SAAQ,IAAKD,MAAMF;AACtE,WAAO,IAAIJ,gBACT,KACA,kBAAkBgC,QAAAA,oCAA4C;EAElE;EAEA,OAAcG,4BAA4C;AACxD,WAAO,IAAInC,gBACT,KACA,kEAAA;EAEJ;EAEA,OAAcoC,qBAAqB9B,OAA0C;AAC3E,WAAO,IAAIN,gBACT,KACA,wCAAwCM,MAAMC,SAAQ,CAAA,sCAAwC;EAElG;EAEA,OAAc8B,eAA+B;AAC3C,WAAO,IAAIrC,gBACT,KACA,kEAAA;EAEJ;AACF;;;AC3HO,IAAMsC,WAAN,MAAMA;EAlBb,OAkBaA;;;;;EACX,YACkBC,MACAC,MAChB;SAFgBD,OAAAA;SACAC,OAAAA;EACf;;EAGIC,UAAUC,OAAiC;AAChD,WAAO;MACLC,SAAS;MACTD;IACF;EACF;;EAGOE,YAAYC,SAA2C;AAC5D,WAAO;MACLF,SAAS;MACTE;IACF;EACF;;EAGOC,UAAUC,MAAsC;AACrD,WAAO;MACLJ,SAAS;MACTK,UAAUD;IACZ;EACF;;EAGOE,UAAuBC,OAAwC;AACpE,WAAO;MACLP,SAAS;MACTO;IACF;EACF;EAEOC,WAAmB;AACxB,WAAO,SAAS,KAAKZ,IAAI;EAC3B;AACF;AAcO,IAAMa,YAAN,cAA2Bd,SAAAA;EAzElC,OAyEkCA;;;EAChBe,QAAQ;EAERF,WAAmB;AACjC,WAAO,aAAa,KAAKZ,IAAI;EAC/B;AACF;AAiBO,IAAMe,iBAAN,cAAgChB,SAAAA;EAhGvC,OAgGuCA;;;EACrBe,QAAQ;EAERF,WAAmB;AACjC,WAAO,kBAAkB,KAAKZ,IAAI;EACpC;AACF;AAUO,SAASgB,WACdC,UAAiB;AAEjB,SAAOA,oBAAoBJ,aAAaI,oBAAoBF;AAC9D;AAJgBC;AAmBT,SAASE,aACdC,UACAC,UAAU,OAAK;AAEf,MAAIC,QAA4B;AAChC,MAAIC,aAAgBH,QAAAA,GAAW;AAC7BE,YAAQE,mBAAsBJ,QAAAA;EAChC,WAAWH,WAAcG,QAAAA,EAAWE,SAAQF;AAE5C,MAAI,CAACE,SAAS,CAACL,WAAcK,KAAAA,GAAQ;AACnC,QAAID,QAAS,OAAMI,eAAeC,aAAaN,QAAAA;AAC/C,UAAMK,eAAeE,gBAAgBC,KAAKC,UAAUT,QAAAA,CAAAA;EACtD;AAEA,SAAOE;AACT;AAfgBH;;;AC5HT,IAAMW,mBAAmBC,OAAO,YAAA;AAuBhC,SAASC,iBAAAA;AACd,SAAO,CAACC,SAAAA;AACN,UAAMC,YAAY,IAAIC,UAAa,IAAIF,KAAKG,IAAI,IAAI;MAClDC,SAAS,6BAAM,IAAIJ,KAAAA,GAAV;IACX,CAAA;AAECA,SAAaH,gBAAAA,IAAoBI;AAClC,WAAOD;EACT;AACF;AATgBD;AA+BT,SAASM,eAAkBL,MAAa;AAC7C,QAAMC,YAAY,IAAIC,UAAa,IAAIF,KAAKG,IAAI,IAAI;IAClDC,SAAS,6BAAM,IAAIJ,KAAAA,GAAV;EACX,CAAA;AAECA,OAAaH,gBAAAA,IAAoBI;AAClC,SAAOD;AACT;AAPgBK;AAUT,SAASC,aAAgBN,MAAa;AAG3C,SACE,OAAOA,SAAS,cAChBO,cAAcP,IAAAA,KACdH,oBAAoBG,QACpBA,KAAKH,gBAAAA,aAA6BK;AAEtC;AATgBI;AAYT,SAASE,mBACdR,MAAoD;AAEpD,SAAOA,KAAKH,gBAAAA;AACd;AAJgBW;AAMT,SAASD,cAAcE,IAAW;AACvC,SAAO,OAAOA,OAAO,cAAcA,GAAGC,aAAaD,GAAGC,UAAU,gBAAgBD;AAClF;AAFgBF;;;ACnFT,IAAeI,SAAf,MAAeA,QAAAA;EAHtB,OAGsBA;;;EACpB,OAAwBC,eAAe,CAAA;EACvC,OAAwBC,YAAY,CAAA;;EAGpC,WAAkBC,kBAAkD;AAClE,WAAOH,QAAOE;EAChB;;;;;;;EAQA,OAAcE,kBAAkBC,GAA6B;AAC3DL,YAAOC,aAAaK,KAAKD,CAAAA;EAC3B;;;;;;;EAQA,OAAcE,qBAAqBC,SAAgC;AACjER,YAAOE,UAAUI,KAAKE,OAAAA;EACxB;EAEA,OAAiBC,SAASC,QAAkC;AAC1D,eAAWC,QAAQX,QAAOC,aAAcU,MAAKF,SAASC,MAAAA;EACxD;AACF;;;ACxBO,IAAeE,mBAAf,MAAeA,kBAAAA;EAbtB,OAasBA;;;EACpB,OAAcC,cAAc;EAC5B,OAAuBC,SAAS,oBAAIC,IAAAA;EACpC,OAAcC,WAA8B;EAC5C,OAAwBC,YAAYC,OAAOC;;;;;;;;EAS3C,OAAcC,OAAOC,MAAiC;AACpD,QAAI,CAACT,kBAAiBC,aAAa;AACjC,YAAMS,eAAeC,0BAAyB;IAChD;AAEAX,sBAAiBE,OAAOU,IAAIH,IAAAA;EAC9B;;;;;;;;;;;;;;;EAgBA,OAAcI,KAAKT,UAA6B;AAC9CJ,sBAAiBE,OAAOY,MAAK;AAC7Bd,sBAAiBC,cAAc;AAC/BD,sBAAiBI,WAAWA,YAAY;EAC1C;EAEA,OAAcW,KAAKC,SAAwC;AACzD,QAAI,OAAOA,YAAY,WAAY,QAAO,oBAAIb,IAAAA;AAC9CH,sBAAiBa,KAAI;AAErB,QAAI;AACFG,cAAAA;IACF,QAAQ;IAER;AAEA,UAAMC,WAAWjB,kBAAiBK;AAClC,eAAWa,WAAWD,UAAU;AAS9B,YAAME,UAAUD,QAAQH,KAAKC,OAAAA;AAC7B,iBAAWP,QAAQU,QAASnB,mBAAiBE,OAAOU,IAAIH,IAAAA;IAC1D;AAEA,UAAMW,aAAapB,kBAAiBqB,eAAc;AAClD,WAAOD;EACT;EAEA,OAAcE,YAAeN,SAAkBZ,UAAyB;AAOtEJ,sBAAiBa,KAAKT,QAAAA;AACtB,QAAI;AACF,aAAOY,QAAAA;IACT,UAAA;AACEhB,wBAAiBqB,eAAc;IACjC;EACF;EAEA,OAAcA,iBAA2C;AACvD,UAAME,QAAQ,IAAIpB,IAAIH,kBAAiBE,MAAM;AAE7CF,sBAAiBC,cAAc;AAC/BD,sBAAiBE,OAAOY,MAAK;AAC7Bd,sBAAiBI,WAAW;AAE5B,WAAOmB;EACT;AACF;;;AC9CO,SAASC,WAOdC,UAAaC,SAA8B;AAC3C,MAAIC,QAAaF;AACjB,MAAIG,aAAaH,QAAAA,EAAWE,SAAQE,mBAAmBJ,QAAAA;AAEvD,MAAI,CAACK,iBAAiBC,aAAa;AACjC,UAAMC,eAAeC,eAAeN,KAAAA;EACtC;AAEA,MAAI,CAACO,WAAWP,KAAAA,EAAQ,OAAMK,eAAeG,gBAAgBC,OAAOT,KAAAA,CAAAA;AAEpE,QAAMU,YAAY;IAAEV;IAAOW,UAAUZ,SAASY,YAAY;EAAM;AAChER,mBAAiBS,OAAOF,SAAAA;AAExB,MAAIP,iBAAiBU,UAAU;AAC7B,WAAOV,iBAAiBU,SAASb,OAAOD,SAASY,QAAAA;EACnD;AAEA,SAAOD;AACT;AAzBgBb;;;AC3DT,IAAMiB,6BAAN,MAAMA;EAAb,OAAaA;;;EACJC,SAASC,QAAkC;AAChDC,YAAQC,IAAI,iCAAA;AACZD,YAAQC,IAAI,YAAYF,OAAOG,UAAU,UAAU;AACnDF,YAAQC,IAAI,KAAKF,OAAOI,YAAYC,MAAM,iCAAiC;AAC3E,eAAWC,QAAQN,OAAOI,YAAaH,SAAQC,IAAI,SAASI,KAAKC,SAAQ,CAAA,EAAI;EAC/E;AACF;;;ACJO,SAASC,gBAAmBC,UAA0B;AAC3D,MAAI,WAAWA,SAAU,QAAO,MAAMA,SAASC;AAC/C,MAAI,aAAaD,SAAU,QAAOA,SAASE;AAC3C,MAAI,cAAcF,SAAU,QAAO,MAAM,IAAIA,SAASG,SAAQ;AAC9D,MAAI,WAAWH,SAAU,QAAOI,aAAaJ,SAASK,OAAO,IAAA;AAE7D,QAAMC,eAAeC,gBAAgBC,KAAKC,UAAUT,QAAAA,CAAAA;AACtD;AAPgBD;;;ACCT,IAAMW,kBAAN,MAAMA;EALb,OAKaA;;;;EAEKC;EACAC;;EAGTC,UAA4B;EAEnC,YAAYF,OAAqBE,SAAmB;AAClD,SAAKF,QAAQA;AACb,SAAKE,UAAUA,WAAW;AAC1B,SAAKD,aAAaC,UAAUC,iBAAiBC,KAAKF,OAAAA,IAAW,oBAAIG,IAAAA;EACnE;EAEOC,aAAsB;AAC3B,WAAO,OAAO,KAAKJ,YAAY;EACjC;EAEOK,WAAWL,SAAwB;AACxC,QAAI,KAAKA,QAAS,OAAMM,eAAeC,iBAAiB,KAAKT,KAAK;AAClE,SAAKE,UAAUA;AAEf,UAAMQ,UAAUP,iBAAiBC,KAAKF,OAAAA;AACtC,eAAWS,aAAaD,SAAS;AAC/B,WAAKT,WAAWW,IAAID,SAAAA;IACtB;EACF;EAEOE,WAAmB;AACxB,WAAO,mBAAmB,KAAKb,MAAMa,SAAQ,CAAA;EAC/C;AACF;AAEO,IAAMC,uBAAN,MAAMA;EAtCb,OAsCaA;;;;EACKZ;EACAD;EAEhB,YACkBc,QAChBb,SACA;SAFgBa,SAAAA;AAGhB,SAAKb,UAAUA;AACf,SAAKD,aAAaE,iBAAiBC,KAAKF,OAAAA;EAC1C;EAEOW,WAAmB;AACxB,WAAO,wBAAwB,KAAKX,QAAQc,QAAQ,WAAA;EACtD;AACF;AAEO,IAAMC,iBAAN,MAAMA;EAvDb,OAuDaA;;;EACKjB;EACAkB,cAAc,oBAAIb,IAAAA;EAClBc,aAAa,oBAAId,IAAAA;EACjBe,mBAAmB,oBAAIf,IAAAA;EAEvC,YAAYL,OAA0B;AACpC,SAAKA,QAAQA;EACf;EAEOqB,YAAYC,WAA0C;AAC3D,QAAIA,qBAAqBC,WAAW;AAClC,WAAKL,YAAYN,IAAIU,SAAAA;IACvB,WAAWA,qBAAqBE,gBAAgB;AAC9C,WAAKL,WAAWP,IAAIU,SAAAA;IACtB,WAAW,OAAOA,cAAc,YAAY;AAC1C,YAAMG,mBAAmB,IAAIX,qBAAwB,MAAMQ,SAAAA;AAC3D,WAAKF,iBAAiBR,IAAIa,gBAAAA;IAC5B;EACF;EAEOZ,WAAmB;AACxB,WAAO,kBAAkB,KAAKb,MAAMa,SAAQ,CAAA;EAC9C;AACF;AAOO,SAASa,sBACdC,OAAgB;AAEhB,SAAO,EAAEA,iBAAiBb;AAC5B;AAJgBY;;;AChFhB,SAASE,iBACPC,MACAC,MACAC,iBAAyC;AAEzC,SAAO,CAACC,OAAoBC,aAAAA;AAC1B,UAAMC,UAAUJ,KAAKK,IAAIH,KAAAA;AACzB,QAAI,CAACE,WAAW,CAACD,UAAU;AACzB,YAAMG,cAAcC,MAAMC,KAAKP,eAAAA,EAAiBQ,KAC9C,CAACC,MAAM,WAAWA,KAAKA,EAAEC,MAAMC,OAAOV,UAAUA,KAAAA;AAElD,UAAII,YAAa,QAAOA,YAAYO;AACpC,YAAMC,eAAeC,UAAUb,OAAOH,IAAAA;IACxC;AAEA,WAAOK,SAASS,YAAY;EAC9B;AACF;AAjBSf;AAoBF,IAAMkB,eAAN,MAAMA;EA1Bb,OA0BaA;;;EACMC,QAA4B,oBAAIC,IAAAA;EAChCC,YAA4B,oBAAIC,IAAAA;EAEjD,IAAWC,eAAmC;AAC5C,WAAO,KAAKJ;EACd;EAEOK,cAAcvB,MAA2B;AAC9C,SAAKkB,MAAMM,IAAIxB,IAAAA;EACjB;EAEOyB,cAAoB;AACzB,eAAWC,OAAO,KAAKR,OAAO;AAC5BQ,UAAID,YAAY,KAAKL,SAAS;AAC9B,UAAI,WAAWM,IAAId,MAAO,MAAKQ,UAAUO,IAAID,IAAId,MAAMT,OAAOuB,GAAAA;IAChE;EACF;EAEOhB,KAAQP,OAAwC;AACrD,UAAMH,OAAO,KAAKoB,UAAUd,IAAIH,KAAAA;AAChC,QAAI,CAACH,KAAM,QAAO;AAClB,WAAOA;EACT;EAEO4B,WAAmB;AACxB,WAAO;EACT;AACF;AAEO,IAAMC,iBAAN,MAAMA;EAxDb,OAwDaA;;;;EACMC,eAAyC,oBAAIX,IAAAA;EAC7CD,QAAwB,oBAAIG,IAAAA;EACrCU,YAAsB;EACtBC,YAAY;EACbC,cAAc;EAErB,IAAWnB,WAAc;AACvB,QAAI,CAAC,KAAKkB,WAAW;AACnB,YAAMjB,eAAemB,qBAAqB,KAAKtB,MAAMT,KAAK;IAC5D;AAEA,WAAO,KAAK4B;EACd;EAEA,YAA4BnB,OAA2B;SAA3BA,QAAAA;EAA4B;EAEjDW,cAAcvB,MAA2B;AAC9C,QAAIA,gBAAgBmC,oBAAqB,MAAKL,aAAaN,IAAIxB,IAAAA;QAC1D,MAAKkB,MAAMS,IAAI3B,KAAKY,MAAMT,OAAOH,IAAAA;AACtCA,SAAKiC;EACP;EAEOR,YAAYW,MAA6B;AAC9C,QAAI,KAAKJ,UAAW;AAEpB,eAAWhC,QAAQ,KAAKkB,MAAMmB,OAAM,EAAIrC,MAAKyB,YAAYW,IAAAA;AACzD,eAAWV,OAAO,KAAKI,aAAcJ,KAAID,YAAYW,IAAAA;AAErD,UAAME,YAAYvC,iBAAiB,KAAKa,MAAMT,OAAO,KAAKe,OAAO,KAAKY,YAAY;AAClF,UAAMS,UAAU,KAAK3B,MAAM2B,WAAW,KAAK3B,MAAMT,MAAMqC,MAAMD;AAC7D,QAAI,CAACA,QAAS,OAAMxB,eAAe0B,SAAS,KAAK7B,MAAMT,KAAK;AAC5D,SAAK4B,YAAYW,iBAAiBjB,YAAYc,SAASD,SAAAA;AAEvD,SAAKN,YAAY;AACjB,QAAII,KAAMA,MAAKT,IAAI,KAAKf,MAAMT,OAAO,IAAI;EAC3C;EAEOyB,WAAmB;AACxB,WAAO,kBAAkB,KAAKhB,MAAMT,MAAMyB,SAAQ,CAAA;EACpD;AACF;AAEO,IAAMO,sBAAN,MAAMA,qBAAAA;EAnGb,OAmGaA;;;;EACML,eAAe,oBAAIX,IAAAA;EACnBD,QAAwB,oBAAIG,IAAAA;EACrCU,YAAsB;EACtBC,YAAY;EACbC,cAAc;EAErB,IAAWnB,WAAc;AACvB,QAAI,CAAC,KAAKkB,UAAW,OAAMjB,eAAe4B,aAAY;AACtD,WAAO,KAAKZ;EACd;EAEA,YAA4BnB,OAAgC;SAAhCA,QAAAA;EAAiC;EAEtDW,cAAcvB,MAA2B;AAC9C,QAAIA,gBAAgBmC,qBAAqB,MAAKL,aAAaN,IAAIxB,IAAAA;QAC1D,MAAKkB,MAAMS,IAAI3B,KAAKY,MAAMT,OAAOH,IAAAA;AAEtCA,SAAKiC;EACP;EAEOR,YAAYW,MAA6B;AAC9C,QAAI,KAAKJ,UAAW;AAEpB,eAAWN,OAAO,KAAKI,aAAcJ,KAAID,YAAYW,IAAAA;AACrD,eAAWpC,QAAQ,KAAKkB,MAAMmB,OAAM,EAAIrC,MAAKyB,YAAYW,IAAAA;AAEzD,UAAME,YAAYvC,iBAChB,KAAKa,MAAMC,OAAOV,OAClB,KAAKe,OACL,KAAKY,YAAY;AAGnB,SAAKC,YAAYW,iBAAiBjB,YAAY,KAAKb,MAAM2B,SAASD,SAAAA;AAClE,SAAKN,YAAY;EACnB;EAEOJ,WAAmB;AACxB,WAAO,uBAAuB,KAAKhB,MAAMC,OAAOV,MAAMyB,SAAQ,CAAA;EAChE;AACF;AAEO,IAAMgB,gBAAN,MAAMA,eAAAA;EA7Ib,OA6IaA;;;;EACM1B,QAAQ,oBAAIC,IAAAA;EACbL,WAAgB,CAAA;EACxBkB,YAAY;EACbC,cAAc;EAErB,YAA4BrB,OAA0B;SAA1BA,QAAAA;EAA2B;EAEhDa,YAAYW,MAA6B;AAC9C,QAAI,KAAKJ,UAAW;AAEpB,eAAWN,OAAO,KAAKR,OAAO;AAC5BQ,UAAID,YAAYW,IAAAA;AAEhB,UAAIV,eAAeG,gBAAgB;AACjC,aAAKf,SAAS+B,KAAKnB,IAAIZ,QAAQ;MACjC,WAAWY,eAAekB,gBAAe;AACvC,aAAK9B,SAAS+B,KAAI,GAAInB,IAAIZ,QAAQ;MACpC,WAAWY,eAAeS,qBAAqB;AAC7C,aAAKrB,SAAS+B,KAAKnB,IAAIZ,QAAQ;MACjC;IACF;AAEA,SAAKkB,YAAY;AACjB,QAAII,KAAMA,MAAKT,IAAI,KAAKf,MAAMT,OAAO,IAAI;EAC3C;EAEOoB,iBAAiBuB,OAAyB;AAC/C,eAAW9C,QAAQ8C,OAAO;AACxB,WAAK5B,MAAMM,IAAIxB,IAAAA;AACfA,WAAKiC;IACP;EACF;EAEOL,WAAmB;AACxB,WAAO,iBAAiB,KAAKhB,MAAMT,MAAMyB,SAAQ,CAAA;EACnD;AACF;;;AC9JA,SAASmB,eAAeC,GAAY;AAClC,MAAIA,aAAaC,gBAAiB,QAAO,IAAIC,eAAeF,CAAAA;AAC5D,MAAIA,aAAaG,eAAgB,QAAO,IAAIC,cAAcJ,CAAAA;AAC1D,MAAIA,aAAaK,qBAAsB,QAAO,IAAIC,oBAAoBN,CAAAA;AACtE,QAAM,IAAIO,MAAM,wBAAA;AAClB;AALSR;AAOF,SAASS,gBACdC,WACAC,OACAC,aACAC,YACAC,gBAA+B;AAE/B,QAAMC,UAAUJ,MAAMK,IAAIN,SAAAA;AAC1B,MAAIK,QAAS,QAAOA;AAEpB,QAAME,WAAWjB,eAAeU,SAAAA;AAEhC,QAAMQ,QAAsB;IAAC;MAAEC,OAAOT;MAAWU,MAAMH;MAAUI,WAAW;IAAM;;AAClF,QAAMC,WAAW,oBAAIC,IAAAA;AAErB,SAAOL,MAAMM,SAAS,GAAG;AAwBvB,QAASC,iBAAT,SAAuBC,OAAmBC,WAAW,OAAK;AACxD,UAAID,iBAAiBE,WAAW;AAC9B,cAAM3B,IAAIW,YAAYI,IAAIU,KAAAA;AAC1B,YAAIzB,GAAG;AACL4B,eAAKC,KAAK7B,CAAAA;AACV;QACF;MACF,WAAWyB,iBAAiBK,gBAAgB;AAC1C,cAAM9B,IAAIY,WAAWG,IAAIU,KAAAA;AACzB,YAAIzB,GAAG;AACL4B,eAAKC,KAAK7B,CAAAA;AACV;QACF;MACF;AAEA,YAAM+B,WAAWlB,iBAAiBY,KAAAA;AAClC,UAAIM,UAAU;AACZH,aAAKC,KAAKE,QAAAA;AACV;MACF;AAEA,UAAI,CAACL,UAAU;AACb,YAAIM,aAAaP,KAAAA,GAAQ;AACvB,gBAAMQ,YAAYC,mBAAmBT,KAAAA;AACrC,gBAAMU,eAAeC,SAASH,SAAAA;QAChC;AAEA,cAAME,eAAeC,SAASX,KAAAA;MAChC;IACF;AA7BSD,wBAAAA;AAAAA,WAAAA,gBAAAA;AAvBT,UAAMa,QAAQpB,MAAMA,MAAMM,SAAS,CAAA;AACnC,UAAM,EAAEL,OAAOC,KAAI,IAAKkB;AAExB,QAAIA,MAAMjB,WAAW;AACnBH,YAAMqB,IAAG;AACTjB,eAASkB,OAAOrB,KAAAA;AAChBR,YAAM8B,IAAItB,OAAOC,IAAAA;AACjB;IACF;AAEA,QAAIE,SAASoB,IAAIvB,KAAAA,KAAUwB,sBAAsBxB,KAAAA,GAAQ;AACvD,YAAMyB,OAAO1B,MAAM2B,IAAI,CAACC,MAAMA,EAAE3B,KAAK,EAAE4B,OAAO,CAAC9C,MAAM0C,sBAAsB1C,CAAAA,CAAAA;AAC3E,YAAM+C,QAAQJ,KAAKK,QAAQ9B,KAAAA;AAC3B,YAAM+B,QAAQN,KAAKO,MAAMH,KAAAA;AACzB,YAAMI,cAAcF,MAAML,IAAI,CAAC5C,MAAMA,EAAEyB,KAAK;AAC5C,YAAMU,eAAeiB,mBAAmBlC,MAAMO,OAAO0B,WAAAA;IACvD;AAEA9B,aAASgC,IAAInC,KAAAA;AACbmB,UAAMjB,YAAY;AAElB,UAAMQ,OAAiC,CAAA;AAiCvC,QAAIV,iBAAiBjB,mBAAmBiB,iBAAiBb,sBAAsB;AAC7E,iBAAWiD,aAAapC,MAAMqC,YAAY;AACxC/B,QAAAA,eAAc8B,UAAU7B,OAAO6B,UAAU5B,QAAQ;MACnD;IACF;AAEA,QAAIR,iBAAiBf,gBAAgB;AACnC,YAAMqD,cAAc3C,iBAAiBK,MAAMO,KAAK;AAChD,UAAI+B,uBAAuBpD,eAAe;AACxCe,aAAKK,cAAcgC,WAAAA;MACrB;AAEA,iBAAWC,UAAUvC,MAAMP,aAAa;AACtC,YAAIX,IAAIW,YAAYI,IAAI0C,MAAAA;AACxB,YAAI,CAACzD,GAAG;AACNA,cAAI,IAAIC,gBAAgBwD,MAAAA;AACxB9C,sBAAY6B,IAAIiB,QAAQzD,CAAAA;QAC1B;AAEA4B,aAAKC,KAAK7B,CAAAA;MACZ;AAEA,iBAAW0D,SAASxC,MAAMN,YAAY;AACpC,YAAIZ,IAAIY,WAAWG,IAAI2C,KAAAA;AACvB,YAAI,CAAC1D,GAAG;AACNA,cAAI,IAAIG,eAAeuD,KAAAA;AACvB9C,qBAAW4B,IAAIkB,OAAO1D,CAAAA;QACxB;AACA4B,aAAKC,KAAK7B,CAAAA;MACZ;AAEA,iBAAW2D,eAAezC,MAAM0C,kBAAkB;AAChDhC,aAAKC,KAAK8B,WAAAA;MACZ;IACF;AAEA,eAAWE,OAAOjC,MAAM;AACtB,UACEiC,eAAe3D,kBACf2D,eAAezD,iBACfyD,eAAevD,qBACf;AACAa,aAAKK,cAAcqC,GAAAA;AACnB;MACF;AAEA,YAAMC,WAAWD;AAEjB,YAAME,SAASrD,MAAMK,IAAI+C,QAAAA;AACzB,UAAIC,QAAQ;AACV5C,aAAKK,cAAcuC,MAAAA;AACnB;MACF;AAEA,UAAI1C,SAASoB,IAAIqB,QAAAA,KAAapB,sBAAsBoB,QAAAA,GAAW;AAC7D,cAAMnB,OAAO1B,MAAM2B,IAAI,CAACC,MAAMA,EAAE3B,KAAK,EAAE4B,OAAO,CAAC9C,MAAM0C,sBAAsB1C,CAAAA,CAAAA;AAC3E,cAAM+C,QAAQJ,KAAKK,QAAQc,QAAAA;AAC3B,cAAMb,QAAQ;aAAIN,KAAKO,MAAMH,KAAAA;UAAQe;;AACrC,cAAMX,cAAcF,MAAML,IAAI,CAAC5C,MAAMA,EAAEyB,KAAK;AAE5C,cAAMU,eAAeiB,mBAAmBU,SAASrC,OAAO0B,WAAAA;MAC1D;AAEA,YAAMa,YAAYjE,eAAe+D,QAAAA;AACjC3C,WAAKK,cAAcwC,SAAAA;AACnB/C,YAAMY,KAAK;QAAEX,OAAO4C;QAAU3C,MAAM6C;QAAW5C,WAAW;MAAM,CAAA;IAClE;EACF;AAEA,SAAOJ;AACT;AA5IgBR;;;ACOT,IAAMyD,eAAN,MAAMA;EAlCb,OAkCaA;;;;EACX,YAA4BC,WAAyB;SAAzBA,YAAAA;EAA0B;EAK/CC,IAAOC,OAA0B;AACtC,WAAO,KAAKF,UAAUC,IAAOC,KAAAA;EAC/B;EAEOC,QAAWC,IAA4B;AAC5C,WAAO,KAAKJ,UAAUG,QAAWC,EAAAA;EACnC;AACF;AAkBO,IAAMC,WAAW,IAAIC,UAAqB,UAAA;;;AChC1C,SAASC,iBACdC,IACAC,MAAwB;AAExB,QAAM,EAAEC,WAAWC,OAAM,IAAKC,WAAWC,QAAAA;AACzC,QAAMC,UAAU,mCAAA;AACd,UAAMC,YAAY,MAAMP,GAAAA;AAExB,UAAMQ,eAAe,IAAIC,cAAc;MAAEN;IAAO,CAAA;AAEhD,QAAIF,MAAMS,UAAWF,cAAaG,QAAQV,KAAKS,SAAS;AACxDF,iBAAaG,QAAQJ,SAAAA;AACrBC,iBAAaI,UAAS;AAEtB,WAAOJ,aAAaK,IAAIR,QAAAA;EAC1B,GAVgB;AAYhB,QAAMS,YAAYb,MAAMa,aAAa;AACrC,MAAI,CAACA,UAAW,QAAOR;AAEvB,MAAIS,QAAmC;AACvC,SAAO,MAAA;AACLA,cAAUT,QAAAA;AACV,WAAOS;EACT;AACF;AAzBgBhB;AAmDT,SAASiB,YACdhB,IACAC,MAAwB;AAExB,QAAM,EAAEC,WAAWC,OAAM,IAAKC,WAAWC,QAAAA;AACzC,QAAMC,UAAW,mCAAA;AACf,UAAMW,QAAQ,MAAMjB,GAAAA;AACpB,UAAMkB,gBAAgB,IAAIT,cAAc;MAAEN;IAAO,CAAA;AAEjD,QAAIF,MAAMS,UAAWQ,eAAcP,QAAQV,KAAKS,SAAS;AACzDQ,kBAAcP,QAAQM,KAAAA;AACtBC,kBAAcN,UAAS;AAEvB,WAAOM,cAAcL,IAAIM,aAAaF,KAAAA,CAAAA;EACxC,GATiB;AAWjB,QAAMH,YAAYb,MAAMa,aAAa;AACrC,MAAI,CAACA,UAAW,QAAOR;AAEvB,MAAIS,QAAiC;AACrC,SAAO,MAAA;AACLA,cAAUT,QAAAA;AACV,WAAOS;EACT;AACF;AAxBgBC;AAuDT,SAASI,iBACdpB,IACAC,MAAwB;AAExB,QAAM,EAAEC,WAAWC,OAAM,IAAKC,WAAWC,QAAAA;AACzC,QAAMC,UAAW,mCAAA;AACf,UAAM,EAAEe,YAAYd,UAAS,IAAK,MAAMP,GAAAA;AAExC,UAAMQ,eAAe,IAAIC,cAAc;MAAEN;IAAO,CAAA;AAEhD,QAAIF,MAAMS,UAAWF,cAAaG,QAAQV,KAAKS,SAAS;AACxDF,iBAAaG,QAAQJ,SAAAA;AACrBC,iBAAaI,UAAS;AAEtB,WAAOJ,aAAaK,IAAIM,aAAaE,UAAAA,CAAAA;EACvC,GAViB;AAYjB,QAAMP,YAAYb,MAAMa,aAAa;AACrC,MAAI,CAACA,UAAW,QAAOR;AAEvB,MAAIS,QAAiC;AACrC,SAAO,MAAA;AACLA,cAAUT,QAAAA;AACV,WAAOS;EACT;AACF;AAzBgBK;;;ACpGT,IAAME,gBAAN,cAA4BC,OAAAA;EAvCnC,OAuCmCA;;;;EACzBC,gBAAgB;EAChBC;EAESC;EACAC,cAAc,oBAAIC,IAAAA;EAClBC,mBAAmB,oBAAID,IAAAA;EAExC,YAA6BE,OAA2B;AACtD,UAAK,GAAA,KADsBA,QAAAA;AAG3B,SAAKJ,UAAUI,OAAOC;AACtB,QAAID,OAAOE,aAAa;AACtBT,aAAOU,kBAAkB,IAAIC,2BAAAA,CAAAA;IAC/B;EACF;;;;;;;;;;;;;;;;;;;;;;;;EAyBOC,QAAWC,UAA6B;AAC7C,QAAI,KAAKZ,eAAe;AACtB,YAAMa,eAAeC,aAAY;IACnC;AAEA,QAAIC,MAAMC,QAAQJ,QAAAA,GAAW;AAC3B,iBAAWK,QAAQL,SAAU,MAAKD,QAAQM,IAAAA;AAC1C;IACF;AAGA,QAAIL,oBAAoBM,gBAAgB;AACtC,UAAI,KAAKb,iBAAiBc,IAAIP,QAAAA,GAAW;AACvC,cAAMC,eAAeO,UAAUR,QAAAA;MACjC;AAEA,YAAMS,WAAW,IAAIC,eAAkBV,QAAAA;AACvC,WAAKP,iBAAiBkB,IAAIX,UAAUS,QAAAA;AACpC;IACF;AAGA,QAAIT,oBAAoBY,WAAW;AACjC,UAAI,KAAKrB,YAAYgB,IAAIP,QAAAA,GAAW;AAClC,cAAMC,eAAeO,UAAUR,QAAAA;MACjC;AAEA,YAAMa,QAAQ,IAAIC,gBAAmBd,QAAAA;AACrC,WAAKT,YAAYoB,IAAIX,UAAUa,KAAAA;AAC/B;IACF;AAGA,QAAI,OAAOb,aAAa,YAAY;AAClC,UAAI,CAACe,aAAgBf,QAAAA,EAAW,OAAMC,eAAee,YAAYhB,QAAAA;AAEjE,YAAMiB,SAAQC,mBAAsBlB,QAAAA;AACpC,UAAI,EAAEiB,kBAAiBL,WAAY,OAAMX,eAAee,YAAYhB,QAAAA;AAEpE,YAAMmB,WAAW,KAAK5B,YAAY6B,IAAIH,MAAAA;AACtC,UAAIE,UAAUE,WAAAA,EAAc,OAAMpB,eAAeO,UAAUS,MAAAA;AAE3D,YAAMK,UAAUL,OAAMM,MAAMD,YAAY,MAAM,IAAItB,SAAAA;AAClD,UAAImB,UAAU;AACZA,iBAASK,WAAWF,OAAAA;AACpB;MACF;AAEA,YAAMT,QAAQ,IAAIC,gBAAmBG,QAAOK,OAAAA;AAC5C,WAAK/B,YAAYoB,IAAIM,QAAOJ,KAAAA;AAC5B;IACF;AAGA,UAAMY,MAAMzB;AACZ,UAAMiB,QAAQS,aAAaD,IAAI1B,OAAO;AACtC,UAAM4B,YAAYC,gBAAmBH,GAAAA;AAErC,QAAIR,iBAAiBX,gBAAgB;AACnC,YAAMuB,aAAa,KAAKpC,iBAAiB2B,IAAIH,KAAAA;AAC7C,UAAIY,YAAY;AACdA,mBAAWC,YAAYH,SAAAA;AACvB;MACF;AAEA,YAAMlB,WAAW,IAAIC,eAAkBO,KAAAA;AACvC,WAAKxB,iBAAiBkB,IAAIM,OAAOR,QAAAA;AACjCA,eAASqB,YAAYH,SAAAA;AACrB;IACF;AAEA,QAAIV,iBAAiBL,WAAW;AAC9B,YAAMO,WAAW,KAAK5B,YAAY6B,IAAIH,KAAAA;AACtC,UAAIE,UAAUE,WAAAA,EAAc,OAAMpB,eAAeO,UAAUS,KAAAA;AAE3D,UAAIK;AACJ,UAAI,OAAOK,cAAc,WAAYL,WAAUK;AAC/C,UAAII,WAAcJ,SAAAA,GAAY;AAC5B,YAAIA,cAAcV,MAAO,OAAMhB,eAAe+B,UAAUf,KAAAA;AACxDK,kBAAU,6BAAMW,WAAwBN,SAAAA,GAA9B;MACZ;AAEA,UAAIR,YAAYG,SAAS;AACvBH,iBAASK,WAAWF,OAAAA;AACpB;MACF;AAEA,YAAMT,QAAQ,IAAIC,gBAAmBG,OAAOK,OAAAA;AAC5C,WAAK/B,YAAYoB,IAAIM,OAAOJ,KAAAA;AAC5B;IACF;AAEA,UAAMZ,eAAeiC,gBAAgBC,KAAKC,UAAUpC,QAAAA,CAAAA;EACtD;EAEOqC,SAAYpB,OAAqC;AACtD,QAAI,CAAC,KAAK5B,UAAW,QAAO;AAC5B,QAAI,CAAC,KAAKD,cAAe,QAAO;AAEhC,QAAI2B,aAAgBE,KAAAA,GAAQ;AAC1B,YAAMqB,OAAOpB,mBAAsBD,KAAAA;AACnC,aAAO,KAAK5B,UAAUkD,KAAKD,IAAAA;IAC7B;AAEA,UAAME,WAAW,KAAKnD,UAAUkD,KAAKtB,KAAAA;AACrC,WAAOuB;EACT;EAEQC,eAAkBxB,OAAqC;AAC7D,QAAI,CAAC,KAAK3B,QAAS,QAAO;AAC1B,UAAMoD,aAAa,KAAKpD;AACxB,WAAOoD,WAAWL,SAASpB,KAAAA;EAC7B;EAEQ0B,sBAAoC;AAC1C,UAAMC,OAAO,IAAIC,aAAAA;AACjB,UAAMC,QAAQ,oBAAItD,IAAAA;AAElB,UAAMuD,QAAqB;SACtB,KAAKxD,YAAYyD,OAAM;SACvB,KAAKvD,iBAAiBuD,OAAM;;AAGjC,UAAMC,iBAAiC,KAAKR,eAAeS,KAAK,IAAI;AAEpE,eAAWZ,QAAQS,OAAO;AACxB,UAAID,MAAMvC,IAAI+B,IAAAA,EAAO;AAErB,YAAME,WAAWW,gBACfb,MACAQ,OACA,KAAKvD,aACL,KAAKE,kBACLwD,cAAAA;AAGFL,WAAKQ,cAAcZ,QAAAA;IACrB;AAEAM,UAAMO,MAAK;AACX,SAAK9D,YAAY8D,MAAK;AACtB,SAAK5D,iBAAiB4D,MAAK;AAE3B,WAAOT;EACT;;;;;;;;;;;;;;;;;;;;;EAsBOU,YAAkB;AACvB,QAAI,KAAKlE,cAAe,OAAMa,eAAesD,gBAAe;AAE5D,UAAMC,QAAQC,YAAYC,IAAG;AAE7B,SAAK3D,QAAQ;MACXA,SAAS4D;MACTC,OAAO,IAAIC,aAAa,IAAI;IAC9B,CAAA;AAEA,SAAKxE,YAAY,KAAKsD,oBAAmB;AACzC,SAAKtD,UAAUyE,YAAW;AAC1B,SAAK1E,gBAAgB;AAErB,UAAM2E,MAAMN,YAAYC,IAAG;AAC3B,UAAMM,WAAWD,MAAMP;AACvB,QAAI,KAAK9D,OAAOuE,oBAAoB;AAClCC,cAAQC,IAAI,sCAA+BH,SAASI,QAAQ,CAAA,CAAA,KAAO;IACrE;AAEA,QAAI,KAAK1E,OAAOE,aAAa;AAC3B,YAAMyE,WAAW,KAAKhF,UAAUiF,aAAaC;AAC7C,YAAMC,cAAcrE,MAAMsE,KAAK,KAAKpF,UAAUiF,YAAY,EACvDI,OAAO,CAACpC,SAASA,KAAKqC,gBAAgB,CAAA,EACtCD,OAAO,CAACpC,SAAAA;AACP,YAAI,EAAEA,KAAKzB,iBAAiBC,iBAAkB,QAAO;AACrD,eAAOwB,KAAKzB,MAAMI,UAAU0C;MAC9B,CAAA;AAEFxE,aAAOyF,SAAS;QACdC,YAAYR;QACZG;QACAM,mBAAmBd;MACrB,CAAA;IACF;EACF;EA0BO5C,IAAOpB,UAA6B;AACzC,QAAI,CAAC,KAAKZ,iBAAiB,CAAC,KAAKC,WAAW;AAC1C,YAAMY,eAAe8E,gBAAe;IACtC;AAEA,QAAI9D,QAA4B;AAChC,QAAI,OAAOjB,aAAa,YAAY;AAClC,UAAI,CAACe,aAAgBf,QAAAA,EAAW,OAAMC,eAAee,YAAYhB,QAAAA;AACjEiB,cAAQC,mBAAsBlB,QAAAA;IAChC;AAEA,QAAI+B,WAAc/B,QAAAA,EAAWiB,SAAQjB;AAErC,QAAI,CAACiB,OAAO;AACV,YAAMhB,eAAeiC,gBAAgBC,KAAKC,UAAUpC,QAAAA,CAAAA;IACtD;AAEA,UAAMwC,WAAW,KAAKnD,UAAUkD,KAAKtB,KAAAA;AACrC,QAAI,CAACuB,UAAU;AACb,YAAMwC,WAAW,KAAKvC,eAAexB,KAAAA;AACrC,UAAI+D,SAAU,QAAOA,SAASC;AAE9B,UAAIhE,iBAAiBX,eAAgB,QAAO,CAAA;AAC5C,YAAML,eAAeiF,SAASjE,KAAAA;IAChC;AAEA,WAAOuB,SAASyC;EAClB;;;;;;;;;;;EAYOE,QAAWC,IAA4B;AAC5C,QAAI,CAAC,KAAKhG,iBAAiB,CAAC,KAAKC,WAAW;AAC1C,YAAMY,eAAe8E,gBAAe;IACtC;AAEA,QAAI,OAAOK,OAAO,WAAY,OAAMnF,eAAee,YAAYoE,EAAAA;AAC/D,QAAIC,cAAcD,EAAAA,KAAO,CAACrE,aAAgBqE,EAAAA,GAAK;AAC7C,YAAMnF,eAAee,YAAYoE,EAAAA;IACnC;AAEA,UAAM9D,UAAUP,aAAgBqE,EAAAA,IAAM,MAAM,IAAIA,GAAAA,IAAQA;AAExD,WAAOE,iBAAiBxB,YAAYxC,SAAS,CAACiE,GAAGC,aAAAA;AAC/C,UAAI,CAAC,KAAKnG,UAAW,OAAMY,eAAe8E,gBAAe;AACzD,YAAMzC,OAAO,KAAKjD,UAAUkD,KAAQgD,CAAAA;AACpC,UAAI,CAACjD,QAAQ,CAACkD,SAAU,OAAMvF,eAAeiF,SAASK,CAAAA;AAEtD,aAAOjD,OAAOA,KAAK2C,WAAW;IAChC,CAAA;EACF;AACF;","names":["InjectionError","Error","code","message","name","duplicate","token","toString","duplicateFactory","invalidCtor","ctor","invalidProvider","provider","invalidAlias","alias","aliasStr","String","loopAlias","notBootstrapped","bootstrapped","doubleBootstrap","notFound","circularDependency","path","providerStr","NodeBase","pathStr","map","p","join","untracked","parent","tokenStr","parentStr","outsideContext","calledUtilsOutsideContext","instanceAccessFailed","accessFailed","NodeBase","name","opts","withValue","value","provide","withFactory","factory","withClass","ctor","useClass","withAlias","alias","toString","NodeToken","multi","MultiNodeToken","isNodeBase","specimen","extractToken","provider","isAlias","token","isInjectable","getInjectableToken","InjectionError","invalidAlias","invalidProvider","JSON","stringify","INJECTION_SYMBOL","Symbol","NodeInjectable","ctor","nodeToken","NodeToken","name","factory","makeInjectable","isInjectable","isConstructor","getInjectableToken","fn","prototype","Illuma","_diagnostics","_scanners","contextScanners","extendDiagnostics","m","push","extendContextScanner","scanner","onReport","report","diag","InjectionContext","contextOpen","_calls","Set","injector","_scanners","Illuma","contextScanners","addDep","node","InjectionError","calledUtilsOutsideContext","add","open","clear","scan","factory","scanners","scanner","scanned","injections","closeAndReport","instantiate","calls","nodeInject","provider","options","token","isInjectable","getInjectableToken","InjectionContext","contextOpen","InjectionError","outsideContext","isNodeBase","invalidProvider","String","injection","optional","addDep","injector","DiagnosticsDefaultReporter","onReport","report","console","log","totalNodes","unusedNodes","length","node","toString","extractProvider","provider","value","factory","useClass","extractToken","alias","InjectionError","invalidProvider","JSON","stringify","ProtoNodeSingle","token","injections","factory","InjectionContext","scan","Set","hasFactory","setFactory","InjectionError","duplicateFactory","scanned","injection","add","toString","ProtoNodeTransparent","parent","name","ProtoNodeMulti","singleNodes","multiNodes","transparentNodes","addProvider","retriever","NodeToken","MultiNodeToken","transparentProto","isNotTransparentProto","proto","retrieverFactory","node","deps","transparentDeps","token","optional","depNode","get","transparent","Array","from","find","n","proto","parent","instance","InjectionError","untracked","TreeRootNode","_deps","Set","_treePool","Map","dependencies","addDependency","add","instantiate","dep","set","toString","TreeNodeSingle","_transparent","_instance","_resolved","allocations","instanceAccessFailed","TreeNodeTransparent","pool","values","retriever","factory","opts","notFound","InjectionContext","accessFailed","TreeNodeMulti","push","nodes","createTreeNode","p","ProtoNodeSingle","TreeNodeSingle","ProtoNodeMulti","TreeNodeMulti","ProtoNodeTransparent","TreeNodeTransparent","Error","resolveTreeNode","rootProto","cache","singleNodes","multiNodes","upstreamGetter","inCache","get","rootNode","stack","proto","node","processed","visiting","Set","length","addDependency","token","optional","NodeToken","deps","push","MultiNodeToken","upstream","isInjectable","nodeToken","getInjectableToken","InjectionError","notFound","frame","pop","delete","set","has","isNotTransparentProto","path","map","f","filter","index","indexOf","cycle","slice","cycleTokens","circularDependency","add","injection","injections","parentNodes","single","multi","transparent","transparentNodes","dep","depProto","cached","childNode","InjectorImpl","container","get","token","produce","fn","Injector","NodeToken","injectGroupAsync","fn","opts","container","parent","nodeInject","Injector","factory","providers","subContainer","NodeContainer","overrides","provide","bootstrap","get","withCache","cache","injectAsync","token","tempContainer","extractToken","injectEntryAsync","entrypoint","NodeContainer","Illuma","_bootstrapped","_rootNode","_parent","_protoNodes","Map","_multiProtoNodes","_opts","parent","diagnostics","extendDiagnostics","DiagnosticsDefaultReporter","provide","provider","InjectionError","bootstrapped","Array","isArray","item","MultiNodeToken","has","duplicate","newProto","ProtoNodeMulti","set","NodeToken","proto","ProtoNodeSingle","isInjectable","invalidCtor","token","getInjectableToken","existing","get","hasFactory","factory","opts","setFactory","obj","extractToken","retriever","extractProvider","multiProto","addProvider","isNodeBase","loopAlias","nodeInject","invalidProvider","JSON","stringify","findNode","node","find","treeNode","_getFromParent","parentNode","_buildInjectionTree","root","TreeRootNode","cache","nodes","values","upstreamGetter","bind","resolveTreeNode","addDependency","clear","bootstrap","doubleBootstrap","start","performance","now","Injector","value","InjectorImpl","instantiate","end","duration","measurePerformance","console","log","toFixed","allNodes","dependencies","size","unusedNodes","from","filter","allocations","onReport","totalNodes","bootstrapDuration","notBootstrapped","upstream","instance","notFound","produce","fn","isConstructor","InjectionContext","t","optional"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { N as NodeBase, P as Provider, T as Token, M as MultiNodeToken, a as NodeToken, C as Ctor } from './providers-D9YA8L_g.cjs';
|
|
2
|
+
export { e as extractToken, g as iNodeAliasProvider, f as iNodeClassProvider, d as iNodeFactoryProvider, h as iNodeProvider, b as iNodeTokenBaseOptions, c as iNodeValueProvider, i as isNodeBase } from './providers-D9YA8L_g.cjs';
|
|
3
|
+
export { E as ExtractInjectedType, N as NodeInjectFn, i as iNodeInjectorOptions, n as nodeInject } from './injection-CSxu56ds.cjs';
|
|
4
|
+
import { i as iInjectionNode, T as TreeNode, I as Illuma } from './plugin-container-D8Zwpigq.cjs';
|
|
5
|
+
|
|
6
|
+
/** @internal */
|
|
7
|
+
type InjectorFn = (token: NodeBase<any>, optional?: boolean) => any;
|
|
8
|
+
/**
|
|
9
|
+
* Internal context manager for tracking dependency injections during factory execution.
|
|
10
|
+
* This class manages the injection context lifecycle and tracks all injection calls.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
declare abstract class InjectionContext {
|
|
15
|
+
static contextOpen: boolean;
|
|
16
|
+
static readonly _calls: Set<iInjectionNode<any>>;
|
|
17
|
+
static injector: InjectorFn | null;
|
|
18
|
+
private static readonly _scanners;
|
|
19
|
+
/**
|
|
20
|
+
* Adds a dependency to the current injection context.
|
|
21
|
+
* Called by `nodeInject` when a dependency is requested.
|
|
22
|
+
*
|
|
23
|
+
* @param node - The injection node representing the dependency
|
|
24
|
+
* @throws {InjectionError} If called outside of an active injection context
|
|
25
|
+
*/
|
|
26
|
+
static addDep(node: iInjectionNode<any>): void;
|
|
27
|
+
/**
|
|
28
|
+
* Opens a new injection context.
|
|
29
|
+
* Resets the calls set and sets the injector if provided.
|
|
30
|
+
*
|
|
31
|
+
* @param injector - Optional injector function to use for resolving dependencies
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Scans a factory function for dependencies.
|
|
35
|
+
* Executes the factory in a dry-run mode to capture `nodeInject` calls.
|
|
36
|
+
* Also runs registered context scanners.
|
|
37
|
+
*
|
|
38
|
+
* @param factory - The factory function to scan
|
|
39
|
+
* @returns A set of detected injection nodes
|
|
40
|
+
*/
|
|
41
|
+
static open(injector?: InjectorFn): void;
|
|
42
|
+
static scan(factory: any): Set<iInjectionNode<any>>;
|
|
43
|
+
static instantiate<T>(factory: () => T, injector: InjectorFn): T;
|
|
44
|
+
static closeAndReport(): Set<iInjectionNode<any>>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Interface for dependency injection containers.
|
|
49
|
+
* Defines the core methods that all DI containers must implement.
|
|
50
|
+
*/
|
|
51
|
+
interface iDIContainer {
|
|
52
|
+
/**
|
|
53
|
+
* Registers a provider in the container.
|
|
54
|
+
* @template T - The type of value being provided
|
|
55
|
+
* @param provider - The provider configuration
|
|
56
|
+
*/
|
|
57
|
+
provide<T>(provider: Provider<T>): void;
|
|
58
|
+
/**
|
|
59
|
+
* @internal Finds the tree node associated with the given token.
|
|
60
|
+
* @template T - The type of value being searched
|
|
61
|
+
* @param token - The token or constructor to find
|
|
62
|
+
* @returns The associated tree node, or null if not found
|
|
63
|
+
*/
|
|
64
|
+
findNode<T>(token: Token<T>): TreeNode<T> | null;
|
|
65
|
+
/**
|
|
66
|
+
* Retrieves an instance for the given token.
|
|
67
|
+
* @template T - The type of value being retrieved
|
|
68
|
+
* @param token - The token or constructor to retrieve
|
|
69
|
+
* @returns The resolved instance
|
|
70
|
+
*/
|
|
71
|
+
get<T>(token: MultiNodeToken<T>): T[];
|
|
72
|
+
get<T>(token: NodeToken<T>): T;
|
|
73
|
+
get<T>(token: Ctor<T>): T;
|
|
74
|
+
produce<T>(fn: Ctor<T> | (() => T)): T;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Symbol used to mark classes as injectable and store their associated token.
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
declare const INJECTION_SYMBOL: unique symbol;
|
|
82
|
+
/**
|
|
83
|
+
* Decorator that marks a class as injectable in the dependency injection system.
|
|
84
|
+
* Automatically creates and associates a NodeToken with the class.
|
|
85
|
+
*
|
|
86
|
+
* @template T - The type of the class being decorated
|
|
87
|
+
* @returns A class decorator function
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* @NodeInjectable()
|
|
92
|
+
* class UserService {
|
|
93
|
+
* public getUser() {
|
|
94
|
+
* return { id: 1, name: 'John' };
|
|
95
|
+
* }
|
|
96
|
+
* }
|
|
97
|
+
*
|
|
98
|
+
* container.provide(UserService);
|
|
99
|
+
* container.bootstrap();
|
|
100
|
+
* const service = container.get(UserService);
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
declare function NodeInjectable<T>(): (ctor: Ctor<T>) => Ctor<T>;
|
|
104
|
+
/**
|
|
105
|
+
* Alternative function to mark a class as injectable in the dependency injection system for environments
|
|
106
|
+
* that do not support decorators.
|
|
107
|
+
* @param ctor
|
|
108
|
+
* @returns
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* import { makeInjectable } from '@illuma/core';
|
|
113
|
+
*
|
|
114
|
+
* class _UserService {
|
|
115
|
+
* public getUser() {
|
|
116
|
+
* return { id: 1, name: "John Doe" };
|
|
117
|
+
* }
|
|
118
|
+
* }
|
|
119
|
+
*
|
|
120
|
+
* export type UserService = _UserService;
|
|
121
|
+
* export const UserService = makeInjectable(_UserService);
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
declare function makeInjectable<T>(ctor: Ctor<T>): Ctor<T>;
|
|
125
|
+
/** @internal */
|
|
126
|
+
declare function isInjectable<T>(ctor: unknown): ctor is Ctor<T> & {
|
|
127
|
+
[INJECTION_SYMBOL]: NodeToken<T>;
|
|
128
|
+
};
|
|
129
|
+
/** @internal */
|
|
130
|
+
declare function getInjectableToken<T>(ctor: Ctor<T> & {
|
|
131
|
+
[INJECTION_SYMBOL]: NodeToken<T>;
|
|
132
|
+
}): NodeToken<T>;
|
|
133
|
+
declare function isConstructor(fn: unknown): fn is Ctor<any>;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Configuration options for the NodeContainer.
|
|
137
|
+
*/
|
|
138
|
+
interface iContainerOptions {
|
|
139
|
+
/**
|
|
140
|
+
* When true, logs the bootstrap time to the console based on performance.now()
|
|
141
|
+
* difference before and after bootstrap.
|
|
142
|
+
* @default false
|
|
143
|
+
*/
|
|
144
|
+
measurePerformance?: boolean;
|
|
145
|
+
diagnostics?: boolean;
|
|
146
|
+
parent?: iDIContainer;
|
|
147
|
+
}
|
|
148
|
+
declare class NodeContainer extends Illuma implements iDIContainer {
|
|
149
|
+
private readonly _opts?;
|
|
150
|
+
private _bootstrapped;
|
|
151
|
+
private _rootNode?;
|
|
152
|
+
private readonly _parent?;
|
|
153
|
+
private readonly _protoNodes;
|
|
154
|
+
private readonly _multiProtoNodes;
|
|
155
|
+
constructor(_opts?: iContainerOptions | undefined);
|
|
156
|
+
/**
|
|
157
|
+
* Registers a provider in the container.
|
|
158
|
+
* Must be called before {@link bootstrap}.
|
|
159
|
+
*
|
|
160
|
+
* @template T - The type of value being provided
|
|
161
|
+
* @param provider - The provider configuration (token, class, or provider object)
|
|
162
|
+
* @throws {InjectionError} If called after bootstrap or if a duplicate provider is detected
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```typescript
|
|
166
|
+
* // Provide a value
|
|
167
|
+
* container.provide({ provide: CONFIG_TOKEN, value: { apiKey: '123' } });
|
|
168
|
+
*
|
|
169
|
+
* // Provide a factory
|
|
170
|
+
* container.provide({ provide: LOGGER_TOKEN, factory: () => new ConsoleLogger() });
|
|
171
|
+
*
|
|
172
|
+
* // Provide an injectable class directly
|
|
173
|
+
* container.provide(UserService);
|
|
174
|
+
*
|
|
175
|
+
* // Provide a class override
|
|
176
|
+
* container.provide({ provide: ServiceClass, useClass: ServiceOverride });
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
provide<T>(provider: Provider<T>): void;
|
|
180
|
+
findNode<T>(token: Token<T>): TreeNode<T> | null;
|
|
181
|
+
private _getFromParent;
|
|
182
|
+
private _buildInjectionTree;
|
|
183
|
+
/**
|
|
184
|
+
* Bootstraps the container by resolving the dependency trees and instantiating all providers.
|
|
185
|
+
* This must be called after all providers are registered and before calling {@link get}.
|
|
186
|
+
*
|
|
187
|
+
* The bootstrap process:
|
|
188
|
+
* 1. Validates all provider registrations
|
|
189
|
+
* 2. Builds dependency injection trees
|
|
190
|
+
* 3. Detects circular dependencies in each tree
|
|
191
|
+
* 4. Instantiates all dependencies in the correct order
|
|
192
|
+
*
|
|
193
|
+
* @throws {InjectionError} If the container is already bootstrapped or if circular dependencies are detected
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* const container = new NodeContainer();
|
|
198
|
+
* container.provide(UserService);
|
|
199
|
+
* container.provide(LoggerService);
|
|
200
|
+
* container.bootstrap(); // Resolves and instantiates all dependencies
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
bootstrap(): void;
|
|
204
|
+
/**
|
|
205
|
+
* Retrieves an instance from the container.
|
|
206
|
+
* Must be called after {@link bootstrap}.
|
|
207
|
+
*
|
|
208
|
+
* @template T - The type of value being retrieved (typically inferred)
|
|
209
|
+
* @param token - The token or class to retrieve
|
|
210
|
+
* @returns For NodeToken: a single instance. For MultiNodeToken: an array of instances.
|
|
211
|
+
* @throws {InjectionError} If called before bootstrap or if the token is not found
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* // Get a single provider
|
|
216
|
+
* const logger = container.get(LoggerToken);
|
|
217
|
+
*
|
|
218
|
+
* // Get a decorated class
|
|
219
|
+
* const service = container.get(UserService);
|
|
220
|
+
*
|
|
221
|
+
* // Get multiple providers
|
|
222
|
+
* const plugins = container.get(PluginToken); // Returns array
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
get<T>(token: MultiNodeToken<T>): T[];
|
|
226
|
+
get<T>(token: NodeToken<T>): T;
|
|
227
|
+
get<T>(token: Ctor<T>): T;
|
|
228
|
+
/**
|
|
229
|
+
* Instantiates a class outside injection context. Primarily used to create instances via Injector.
|
|
230
|
+
* Class does not get registered in the container and cannot be retrieved via {@link get} or {@link nodeInject}.
|
|
231
|
+
* Must be called after {@link bootstrap}.
|
|
232
|
+
*
|
|
233
|
+
* @template T - The type of the class being instantiated
|
|
234
|
+
* @param factory - Factory or class constructor to instantiate
|
|
235
|
+
* @returns A new instance of the class with dependencies injected
|
|
236
|
+
* @throws {InjectionError} If called before bootstrap or if the constructor is invalid
|
|
237
|
+
*/
|
|
238
|
+
produce<T>(fn: Ctor<T> | (() => T)): T;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
declare class InjectionError extends Error {
|
|
242
|
+
readonly code: number;
|
|
243
|
+
constructor(code: number, message: string);
|
|
244
|
+
static duplicate(token: NodeBase<unknown>): InjectionError;
|
|
245
|
+
static duplicateFactory(token: NodeBase<unknown>): InjectionError;
|
|
246
|
+
static invalidCtor(ctor: Ctor<unknown>): InjectionError;
|
|
247
|
+
static invalidProvider(provider: string): InjectionError;
|
|
248
|
+
static invalidAlias(alias: unknown): InjectionError;
|
|
249
|
+
static loopAlias(alias: NodeBase<unknown>): InjectionError;
|
|
250
|
+
static notBootstrapped(): InjectionError;
|
|
251
|
+
static bootstrapped(): InjectionError;
|
|
252
|
+
static doubleBootstrap(): InjectionError;
|
|
253
|
+
static notFound(token: NodeBase<unknown>): InjectionError;
|
|
254
|
+
static circularDependency(provider: NodeBase<unknown> | Ctor<unknown>, path: (NodeBase<unknown> | Ctor<unknown>)[]): InjectionError;
|
|
255
|
+
static untracked(token: NodeBase<unknown> | Ctor<unknown>, parent: NodeBase<unknown> | Ctor<unknown>): InjectionError;
|
|
256
|
+
static outsideContext(token: NodeBase<unknown> | Ctor<unknown>): InjectionError;
|
|
257
|
+
static calledUtilsOutsideContext(): InjectionError;
|
|
258
|
+
static instanceAccessFailed(token: NodeBase<unknown>): InjectionError;
|
|
259
|
+
static accessFailed(): InjectionError;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
interface iInjector {
|
|
263
|
+
/** The DI container associated with this injector */
|
|
264
|
+
readonly container: iDIContainer;
|
|
265
|
+
/**
|
|
266
|
+
* Retrieves an instance for the given token.
|
|
267
|
+
* @template T - The type of value being retrieved
|
|
268
|
+
* @param token - The token or constructor to retrieve
|
|
269
|
+
* @returns The resolved instance
|
|
270
|
+
*/
|
|
271
|
+
get<T>(token: MultiNodeToken<T>): T[];
|
|
272
|
+
get<T>(token: NodeToken<T>): T;
|
|
273
|
+
get<T>(token: Ctor<T>): T;
|
|
274
|
+
/**
|
|
275
|
+
* Instantiates a class with injections in runtime using current context.
|
|
276
|
+
* Useful when creating an object that requires injections in runtime.
|
|
277
|
+
* Class does not get registered in the container and cannot be retrieved via {@link get} or {@link nodeInject}.
|
|
278
|
+
*
|
|
279
|
+
* @template T - The type of the class being instantiated
|
|
280
|
+
* @param ctor - The constructor of the class to instantiate
|
|
281
|
+
* @returns A new instance of the class with dependencies injected
|
|
282
|
+
* @throws {InjectionError} If called before bootstrap or if the constructor is invalid
|
|
283
|
+
* Must be called after {@link bootstrap}.
|
|
284
|
+
*/
|
|
285
|
+
produce<T>(fn: Ctor<T> | (() => T)): T;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Injector implementation that allows retrieving instances from the parent DI container.
|
|
289
|
+
*/
|
|
290
|
+
declare class InjectorImpl implements iInjector {
|
|
291
|
+
readonly container: iDIContainer;
|
|
292
|
+
constructor(container: iDIContainer);
|
|
293
|
+
get<T>(token: MultiNodeToken<T>): T[];
|
|
294
|
+
get<T>(token: NodeToken<T>): T;
|
|
295
|
+
get<T>(token: Ctor<T>): T;
|
|
296
|
+
produce<T>(fn: Ctor<T> | (() => T)): T;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Injector node that is used to access provider outside of injection context.
|
|
300
|
+
* @example
|
|
301
|
+
* ```typescript
|
|
302
|
+
* import { Injector, nodeInject, NodeInjectable, NodeContainer } from "@illuma/core";
|
|
303
|
+
*
|
|
304
|
+
* @NodeInjectable()
|
|
305
|
+
* class MyService {
|
|
306
|
+
* private readonly _injector = nodeInject(Injector);
|
|
307
|
+
* public doSomething() {
|
|
308
|
+
* const otherService = this._injector.get(OtherService);
|
|
309
|
+
* // Use otherService...
|
|
310
|
+
* }
|
|
311
|
+
* }
|
|
312
|
+
* ```
|
|
313
|
+
*/
|
|
314
|
+
declare const Injector: NodeToken<iInjector>;
|
|
315
|
+
|
|
316
|
+
type MaybeAsyncFactory<T> = () => T | Promise<T>;
|
|
317
|
+
interface iInjectionOptions {
|
|
318
|
+
/**
|
|
319
|
+
* Whether to cache the result of the injection function
|
|
320
|
+
* Prevents multiple invocations from creating multiple sub-containers or injections
|
|
321
|
+
* @default true
|
|
322
|
+
*/
|
|
323
|
+
withCache?: boolean;
|
|
324
|
+
/**
|
|
325
|
+
* Overrides to provide to the sub-container
|
|
326
|
+
* These will be provided in addition to the main injection
|
|
327
|
+
* @default []
|
|
328
|
+
*/
|
|
329
|
+
overrides?: Provider[];
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Creates an async function that injects a group of dependencies as a sub-container.
|
|
333
|
+
* The returned function, when called, will create a new sub-container, provide the given dependencies,
|
|
334
|
+
* bootstrap it, and return its injector.
|
|
335
|
+
*
|
|
336
|
+
* @note
|
|
337
|
+
* `injectGroupAsync` should be called within an injection context where the parent container is accessible.
|
|
338
|
+
*
|
|
339
|
+
* @param fn - A function that returns an array of providers or a promise resolving to one
|
|
340
|
+
* @returns A function that returns a promise resolving to the injector of the sub-container
|
|
341
|
+
*/
|
|
342
|
+
declare function injectGroupAsync(fn: MaybeAsyncFactory<Provider[]>, opts?: iInjectionOptions): () => Promise<iInjector>;
|
|
343
|
+
/**
|
|
344
|
+
* Creates an async function that injects a dependency for the given token or constructor.
|
|
345
|
+
* The returned function, when called, will create a new sub-container,
|
|
346
|
+
* provide the token or constructor, bootstrap it, and return the resolved instance(s).
|
|
347
|
+
*
|
|
348
|
+
* @note
|
|
349
|
+
* `injectAsync` should be called within an injection context where the parent container is accessible.
|
|
350
|
+
*
|
|
351
|
+
* @template T - The type of value being injected
|
|
352
|
+
* @param fn - A function that returns a token, constructor, or a promise resolving to one
|
|
353
|
+
* @returns A function that returns a promise resolving to the injected instance(s)
|
|
354
|
+
*/
|
|
355
|
+
declare function injectAsync<T>(fn: MaybeAsyncFactory<MultiNodeToken<T>>, opts?: iInjectionOptions): () => Promise<T[]>;
|
|
356
|
+
declare function injectAsync<T>(fn: MaybeAsyncFactory<NodeToken<T>>, opts?: iInjectionOptions): () => Promise<T>;
|
|
357
|
+
declare function injectAsync<T>(fn: MaybeAsyncFactory<Ctor<T>>, opts?: iInjectionOptions): () => Promise<T>;
|
|
358
|
+
interface iEntrypointConfig<T extends Token<any>> {
|
|
359
|
+
readonly entrypoint: T;
|
|
360
|
+
readonly providers: Provider[];
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Creates an async function that injects a sub-container with a specific entrypoint.
|
|
364
|
+
* The returned function, when called, will create a new sub-container,
|
|
365
|
+
* provide the given providers, bootstrap it, and return the resolved instance(s) of the entrypoint.
|
|
366
|
+
*
|
|
367
|
+
* @note
|
|
368
|
+
* `injectEntryAsync` should be called within an injection context where the parent container is accessible.
|
|
369
|
+
*
|
|
370
|
+
* @template T - The type of the entrypoint token
|
|
371
|
+
* @param fn - A function that returns an entrypoint configuration or a promise resolving to one
|
|
372
|
+
* @returns A function that returns a promise resolving to the injected instance(s) of the entrypoint
|
|
373
|
+
*/
|
|
374
|
+
declare function injectEntryAsync<T>(fn: MaybeAsyncFactory<iEntrypointConfig<NodeToken<T>>>, opts?: iInjectionOptions): () => Promise<T[]>;
|
|
375
|
+
declare function injectEntryAsync<T>(fn: MaybeAsyncFactory<iEntrypointConfig<Ctor<T>>>, opts?: iInjectionOptions): () => Promise<T>;
|
|
376
|
+
declare function injectEntryAsync<T>(fn: MaybeAsyncFactory<iEntrypointConfig<MultiNodeToken<T>>>, opts?: iInjectionOptions): () => Promise<T>;
|
|
377
|
+
|
|
378
|
+
export { Ctor, INJECTION_SYMBOL, InjectionContext, InjectionError, Injector, type InjectorFn, InjectorImpl, MultiNodeToken, NodeBase, NodeContainer, NodeInjectable, NodeToken, Provider, Token, getInjectableToken, type iDIContainer, type iEntrypointConfig, iInjectionNode, type iInjector, injectAsync, injectEntryAsync, injectGroupAsync, isConstructor, isInjectable, makeInjectable };
|