@vielzeug/conduit 3.0.0 → 26.10.1
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/README.md +1 -1
- package/dist/conduit.cjs +1 -1
- package/dist/conduit.cjs.map +1 -1
- package/dist/conduit.iife.js +1 -1
- package/dist/conduit.iife.js.map +1 -1
- package/dist/conduit.js +1 -1
- package/dist/conduit.js.map +1 -1
- package/dist/container.cjs +1 -1
- package/dist/container.cjs.map +1 -1
- package/dist/container.d.ts +2 -2
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +1 -201
- package/dist/container.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +1 -14
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -51
- package/dist/errors.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -4
- package/dist/types.cjs +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.ts +19 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -26
- package/dist/types.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -38,4 +38,4 @@ await container.dispose();
|
|
|
38
38
|
|
|
39
39
|
## License
|
|
40
40
|
|
|
41
|
-
MIT © [Helmuth Saatkamp](https://github.com/helmuthdu)
|
|
41
|
+
MIT © [Helmuth Saatkamp](https://github.com/helmuthdu): part of the [Vielzeug](https://github.com/helmuthdu/vielzeug) monorepo.
|
package/dist/conduit.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function tokenName(e){return e.description??`anonymous`}var ConduitError=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},ConduitCircularDependencyError=class extends ConduitError{cycle;constructor(e){super(`Circular dependency detected: ${e.map(tokenName).join(` -> `)}`),this.cycle=Object.freeze([...e])}},ConduitProviderNotFoundError=class extends ConduitError{containerName;token;constructor(e,t){super(`No provider registered for token: ${tokenName(e)} (in container '${t}')`),this.containerName=t,this.token=e}},ConduitDuplicateRegistrationError=class extends ConduitError{token;constructor(e){super(`Token "${tokenName(e)}" is already registered.`),this.token=e}},ConduitDisposedError=class extends ConduitError{containerName;constructor(e){super(`Cannot use disposed container '${e}'.`),this.containerName=e}},ConduitDisposeError=class extends ConduitError{errors;constructor(e){super(`Container disposal failed with ${e.length} cleanup error${e.length===1?``:`s`}.`),this.errors=Object.freeze([...e])}};function token(e){return Symbol(e)}var e=token(`Conduit disposal signal`);function valueProvider(e,t,n={}){return Object.freeze({...n,token:e,value:t})}function factoryProvider(e,t,n,r={}){return Object.freeze({...r,dependencies:Object.freeze([...t]),factory:n,token:e})}var t=class ContainerImpl{#e=new Map;#t=new Set;#n=[];#r=new AbortController;#i=new Set;#a=`active`;#o;#s=[];#c;#l=new Map;name;constructor(t,n,r){this.#c=t,t&&t.#t.add(this),this.name=r.name??(t?`${t.name}:child`:`root`),this.#l.set(e,{kind:`value`,value:this.disposalSignal});try{this.#p(n),this.#_(),this.#m()}catch(e){throw t&&t.#t.delete(this),this.#l.clear(),e}}get disposalSignal(){return this.#r.signal}get disposed(){return this.#a===`disposed`}has(e){return this.#d(),this.#h(e)!==void 0}async resolve(e){if(this.#d(),typeof e==`symbol`)return this.#y(e,[]);if(typeof e!=`object`||!e||Array.isArray(e))throw new ConduitError(`resolve() requires a token or service map`);let t=Object.keys(e),n=await Promise.all(t.map(t=>this.#y(e[t],[]))),r={};return t.forEach((e,t)=>{Object.defineProperty(r,e,{configurable:!0,enumerable:!0,value:n[t],writable:!0})}),r}createScope(e={}){return this.#d(),new ContainerImpl(this,e.providers??[],{name:e.name})}dispose(){return this.#a===`disposed`?Promise.resolve():this.#o?this.#o:(this.#a=`disposing`,this.#r.abort(),this.#o=this.#u(),this.#o)}async[Symbol.asyncDispose](){await this.dispose()}async#u(){let e=await Promise.allSettled([...this.#t].map(e=>e.dispose()));await Promise.allSettled([...this.#i]);let t=[...this.#n,...e.flatMap(e=>e.status===`rejected`?e.reason instanceof ConduitDisposeError?e.reason.errors:[e.reason]:[])];for(let e of[...this.#s].reverse())if(e.dispose)try{await e.dispose(e.value)}catch(e){t.push(e)}if(this.#e.clear(),this.#t.clear(),this.#n=[],this.#s=[],this.#l.clear(),this.#c&&this.#c.#t.delete(this),this.#a=`disposed`,t.length)throw new ConduitDisposeError(t)}#d(){if(this.#a!==`active`)throw new ConduitDisposedError(this.name)}#f(e){if(this.#l.has(e))throw new ConduitDuplicateRegistrationError(e)}#p(e){if(!Array.isArray(e))throw new ConduitError(`Container providers must be an array`);for(let t of e){if(typeof t!=`object`||!t||Array.isArray(t))throw new ConduitError(`Each provider must be an object`);let e=t,n=Object.hasOwn(e,`dependencies`),r=Object.hasOwn(e,`factory`),i=Object.hasOwn(e,`value`);if(typeof e.token!=`symbol`)throw new ConduitError(`Each provider requires a token`);if(e.dispose!==void 0&&typeof e.dispose!=`function`)throw new ConduitError(`Provider "${e.token.description??`anonymous`}" has an invalid disposer`);if(i===r||i===n||i&&Object.hasOwn(e,`lifetime`))throw new ConduitError(`Provider "${e.token.description??`anonymous`}" must define exactly one value or factory`);if(this.#f(e.token),r){let t=e;if(!Array.isArray(t.dependencies)||t.dependencies.some(e=>typeof e!=`symbol`))throw new ConduitError(`Factory provider "${e.token.description??`anonymous`}" has invalid dependencies`);if(typeof t.factory!=`function`)throw new ConduitError(`Factory provider "${e.token.description??`anonymous`}" requires a factory`);if(t.lifetime!==void 0&&t.lifetime!==`singleton`&&t.lifetime!==`transient`)throw new ConduitError(`Factory provider "${e.token.description??`anonymous`}" has an invalid lifetime`);this.#l.set(e.token,{dependencies:Object.freeze([...t.dependencies]),dispose:t.dispose,factory:t.factory,kind:`factory`,lifetime:t.lifetime??`singleton`})}else{let t=e;this.#l.set(e.token,{dispose:t.dispose,kind:`value`,value:t.value})}}}#m(){for(let e of this.#l.values())e.kind===`value`&&e.dispose&&this.#s.push({dispose:e.dispose,value:e.value})}#h(e){let t=this.#l.get(e);if(t)return{owner:this,registration:t};if(this.#c)return this.#c.#h(e)}#g(){let e=this.#c?this.#c.#g():[],t=[...this.#l].flatMap(([e,t])=>t.kind===`factory`?[{owner:this,registration:t,token:e}]:[]);return[...e,...t]}#_(){for(let{owner:e,registration:t,token:n}of this.#g())e.#v(n,t,new Set,[])}#v(e,t,n,r){if(n.has(e))throw new ConduitCircularDependencyError([...r,e]);n.add(e);for(let i of t.dependencies){let a=this.#h(i);if(!a)throw new ConduitProviderNotFoundError(i,this.name);if(a.registration.kind===`factory`){if(t.lifetime===`singleton`&&a.registration.lifetime===`transient`)throw new ConduitError(`Singleton "${e.description??`anonymous`}" cannot depend on a transient factory`);a.owner.#v(i,a.registration,n,[...r,e])}}n.delete(e)}async#y(e,t){if(t.includes(e))throw new ConduitCircularDependencyError([...t,e]);let n=this.#h(e);if(!n)throw new ConduitProviderNotFoundError(e,this.name);let r=n.registration;if(r.kind===`value`)return r.value;if(r.lifetime===`transient`)return this.#b(this.#x(r,this,[...t,e]));let i=n.owner,a=i.#e.get(r);if(a?.resolved)return a.value;if(a)return a.promise;let o={promise:Promise.resolve(),resolved:!1},s=i.#x(r,i,[...t,e]).then(e=>(o.resolved=!0,o.value=e,e),e=>{throw i.#e.get(r)===o&&i.#e.delete(r),e});return o.promise=i.#b(s),i.#e.set(r,o),o.promise}#b(e){return this.#i.add(e),e.then(()=>this.#i.delete(e),()=>this.#i.delete(e)),e}async#x(e,t,n){let r=await Promise.all(e.dependencies.map(e=>t.#y(e,n))).then(t=>e.factory(...t));if(t.#a!==`active`){if(e.dispose)try{await e.dispose(r)}catch(e){t.#n.push(e)}throw new ConduitDisposedError(t.name)}return e.dispose&&t.#s.push({dispose:e.dispose,value:r}),r}};function createContainer(e,n){return new t(void 0,e,{name:n?.name})}exports.ConduitCircularDependencyError=ConduitCircularDependencyError,exports.ConduitDisposeError=ConduitDisposeError,exports.ConduitDisposedError=ConduitDisposedError,exports.ConduitDuplicateRegistrationError=ConduitDuplicateRegistrationError,exports.ConduitError=ConduitError,exports.ConduitProviderNotFoundError=ConduitProviderNotFoundError,exports.createContainer=createContainer,exports.disposalSignalToken=e,exports.factoryProvider=factoryProvider,exports.token=token,exports.valueProvider=valueProvider;
|
|
2
2
|
//# sourceMappingURL=conduit.cjs.map
|
package/dist/conduit.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conduit.cjs","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/container.ts"],"sourcesContent":["import type { ScopeToken, Token } from './types.js';\n\nexport function tokenName(token: Token<unknown>): string {\n return token.description ?? 'anonymous';\n}\n\nexport class ConduitError extends Error {\n protected static readonly errorName: string = 'ConduitError';\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = (new.target as typeof ConduitError).errorName;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class ConduitCircularDependencyError extends ConduitError {\n protected static override readonly errorName = 'ConduitCircularDependencyError';\n readonly cycle: readonly Token<unknown>[];\n\n constructor(cycle: readonly Token<unknown>[]) {\n super(`Circular dependency detected: ${cycle.map(tokenName).join(' -> ')}`);\n this.cycle = Object.freeze([...cycle]);\n }\n}\n\nexport class ConduitProviderNotFoundError extends ConduitError {\n protected static override readonly errorName = 'ConduitProviderNotFoundError';\n readonly containerName: string;\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>, containerName: string) {\n super(`No provider registered for token: ${tokenName(token)} (in container '${containerName}')`);\n this.containerName = containerName;\n this.token = token;\n }\n}\n\nexport class ConduitDuplicateRegistrationError extends ConduitError {\n protected static override readonly errorName = 'ConduitDuplicateRegistrationError';\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>) {\n super(`Token \"${tokenName(token)}\" is already registered.`);\n this.token = token;\n }\n}\n\nexport class ConduitScopedResolutionError extends ConduitError {\n protected static override readonly errorName = 'ConduitScopedResolutionError';\n readonly requiredScope: ScopeToken;\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>, requiredScope: ScopeToken) {\n super(`Token \"${tokenName(token)}\" requires scope \"${requiredScope.description ?? 'anonymous'}\".`);\n this.requiredScope = requiredScope;\n this.token = token;\n }\n}\n\nexport class ConduitDisposedError extends ConduitError {\n protected static override readonly errorName = 'ConduitDisposedError';\n readonly containerName: string;\n\n constructor(containerName: string) {\n super(`Cannot use disposed container '${containerName}'.`);\n this.containerName = containerName;\n }\n}\n\nexport class ConduitDisposeError extends ConduitError {\n protected static override readonly errorName = 'ConduitDisposeError';\n readonly errors: readonly unknown[];\n\n constructor(errors: readonly unknown[]) {\n super(`Container disposal failed with ${errors.length} cleanup error${errors.length === 1 ? '' : 's'}.`);\n this.errors = Object.freeze([...errors]);\n }\n}\n","declare const tokenBrand: unique symbol;\ndeclare const scopeBrand: unique symbol;\n\nexport type Token<T = unknown> = symbol & { readonly [tokenBrand]: T };\nexport type ScopeToken = symbol & { readonly [scopeBrand]: true };\n\nexport function token<T>(description: string): Token<T> {\n return Symbol(description) as Token<T>;\n}\n\nexport function scope(name: string): ScopeToken {\n return Symbol(name) as ScopeToken;\n}\n\nexport const disposalSignalToken = token<AbortSignal>('Conduit disposal signal');\n\n/** Singleton results are cached on the registering container; transient results belong to the requesting container; a `ScopeToken` caches on the matching child scope. */\nexport type Lifetime = 'singleton' | 'transient' | ScopeToken;\n\nexport type InferTokens<T extends readonly Token<unknown>[]> = {\n [K in keyof T]: T[K] extends Token<infer Value> ? Value : never;\n};\n\nexport type ValueOptions<T> = Readonly<{\n dispose?: (value: T) => Promise<void> | void;\n}>;\n\nexport type FactoryOptions<T> = Readonly<{\n dispose?: (value: T) => Promise<void> | void;\n lifetime?: Lifetime;\n}>;\n\nexport interface ValueProvider<T> {\n readonly dispose?: (value: T) => Promise<void> | void;\n readonly token: Token<T>;\n readonly value: T;\n}\n\nexport interface FactoryProvider<T, Dependencies extends readonly Token<unknown>[] = readonly Token<unknown>[]> {\n readonly dependencies: Dependencies;\n readonly dispose?: (value: T) => Promise<void> | void;\n readonly factory: (...values: InferTokens<Dependencies>) => Promise<T> | T;\n readonly lifetime?: Lifetime;\n readonly token: Token<T>;\n}\n\nexport type Provider<T = unknown, Dependencies extends readonly Token<unknown>[] = readonly Token<unknown>[]> =\n | ValueProvider<T>\n | FactoryProvider<T, Dependencies>;\n\nexport function valueProvider<T>(token: Token<T>, value: NoInfer<T>, options: ValueOptions<T> = {}): ValueProvider<T> {\n return Object.freeze({ ...options, token, value });\n}\n\nexport function factoryProvider<T, const Dependencies extends readonly Token<unknown>[]>(\n token: Token<T>,\n dependencies: Dependencies,\n factory: (...values: InferTokens<Dependencies>) => Promise<T> | T,\n options: FactoryOptions<T> = {},\n): FactoryProvider<T, Dependencies> {\n return Object.freeze({\n ...options,\n dependencies: Object.freeze([...dependencies]) as unknown as Dependencies,\n factory,\n token,\n });\n}\n\n/** Map of service name to dependency token, passed to `container.resolve()` at a composition root. */\nexport type ServiceMap = { readonly [key: string]: Token<unknown> };\n\nexport type InferServices<M extends ServiceMap> = {\n readonly [K in keyof M]: M[K] extends Token<infer Value> ? Value : never;\n};\n\nexport interface Container {\n createScope(\n scope?: ScopeToken,\n options?: { readonly name?: string; readonly providers?: readonly Provider<any, any>[] },\n ): Container;\n readonly disposalSignal: AbortSignal;\n dispose(): Promise<void>;\n readonly disposed: boolean;\n has<T>(token: Token<T>): boolean;\n readonly name: string;\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n","import {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n ConduitScopedResolutionError,\n} from './errors.js';\nimport type {\n Container,\n FactoryProvider,\n InferServices,\n Lifetime,\n Provider,\n ScopeToken,\n ServiceMap,\n Token,\n ValueProvider,\n} from './types.js';\nimport { disposalSignalToken } from './types.js';\n\ntype Disposer = (value: unknown) => Promise<void> | void;\n\ntype ValueRegistration<T> = Readonly<{\n dispose?: Disposer;\n kind: 'value';\n value: T;\n}>;\n\ntype FactoryRegistration<T = unknown> = Readonly<{\n factory: (...values: unknown[]) => Promise<T> | T;\n dependencies: readonly Token<unknown>[];\n dispose?: Disposer;\n kind: 'factory';\n lifetime: Lifetime;\n}>;\n\ntype Registration<T = unknown> = FactoryRegistration<T> | ValueRegistration<T>;\ntype OwnedResource = Readonly<{ dispose?: Disposer; value: unknown }>;\ntype CacheEntry = { promise: Promise<unknown>; resolved: boolean; value?: unknown };\ntype Lifecycle = 'active' | 'disposed' | 'disposing';\n\nclass ContainerImpl implements Container {\n #cache = new Map<FactoryRegistration<unknown>, CacheEntry>();\n #children = new Set<ContainerImpl>();\n #cleanupFailures: unknown[] = [];\n #disposalController = new AbortController();\n #inFlight = new Set<Promise<unknown>>();\n #lifecycle: Lifecycle = 'active';\n #disposePromise?: Promise<void>;\n #owned: OwnedResource[] = [];\n #parent?: ContainerImpl;\n #registry = new Map<Token<unknown>, Registration<unknown>>();\n #scope?: ScopeToken;\n readonly name: string;\n\n constructor(\n parent: ContainerImpl | undefined,\n providers: readonly Provider<any, any>[],\n options: { name?: string; scope?: ScopeToken },\n ) {\n this.#parent = parent;\n this.#scope = options.scope;\n\n if (parent) parent.#children.add(this);\n\n this.name = options.name ?? (parent ? `${parent.name}:${options.scope?.description ?? 'child'}` : 'root');\n this.#registry.set(disposalSignalToken, { kind: 'value', value: this.disposalSignal });\n\n try {\n this.#registerProviders(providers);\n this.#validateGraph();\n this.#claimValues();\n } catch (error) {\n if (parent) parent.#children.delete(this);\n this.#registry.clear();\n throw error;\n }\n }\n\n get disposalSignal(): AbortSignal {\n return this.#disposalController.signal;\n }\n\n get disposed(): boolean {\n return this.#lifecycle === 'disposed';\n }\n\n has<T>(token: Token<T>): boolean {\n this.#assertActive();\n\n return this.#lookup(token) !== undefined;\n }\n\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n async resolve<T, M extends ServiceMap>(input: Token<T> | M): Promise<InferServices<M> | T> {\n this.#assertActive();\n\n if (typeof input === 'symbol') return this.#resolve(input, []);\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw new ConduitError('resolve() requires a token or service map');\n }\n\n const entries = Object.keys(input) as (keyof M & string)[];\n const values = await Promise.all(entries.map((key) => this.#resolve(input[key] as Token<unknown>, [])));\n const services = {} as InferServices<M>;\n\n entries.forEach((key, index) => {\n Object.defineProperty(services, key, {\n configurable: true,\n enumerable: true,\n value: values[index],\n writable: true,\n });\n });\n\n return services;\n }\n\n createScope(\n scope?: ScopeToken,\n options?: { readonly name?: string; readonly providers?: readonly Provider<any, any>[] },\n ): Container {\n this.#assertActive();\n\n return new ContainerImpl(this, options?.providers ?? [], { name: options?.name, scope });\n }\n\n dispose(): Promise<void> {\n if (this.#lifecycle === 'disposed') return Promise.resolve();\n\n if (this.#disposePromise) return this.#disposePromise;\n\n this.#lifecycle = 'disposing';\n this.#disposalController.abort();\n this.#disposePromise = this.#finishDisposal();\n\n return this.#disposePromise;\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.dispose();\n }\n\n async #finishDisposal(): Promise<void> {\n const childOutcomes = await Promise.allSettled([...this.#children].map((child) => child.dispose()));\n\n await Promise.allSettled([...this.#inFlight]);\n\n const failures = [\n ...this.#cleanupFailures,\n ...childOutcomes.flatMap((outcome) => {\n if (outcome.status !== 'rejected') return [];\n\n return outcome.reason instanceof ConduitDisposeError ? outcome.reason.errors : [outcome.reason];\n }),\n ];\n\n for (const resource of [...this.#owned].reverse()) {\n if (!resource.dispose) continue;\n\n try {\n await resource.dispose(resource.value);\n } catch (error) {\n failures.push(error);\n }\n }\n\n this.#cache.clear();\n this.#children.clear();\n this.#cleanupFailures = [];\n this.#owned = [];\n this.#registry.clear();\n\n if (this.#parent) this.#parent.#children.delete(this);\n\n this.#lifecycle = 'disposed';\n\n if (failures.length) throw new ConduitDisposeError(failures);\n }\n\n #assertActive(): void {\n if (this.#lifecycle !== 'active') throw new ConduitDisposedError(this.name);\n }\n\n #assertUnregistered(token: Token<unknown>): void {\n if (this.#registry.has(token)) throw new ConduitDuplicateRegistrationError(token);\n }\n\n #registerProviders(providers: readonly Provider<any, any>[]): void {\n if (!Array.isArray(providers)) throw new ConduitError('Container providers must be an array');\n\n for (const input of providers) {\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw new ConduitError('Each provider must be an object');\n }\n\n const provider = input as Provider;\n const hasDependencies = Object.hasOwn(provider, 'dependencies');\n const hasFactory = Object.hasOwn(provider, 'factory');\n const hasValue = Object.hasOwn(provider, 'value');\n\n if (typeof provider.token !== 'symbol') throw new ConduitError('Each provider requires a token');\n if (provider.dispose !== undefined && typeof provider.dispose !== 'function') {\n throw new ConduitError(`Provider \"${provider.token.description ?? 'anonymous'}\" has an invalid disposer`);\n }\n if (\n hasValue === hasFactory ||\n hasValue === hasDependencies ||\n (hasValue && Object.hasOwn(provider, 'lifetime'))\n ) {\n throw new ConduitError(\n `Provider \"${provider.token.description ?? 'anonymous'}\" must define exactly one value or factory`,\n );\n }\n\n this.#assertUnregistered(provider.token);\n\n if (hasFactory) {\n const factory = provider as FactoryProvider<unknown>;\n\n if (\n !Array.isArray(factory.dependencies) ||\n factory.dependencies.some((dependency) => typeof dependency !== 'symbol')\n ) {\n throw new ConduitError(\n `Factory provider \"${provider.token.description ?? 'anonymous'}\" has invalid dependencies`,\n );\n }\n if (typeof factory.factory !== 'function') {\n throw new ConduitError(`Factory provider \"${provider.token.description ?? 'anonymous'}\" requires a factory`);\n }\n if (\n factory.lifetime !== undefined &&\n factory.lifetime !== 'singleton' &&\n factory.lifetime !== 'transient' &&\n typeof factory.lifetime !== 'symbol'\n ) {\n throw new ConduitError(\n `Factory provider \"${provider.token.description ?? 'anonymous'}\" has an invalid lifetime`,\n );\n }\n\n this.#registry.set(provider.token, {\n dependencies: Object.freeze([...factory.dependencies]),\n dispose: factory.dispose as Disposer | undefined,\n factory: factory.factory as (...values: unknown[]) => Promise<unknown> | unknown,\n kind: 'factory',\n lifetime: factory.lifetime ?? 'singleton',\n });\n } else {\n const valueProvider = provider as ValueProvider<unknown>;\n\n this.#registry.set(provider.token, {\n dispose: valueProvider.dispose as Disposer | undefined,\n kind: 'value',\n value: valueProvider.value,\n });\n }\n }\n }\n\n #claimValues(): void {\n for (const registration of this.#registry.values()) {\n if (registration.kind === 'value' && registration.dispose) {\n this.#owned.push({ dispose: registration.dispose, value: registration.value });\n }\n }\n }\n\n #lookup<T>(token: Token<T>): { owner: ContainerImpl; registration: Registration<T> } | undefined {\n const local = this.#registry.get(token) as Registration<T> | undefined;\n\n if (local) return { owner: this, registration: local };\n\n if (!this.#parent) return undefined;\n\n return this.#parent.#lookup(token);\n }\n\n #factories(): { owner: ContainerImpl; registration: FactoryRegistration; token: Token<unknown> }[] {\n const parentFactories = this.#parent ? this.#parent.#factories() : [];\n const localFactories = [...this.#registry].flatMap(([token, registration]) =>\n registration.kind === 'factory' ? [{ owner: this, registration, token }] : [],\n );\n\n return [...parentFactories, ...localFactories];\n }\n\n #validateGraph(): void {\n for (const { owner, registration, token } of this.#factories()) {\n owner.#validatePath(token, registration, new Set(), []);\n }\n }\n\n #validatePath(\n token: Token<unknown>,\n registration: FactoryRegistration,\n visiting: Set<Token<unknown>>,\n path: Token<unknown>[],\n ): void {\n if (visiting.has(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n visiting.add(token);\n\n for (const dependency of registration.dependencies) {\n const found = this.#lookup(dependency);\n\n if (!found) throw new ConduitProviderNotFoundError(dependency, this.name);\n\n if (found.registration.kind === 'factory') {\n if (registration.lifetime === 'singleton' && found.registration.lifetime === 'transient') {\n throw new ConduitError(\n `Singleton \"${token.description ?? 'anonymous'}\" cannot depend on a transient factory`,\n );\n }\n if (registration.lifetime === 'singleton' && typeof found.registration.lifetime === 'symbol') {\n throw new ConduitScopedResolutionError(token, found.registration.lifetime);\n }\n if (\n typeof registration.lifetime === 'symbol' &&\n typeof found.registration.lifetime === 'symbol' &&\n registration.lifetime !== found.registration.lifetime\n ) {\n throw new ConduitScopedResolutionError(token, found.registration.lifetime);\n }\n\n found.owner.#validatePath(dependency, found.registration, visiting, [...path, token]);\n }\n }\n\n visiting.delete(token);\n }\n\n async #resolve<T>(token: Token<T>, path: Token<unknown>[]): Promise<T> {\n if (path.includes(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n const found = this.#lookup(token);\n\n if (!found) throw new ConduitProviderNotFoundError(token, this.name);\n\n const registration = found.registration;\n\n if (registration.kind === 'value') return registration.value as T;\n\n const owner = this.#ownerFor(found.owner, registration, token);\n\n if (registration.lifetime === 'transient') {\n return owner.#track(owner.#create(registration, owner, [...path, token])) as Promise<T>;\n }\n\n const existing = owner.#cache.get(registration);\n\n if (existing?.resolved) return existing.value as T;\n if (existing) return existing.promise as Promise<T>;\n\n const entry = { promise: Promise.resolve(), resolved: false } as CacheEntry;\n const creation = owner.#create(registration, owner, [...path, token]).then(\n (value) => {\n entry.resolved = true;\n entry.value = value;\n return value;\n },\n (error) => {\n if (owner.#cache.get(registration) === entry) owner.#cache.delete(registration);\n throw error;\n },\n );\n\n entry.promise = owner.#track(creation);\n owner.#cache.set(registration, entry);\n\n return entry.promise as Promise<T>;\n }\n\n #ownerFor(owner: ContainerImpl, registration: FactoryRegistration, token: Token<unknown>): ContainerImpl {\n if (registration.lifetime === 'singleton') return owner;\n if (registration.lifetime === 'transient') return this;\n\n const scopeOwner = this.#scopeOwner(registration.lifetime as ScopeToken);\n\n if (!scopeOwner) throw new ConduitScopedResolutionError(token, registration.lifetime as ScopeToken);\n\n return scopeOwner;\n }\n\n #scopeOwner(scope: ScopeToken): ContainerImpl | undefined {\n if (this.#scope === scope) return this;\n\n return this.#parent ? this.#parent.#scopeOwner(scope) : undefined;\n }\n\n #track<T>(promise: Promise<T>): Promise<T> {\n this.#inFlight.add(promise);\n void promise.then(\n () => this.#inFlight.delete(promise),\n () => this.#inFlight.delete(promise),\n );\n return promise;\n }\n\n async #create(registration: FactoryRegistration, owner: ContainerImpl, path: Token<unknown>[]): Promise<unknown> {\n const value = await Promise.all(\n registration.dependencies.map((dependency) => owner.#resolve(dependency, path)),\n ).then((dependencies) => registration.factory(...dependencies));\n\n if (owner.#lifecycle !== 'active') {\n if (registration.dispose) {\n try {\n await registration.dispose(value);\n } catch (error) {\n owner.#cleanupFailures.push(error);\n }\n }\n\n throw new ConduitDisposedError(owner.name);\n }\n\n if (registration.dispose) owner.#owned.push({ dispose: registration.dispose, value });\n\n return value;\n }\n}\n\nexport function createContainer(\n providers: readonly Provider<any, any>[],\n options?: { readonly name?: string },\n): Container {\n return new ContainerImpl(undefined, providers, { name: options?.name });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"conduit.cjs","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/container.ts"],"sourcesContent":["import type { Token } from './types.js';\n\nfunction tokenName(token: Token<unknown>): string {\n return token.description ?? 'anonymous';\n}\n\nexport class ConduitError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class ConduitCircularDependencyError extends ConduitError {\n readonly cycle: readonly Token<unknown>[];\n\n constructor(cycle: readonly Token<unknown>[]) {\n super(`Circular dependency detected: ${cycle.map(tokenName).join(' -> ')}`);\n this.cycle = Object.freeze([...cycle]);\n }\n}\n\nexport class ConduitProviderNotFoundError extends ConduitError {\n readonly containerName: string;\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>, containerName: string) {\n super(`No provider registered for token: ${tokenName(token)} (in container '${containerName}')`);\n this.containerName = containerName;\n this.token = token;\n }\n}\n\nexport class ConduitDuplicateRegistrationError extends ConduitError {\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>) {\n super(`Token \"${tokenName(token)}\" is already registered.`);\n this.token = token;\n }\n}\n\nexport class ConduitDisposedError extends ConduitError {\n readonly containerName: string;\n\n constructor(containerName: string) {\n super(`Cannot use disposed container '${containerName}'.`);\n this.containerName = containerName;\n }\n}\n\nexport class ConduitDisposeError extends ConduitError {\n readonly errors: readonly unknown[];\n\n constructor(errors: readonly unknown[]) {\n super(`Container disposal failed with ${errors.length} cleanup error${errors.length === 1 ? '' : 's'}.`);\n this.errors = Object.freeze([...errors]);\n }\n}\n","declare const tokenBrand: unique symbol;\n\nexport type Token<T = unknown> = symbol & { readonly [tokenBrand]: T };\n\nexport function token<T>(description: string): Token<T> {\n return Symbol(description) as Token<T>;\n}\n\nexport const disposalSignalToken = token<AbortSignal>('Conduit disposal signal');\n\n/** Singleton results are cached on the registering container; transient results belong to the requesting container. */\nexport type Lifetime = 'singleton' | 'transient';\n\nexport type InferTokens<T extends readonly Token<unknown>[]> = {\n [K in keyof T]: T[K] extends Token<infer Value> ? Value : never;\n};\n\nexport type ValueOptions<T> = Readonly<{\n dispose?: (value: T) => Promise<void> | void;\n}>;\n\nexport type FactoryOptions<T> = Readonly<{\n dispose?: (value: T) => Promise<void> | void;\n lifetime?: Lifetime;\n}>;\n\nexport interface ValueProvider<T> {\n readonly dispose?: (value: T) => Promise<void> | void;\n readonly token: Token<T>;\n readonly value: T;\n}\n\nexport interface FactoryProvider<T, Dependencies extends readonly Token<unknown>[] = readonly Token<unknown>[]> {\n readonly dependencies: Dependencies;\n readonly dispose?: (value: T) => Promise<void> | void;\n readonly factory: (...values: InferTokens<Dependencies>) => Promise<T> | T;\n readonly lifetime?: Lifetime;\n readonly token: Token<T>;\n}\n\nexport type Provider<T = unknown, Dependencies extends readonly Token<unknown>[] = readonly Token<unknown>[]> =\n | ValueProvider<T>\n | FactoryProvider<T, Dependencies>;\n\n/**\n * Type-erased provider for the heterogeneous lists accepted by\n * `createContainer()` and `createScope()`. Providers are invariant in their\n * value type, so erasure needs `any` at this one boundary; registration\n * re-validates every provider at runtime.\n */\nexport type AnyProvider = Provider<any, any>;\n\nexport function valueProvider<T>(token: Token<T>, value: NoInfer<T>, options: ValueOptions<T> = {}): ValueProvider<T> {\n return Object.freeze({ ...options, token, value });\n}\n\nexport function factoryProvider<T, const Dependencies extends readonly Token<unknown>[]>(\n token: Token<T>,\n dependencies: Dependencies,\n factory: (...values: InferTokens<Dependencies>) => Promise<T> | T,\n options: FactoryOptions<T> = {},\n): FactoryProvider<T, Dependencies> {\n return Object.freeze({\n ...options,\n dependencies: Object.freeze([...dependencies]) as unknown as Dependencies,\n factory,\n token,\n });\n}\n\n/** Map of service name to dependency token, passed to `container.resolve()` at a composition root. */\nexport type ServiceMap = { readonly [key: string]: Token<unknown> };\n\nexport type InferServices<M extends ServiceMap> = {\n readonly [K in keyof M]: M[K] extends Token<infer Value> ? Value : never;\n};\n\nexport type CreateScopeOptions = Readonly<{\n name?: string;\n providers?: readonly AnyProvider[];\n}>;\n\nexport interface Container {\n /**\n * Create a child container that inherits parent registrations. Providers\n * registered on the child are local to it, which is how request-scoped\n * values are spelled: one child per request.\n */\n createScope(options?: CreateScopeOptions): Container;\n readonly disposalSignal: AbortSignal;\n dispose(): Promise<void>;\n readonly disposed: boolean;\n has<T>(token: Token<T>): boolean;\n readonly name: string;\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n","import {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n} from './errors.js';\nimport type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryProvider,\n InferServices,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueProvider,\n} from './types.js';\nimport { disposalSignalToken } from './types.js';\n\ntype Disposer = (value: unknown) => Promise<void> | void;\n\ntype ValueRegistration<T> = Readonly<{\n dispose?: Disposer;\n kind: 'value';\n value: T;\n}>;\n\ntype FactoryRegistration<T = unknown> = Readonly<{\n factory: (...values: unknown[]) => Promise<T> | T;\n dependencies: readonly Token<unknown>[];\n dispose?: Disposer;\n kind: 'factory';\n lifetime: Lifetime;\n}>;\n\ntype Registration<T = unknown> = FactoryRegistration<T> | ValueRegistration<T>;\ntype OwnedResource = Readonly<{ dispose?: Disposer; value: unknown }>;\ntype CacheEntry = { promise: Promise<unknown>; resolved: boolean; value?: unknown };\ntype Lifecycle = 'active' | 'disposed' | 'disposing';\n\nclass ContainerImpl implements Container {\n #cache = new Map<FactoryRegistration<unknown>, CacheEntry>();\n #children = new Set<ContainerImpl>();\n #cleanupFailures: unknown[] = [];\n #disposalController = new AbortController();\n #inFlight = new Set<Promise<unknown>>();\n #lifecycle: Lifecycle = 'active';\n #disposePromise?: Promise<void>;\n #owned: OwnedResource[] = [];\n #parent?: ContainerImpl;\n #registry = new Map<Token<unknown>, Registration<unknown>>();\n readonly name: string;\n\n constructor(parent: ContainerImpl | undefined, providers: readonly AnyProvider[], options: CreateScopeOptions) {\n this.#parent = parent;\n\n if (parent) parent.#children.add(this);\n\n this.name = options.name ?? (parent ? `${parent.name}:child` : 'root');\n this.#registry.set(disposalSignalToken, { kind: 'value', value: this.disposalSignal });\n\n try {\n this.#registerProviders(providers);\n this.#validateGraph();\n this.#claimValues();\n } catch (error) {\n if (parent) parent.#children.delete(this);\n this.#registry.clear();\n throw error;\n }\n }\n\n get disposalSignal(): AbortSignal {\n return this.#disposalController.signal;\n }\n\n get disposed(): boolean {\n return this.#lifecycle === 'disposed';\n }\n\n has<T>(token: Token<T>): boolean {\n this.#assertActive();\n\n return this.#lookup(token) !== undefined;\n }\n\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n async resolve<T, M extends ServiceMap>(input: Token<T> | M): Promise<InferServices<M> | T> {\n this.#assertActive();\n\n if (typeof input === 'symbol') return this.#resolve(input, []);\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw new ConduitError('resolve() requires a token or service map');\n }\n\n const entries = Object.keys(input) as (keyof M & string)[];\n const values = await Promise.all(entries.map((key) => this.#resolve(input[key] as Token<unknown>, [])));\n const services = {} as InferServices<M>;\n\n entries.forEach((key, index) => {\n Object.defineProperty(services, key, {\n configurable: true,\n enumerable: true,\n value: values[index],\n writable: true,\n });\n });\n\n return services;\n }\n\n createScope(options: CreateScopeOptions = {}): Container {\n this.#assertActive();\n\n return new ContainerImpl(this, options.providers ?? [], { name: options.name });\n }\n\n dispose(): Promise<void> {\n if (this.#lifecycle === 'disposed') return Promise.resolve();\n\n if (this.#disposePromise) return this.#disposePromise;\n\n this.#lifecycle = 'disposing';\n this.#disposalController.abort();\n this.#disposePromise = this.#finishDisposal();\n\n return this.#disposePromise;\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.dispose();\n }\n\n async #finishDisposal(): Promise<void> {\n const childOutcomes = await Promise.allSettled([...this.#children].map((child) => child.dispose()));\n\n await Promise.allSettled([...this.#inFlight]);\n\n const failures = [\n ...this.#cleanupFailures,\n ...childOutcomes.flatMap((outcome) => {\n if (outcome.status !== 'rejected') return [];\n\n return outcome.reason instanceof ConduitDisposeError ? outcome.reason.errors : [outcome.reason];\n }),\n ];\n\n for (const resource of [...this.#owned].reverse()) {\n if (!resource.dispose) continue;\n\n try {\n await resource.dispose(resource.value);\n } catch (error) {\n failures.push(error);\n }\n }\n\n this.#cache.clear();\n this.#children.clear();\n this.#cleanupFailures = [];\n this.#owned = [];\n this.#registry.clear();\n\n if (this.#parent) this.#parent.#children.delete(this);\n\n this.#lifecycle = 'disposed';\n\n if (failures.length) throw new ConduitDisposeError(failures);\n }\n\n #assertActive(): void {\n if (this.#lifecycle !== 'active') throw new ConduitDisposedError(this.name);\n }\n\n #assertUnregistered(token: Token<unknown>): void {\n if (this.#registry.has(token)) throw new ConduitDuplicateRegistrationError(token);\n }\n\n #registerProviders(providers: readonly AnyProvider[]): void {\n if (!Array.isArray(providers)) throw new ConduitError('Container providers must be an array');\n\n for (const input of providers) {\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw new ConduitError('Each provider must be an object');\n }\n\n const provider = input as Provider;\n const hasDependencies = Object.hasOwn(provider, 'dependencies');\n const hasFactory = Object.hasOwn(provider, 'factory');\n const hasValue = Object.hasOwn(provider, 'value');\n\n if (typeof provider.token !== 'symbol') throw new ConduitError('Each provider requires a token');\n if (provider.dispose !== undefined && typeof provider.dispose !== 'function') {\n throw new ConduitError(`Provider \"${provider.token.description ?? 'anonymous'}\" has an invalid disposer`);\n }\n if (\n hasValue === hasFactory ||\n hasValue === hasDependencies ||\n (hasValue && Object.hasOwn(provider, 'lifetime'))\n ) {\n throw new ConduitError(\n `Provider \"${provider.token.description ?? 'anonymous'}\" must define exactly one value or factory`,\n );\n }\n\n this.#assertUnregistered(provider.token);\n\n if (hasFactory) {\n const factory = provider as FactoryProvider<unknown>;\n\n if (\n !Array.isArray(factory.dependencies) ||\n factory.dependencies.some((dependency) => typeof dependency !== 'symbol')\n ) {\n throw new ConduitError(\n `Factory provider \"${provider.token.description ?? 'anonymous'}\" has invalid dependencies`,\n );\n }\n if (typeof factory.factory !== 'function') {\n throw new ConduitError(`Factory provider \"${provider.token.description ?? 'anonymous'}\" requires a factory`);\n }\n if (factory.lifetime !== undefined && factory.lifetime !== 'singleton' && factory.lifetime !== 'transient') {\n throw new ConduitError(\n `Factory provider \"${provider.token.description ?? 'anonymous'}\" has an invalid lifetime`,\n );\n }\n\n this.#registry.set(provider.token, {\n dependencies: Object.freeze([...factory.dependencies]),\n dispose: factory.dispose as Disposer | undefined,\n factory: factory.factory as (...values: unknown[]) => Promise<unknown> | unknown,\n kind: 'factory',\n lifetime: factory.lifetime ?? 'singleton',\n });\n } else {\n const valueProvider = provider as ValueProvider<unknown>;\n\n this.#registry.set(provider.token, {\n dispose: valueProvider.dispose as Disposer | undefined,\n kind: 'value',\n value: valueProvider.value,\n });\n }\n }\n }\n\n #claimValues(): void {\n for (const registration of this.#registry.values()) {\n if (registration.kind === 'value' && registration.dispose) {\n this.#owned.push({ dispose: registration.dispose, value: registration.value });\n }\n }\n }\n\n #lookup<T>(token: Token<T>): { owner: ContainerImpl; registration: Registration<T> } | undefined {\n const local = this.#registry.get(token) as Registration<T> | undefined;\n\n if (local) return { owner: this, registration: local };\n\n if (!this.#parent) return undefined;\n\n return this.#parent.#lookup(token);\n }\n\n #factories(): { owner: ContainerImpl; registration: FactoryRegistration; token: Token<unknown> }[] {\n const parentFactories = this.#parent ? this.#parent.#factories() : [];\n const localFactories = [...this.#registry].flatMap(([token, registration]) =>\n registration.kind === 'factory' ? [{ owner: this, registration, token }] : [],\n );\n\n return [...parentFactories, ...localFactories];\n }\n\n #validateGraph(): void {\n for (const { owner, registration, token } of this.#factories()) {\n owner.#validatePath(token, registration, new Set(), []);\n }\n }\n\n #validatePath(\n token: Token<unknown>,\n registration: FactoryRegistration,\n visiting: Set<Token<unknown>>,\n path: Token<unknown>[],\n ): void {\n if (visiting.has(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n visiting.add(token);\n\n for (const dependency of registration.dependencies) {\n const found = this.#lookup(dependency);\n\n if (!found) throw new ConduitProviderNotFoundError(dependency, this.name);\n\n if (found.registration.kind === 'factory') {\n if (registration.lifetime === 'singleton' && found.registration.lifetime === 'transient') {\n throw new ConduitError(\n `Singleton \"${token.description ?? 'anonymous'}\" cannot depend on a transient factory`,\n );\n }\n\n found.owner.#validatePath(dependency, found.registration, visiting, [...path, token]);\n }\n }\n\n visiting.delete(token);\n }\n\n async #resolve<T>(token: Token<T>, path: Token<unknown>[]): Promise<T> {\n if (path.includes(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n const found = this.#lookup(token);\n\n if (!found) throw new ConduitProviderNotFoundError(token, this.name);\n\n const registration = found.registration;\n\n if (registration.kind === 'value') return registration.value as T;\n\n if (registration.lifetime === 'transient') {\n return this.#track(this.#create(registration, this, [...path, token])) as Promise<T>;\n }\n\n const owner = found.owner;\n const existing = owner.#cache.get(registration);\n\n if (existing?.resolved) return existing.value as T;\n if (existing) return existing.promise as Promise<T>;\n\n const entry = { promise: Promise.resolve(), resolved: false } as CacheEntry;\n const creation = owner.#create(registration, owner, [...path, token]).then(\n (value) => {\n entry.resolved = true;\n entry.value = value;\n return value;\n },\n (error) => {\n if (owner.#cache.get(registration) === entry) owner.#cache.delete(registration);\n throw error;\n },\n );\n\n entry.promise = owner.#track(creation);\n owner.#cache.set(registration, entry);\n\n return entry.promise as Promise<T>;\n }\n\n #track<T>(promise: Promise<T>): Promise<T> {\n this.#inFlight.add(promise);\n void promise.then(\n () => this.#inFlight.delete(promise),\n () => this.#inFlight.delete(promise),\n );\n return promise;\n }\n\n async #create(registration: FactoryRegistration, owner: ContainerImpl, path: Token<unknown>[]): Promise<unknown> {\n const value = await Promise.all(\n registration.dependencies.map((dependency) => owner.#resolve(dependency, path)),\n ).then((dependencies) => registration.factory(...dependencies));\n\n if (owner.#lifecycle !== 'active') {\n if (registration.dispose) {\n try {\n await registration.dispose(value);\n } catch (error) {\n owner.#cleanupFailures.push(error);\n }\n }\n\n throw new ConduitDisposedError(owner.name);\n }\n\n if (registration.dispose) owner.#owned.push({ dispose: registration.dispose, value });\n\n return value;\n }\n}\n\nexport function createContainer(providers: readonly AnyProvider[], options?: { readonly name?: string }): Container {\n return new ContainerImpl(undefined, providers, { name: options?.name });\n}\n"],"mappings":"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"}
|
package/dist/conduit.iife.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var Conduit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function
|
|
1
|
+
var Conduit=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function tokenName(e){return e.description??`anonymous`}var ConduitError=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},ConduitCircularDependencyError=class extends ConduitError{cycle;constructor(e){super(`Circular dependency detected: ${e.map(tokenName).join(` -> `)}`),this.cycle=Object.freeze([...e])}},ConduitProviderNotFoundError=class extends ConduitError{containerName;token;constructor(e,t){super(`No provider registered for token: ${tokenName(e)} (in container '${t}')`),this.containerName=t,this.token=e}},ConduitDuplicateRegistrationError=class extends ConduitError{token;constructor(e){super(`Token "${tokenName(e)}" is already registered.`),this.token=e}},ConduitDisposedError=class extends ConduitError{containerName;constructor(e){super(`Cannot use disposed container '${e}'.`),this.containerName=e}},ConduitDisposeError=class extends ConduitError{errors;constructor(e){super(`Container disposal failed with ${e.length} cleanup error${e.length===1?``:`s`}.`),this.errors=Object.freeze([...e])}};function token(e){return Symbol(e)}var t=token(`Conduit disposal signal`);function valueProvider(e,t,n={}){return Object.freeze({...n,token:e,value:t})}function factoryProvider(e,t,n,r={}){return Object.freeze({...r,dependencies:Object.freeze([...t]),factory:n,token:e})}var n=class ContainerImpl{#e=new Map;#t=new Set;#n=[];#r=new AbortController;#i=new Set;#a=`active`;#o;#s=[];#c;#l=new Map;name;constructor(e,n,r){this.#c=e,e&&e.#t.add(this),this.name=r.name??(e?`${e.name}:child`:`root`),this.#l.set(t,{kind:`value`,value:this.disposalSignal});try{this.#p(n),this.#_(),this.#m()}catch(t){throw e&&e.#t.delete(this),this.#l.clear(),t}}get disposalSignal(){return this.#r.signal}get disposed(){return this.#a===`disposed`}has(e){return this.#d(),this.#h(e)!==void 0}async resolve(e){if(this.#d(),typeof e==`symbol`)return this.#y(e,[]);if(typeof e!=`object`||!e||Array.isArray(e))throw new ConduitError(`resolve() requires a token or service map`);let t=Object.keys(e),n=await Promise.all(t.map(t=>this.#y(e[t],[]))),r={};return t.forEach((e,t)=>{Object.defineProperty(r,e,{configurable:!0,enumerable:!0,value:n[t],writable:!0})}),r}createScope(e={}){return this.#d(),new ContainerImpl(this,e.providers??[],{name:e.name})}dispose(){return this.#a===`disposed`?Promise.resolve():this.#o?this.#o:(this.#a=`disposing`,this.#r.abort(),this.#o=this.#u(),this.#o)}async[Symbol.asyncDispose](){await this.dispose()}async#u(){let e=await Promise.allSettled([...this.#t].map(e=>e.dispose()));await Promise.allSettled([...this.#i]);let t=[...this.#n,...e.flatMap(e=>e.status===`rejected`?e.reason instanceof ConduitDisposeError?e.reason.errors:[e.reason]:[])];for(let e of[...this.#s].reverse())if(e.dispose)try{await e.dispose(e.value)}catch(e){t.push(e)}if(this.#e.clear(),this.#t.clear(),this.#n=[],this.#s=[],this.#l.clear(),this.#c&&this.#c.#t.delete(this),this.#a=`disposed`,t.length)throw new ConduitDisposeError(t)}#d(){if(this.#a!==`active`)throw new ConduitDisposedError(this.name)}#f(e){if(this.#l.has(e))throw new ConduitDuplicateRegistrationError(e)}#p(e){if(!Array.isArray(e))throw new ConduitError(`Container providers must be an array`);for(let t of e){if(typeof t!=`object`||!t||Array.isArray(t))throw new ConduitError(`Each provider must be an object`);let e=t,n=Object.hasOwn(e,`dependencies`),r=Object.hasOwn(e,`factory`),i=Object.hasOwn(e,`value`);if(typeof e.token!=`symbol`)throw new ConduitError(`Each provider requires a token`);if(e.dispose!==void 0&&typeof e.dispose!=`function`)throw new ConduitError(`Provider "${e.token.description??`anonymous`}" has an invalid disposer`);if(i===r||i===n||i&&Object.hasOwn(e,`lifetime`))throw new ConduitError(`Provider "${e.token.description??`anonymous`}" must define exactly one value or factory`);if(this.#f(e.token),r){let t=e;if(!Array.isArray(t.dependencies)||t.dependencies.some(e=>typeof e!=`symbol`))throw new ConduitError(`Factory provider "${e.token.description??`anonymous`}" has invalid dependencies`);if(typeof t.factory!=`function`)throw new ConduitError(`Factory provider "${e.token.description??`anonymous`}" requires a factory`);if(t.lifetime!==void 0&&t.lifetime!==`singleton`&&t.lifetime!==`transient`)throw new ConduitError(`Factory provider "${e.token.description??`anonymous`}" has an invalid lifetime`);this.#l.set(e.token,{dependencies:Object.freeze([...t.dependencies]),dispose:t.dispose,factory:t.factory,kind:`factory`,lifetime:t.lifetime??`singleton`})}else{let t=e;this.#l.set(e.token,{dispose:t.dispose,kind:`value`,value:t.value})}}}#m(){for(let e of this.#l.values())e.kind===`value`&&e.dispose&&this.#s.push({dispose:e.dispose,value:e.value})}#h(e){let t=this.#l.get(e);if(t)return{owner:this,registration:t};if(this.#c)return this.#c.#h(e)}#g(){let e=this.#c?this.#c.#g():[],t=[...this.#l].flatMap(([e,t])=>t.kind===`factory`?[{owner:this,registration:t,token:e}]:[]);return[...e,...t]}#_(){for(let{owner:e,registration:t,token:n}of this.#g())e.#v(n,t,new Set,[])}#v(e,t,n,r){if(n.has(e))throw new ConduitCircularDependencyError([...r,e]);n.add(e);for(let i of t.dependencies){let a=this.#h(i);if(!a)throw new ConduitProviderNotFoundError(i,this.name);if(a.registration.kind===`factory`){if(t.lifetime===`singleton`&&a.registration.lifetime===`transient`)throw new ConduitError(`Singleton "${e.description??`anonymous`}" cannot depend on a transient factory`);a.owner.#v(i,a.registration,n,[...r,e])}}n.delete(e)}async#y(e,t){if(t.includes(e))throw new ConduitCircularDependencyError([...t,e]);let n=this.#h(e);if(!n)throw new ConduitProviderNotFoundError(e,this.name);let r=n.registration;if(r.kind===`value`)return r.value;if(r.lifetime===`transient`)return this.#b(this.#x(r,this,[...t,e]));let i=n.owner,a=i.#e.get(r);if(a?.resolved)return a.value;if(a)return a.promise;let o={promise:Promise.resolve(),resolved:!1},s=i.#x(r,i,[...t,e]).then(e=>(o.resolved=!0,o.value=e,e),e=>{throw i.#e.get(r)===o&&i.#e.delete(r),e});return o.promise=i.#b(s),i.#e.set(r,o),o.promise}#b(e){return this.#i.add(e),e.then(()=>this.#i.delete(e),()=>this.#i.delete(e)),e}async#x(e,t,n){let r=await Promise.all(e.dependencies.map(e=>t.#y(e,n))).then(t=>e.factory(...t));if(t.#a!==`active`){if(e.dispose)try{await e.dispose(r)}catch(e){t.#n.push(e)}throw new ConduitDisposedError(t.name)}return e.dispose&&t.#s.push({dispose:e.dispose,value:r}),r}};function createContainer(e,t){return new n(void 0,e,{name:t?.name})}return e.ConduitCircularDependencyError=ConduitCircularDependencyError,e.ConduitDisposeError=ConduitDisposeError,e.ConduitDisposedError=ConduitDisposedError,e.ConduitDuplicateRegistrationError=ConduitDuplicateRegistrationError,e.ConduitError=ConduitError,e.ConduitProviderNotFoundError=ConduitProviderNotFoundError,e.createContainer=createContainer,e.disposalSignalToken=t,e.factoryProvider=factoryProvider,e.token=token,e.valueProvider=valueProvider,e})({});
|
|
2
2
|
//# sourceMappingURL=conduit.iife.js.map
|
package/dist/conduit.iife.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conduit.iife.js","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/container.ts"],"sourcesContent":["import type { ScopeToken, Token } from './types.js';\n\nexport function tokenName(token: Token<unknown>): string {\n return token.description ?? 'anonymous';\n}\n\nexport class ConduitError extends Error {\n protected static readonly errorName: string = 'ConduitError';\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = (new.target as typeof ConduitError).errorName;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class ConduitCircularDependencyError extends ConduitError {\n protected static override readonly errorName = 'ConduitCircularDependencyError';\n readonly cycle: readonly Token<unknown>[];\n\n constructor(cycle: readonly Token<unknown>[]) {\n super(`Circular dependency detected: ${cycle.map(tokenName).join(' -> ')}`);\n this.cycle = Object.freeze([...cycle]);\n }\n}\n\nexport class ConduitProviderNotFoundError extends ConduitError {\n protected static override readonly errorName = 'ConduitProviderNotFoundError';\n readonly containerName: string;\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>, containerName: string) {\n super(`No provider registered for token: ${tokenName(token)} (in container '${containerName}')`);\n this.containerName = containerName;\n this.token = token;\n }\n}\n\nexport class ConduitDuplicateRegistrationError extends ConduitError {\n protected static override readonly errorName = 'ConduitDuplicateRegistrationError';\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>) {\n super(`Token \"${tokenName(token)}\" is already registered.`);\n this.token = token;\n }\n}\n\nexport class ConduitScopedResolutionError extends ConduitError {\n protected static override readonly errorName = 'ConduitScopedResolutionError';\n readonly requiredScope: ScopeToken;\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>, requiredScope: ScopeToken) {\n super(`Token \"${tokenName(token)}\" requires scope \"${requiredScope.description ?? 'anonymous'}\".`);\n this.requiredScope = requiredScope;\n this.token = token;\n }\n}\n\nexport class ConduitDisposedError extends ConduitError {\n protected static override readonly errorName = 'ConduitDisposedError';\n readonly containerName: string;\n\n constructor(containerName: string) {\n super(`Cannot use disposed container '${containerName}'.`);\n this.containerName = containerName;\n }\n}\n\nexport class ConduitDisposeError extends ConduitError {\n protected static override readonly errorName = 'ConduitDisposeError';\n readonly errors: readonly unknown[];\n\n constructor(errors: readonly unknown[]) {\n super(`Container disposal failed with ${errors.length} cleanup error${errors.length === 1 ? '' : 's'}.`);\n this.errors = Object.freeze([...errors]);\n }\n}\n","declare const tokenBrand: unique symbol;\ndeclare const scopeBrand: unique symbol;\n\nexport type Token<T = unknown> = symbol & { readonly [tokenBrand]: T };\nexport type ScopeToken = symbol & { readonly [scopeBrand]: true };\n\nexport function token<T>(description: string): Token<T> {\n return Symbol(description) as Token<T>;\n}\n\nexport function scope(name: string): ScopeToken {\n return Symbol(name) as ScopeToken;\n}\n\nexport const disposalSignalToken = token<AbortSignal>('Conduit disposal signal');\n\n/** Singleton results are cached on the registering container; transient results belong to the requesting container; a `ScopeToken` caches on the matching child scope. */\nexport type Lifetime = 'singleton' | 'transient' | ScopeToken;\n\nexport type InferTokens<T extends readonly Token<unknown>[]> = {\n [K in keyof T]: T[K] extends Token<infer Value> ? Value : never;\n};\n\nexport type ValueOptions<T> = Readonly<{\n dispose?: (value: T) => Promise<void> | void;\n}>;\n\nexport type FactoryOptions<T> = Readonly<{\n dispose?: (value: T) => Promise<void> | void;\n lifetime?: Lifetime;\n}>;\n\nexport interface ValueProvider<T> {\n readonly dispose?: (value: T) => Promise<void> | void;\n readonly token: Token<T>;\n readonly value: T;\n}\n\nexport interface FactoryProvider<T, Dependencies extends readonly Token<unknown>[] = readonly Token<unknown>[]> {\n readonly dependencies: Dependencies;\n readonly dispose?: (value: T) => Promise<void> | void;\n readonly factory: (...values: InferTokens<Dependencies>) => Promise<T> | T;\n readonly lifetime?: Lifetime;\n readonly token: Token<T>;\n}\n\nexport type Provider<T = unknown, Dependencies extends readonly Token<unknown>[] = readonly Token<unknown>[]> =\n | ValueProvider<T>\n | FactoryProvider<T, Dependencies>;\n\nexport function valueProvider<T>(token: Token<T>, value: NoInfer<T>, options: ValueOptions<T> = {}): ValueProvider<T> {\n return Object.freeze({ ...options, token, value });\n}\n\nexport function factoryProvider<T, const Dependencies extends readonly Token<unknown>[]>(\n token: Token<T>,\n dependencies: Dependencies,\n factory: (...values: InferTokens<Dependencies>) => Promise<T> | T,\n options: FactoryOptions<T> = {},\n): FactoryProvider<T, Dependencies> {\n return Object.freeze({\n ...options,\n dependencies: Object.freeze([...dependencies]) as unknown as Dependencies,\n factory,\n token,\n });\n}\n\n/** Map of service name to dependency token, passed to `container.resolve()` at a composition root. */\nexport type ServiceMap = { readonly [key: string]: Token<unknown> };\n\nexport type InferServices<M extends ServiceMap> = {\n readonly [K in keyof M]: M[K] extends Token<infer Value> ? Value : never;\n};\n\nexport interface Container {\n createScope(\n scope?: ScopeToken,\n options?: { readonly name?: string; readonly providers?: readonly Provider<any, any>[] },\n ): Container;\n readonly disposalSignal: AbortSignal;\n dispose(): Promise<void>;\n readonly disposed: boolean;\n has<T>(token: Token<T>): boolean;\n readonly name: string;\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n","import {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n ConduitScopedResolutionError,\n} from './errors.js';\nimport type {\n Container,\n FactoryProvider,\n InferServices,\n Lifetime,\n Provider,\n ScopeToken,\n ServiceMap,\n Token,\n ValueProvider,\n} from './types.js';\nimport { disposalSignalToken } from './types.js';\n\ntype Disposer = (value: unknown) => Promise<void> | void;\n\ntype ValueRegistration<T> = Readonly<{\n dispose?: Disposer;\n kind: 'value';\n value: T;\n}>;\n\ntype FactoryRegistration<T = unknown> = Readonly<{\n factory: (...values: unknown[]) => Promise<T> | T;\n dependencies: readonly Token<unknown>[];\n dispose?: Disposer;\n kind: 'factory';\n lifetime: Lifetime;\n}>;\n\ntype Registration<T = unknown> = FactoryRegistration<T> | ValueRegistration<T>;\ntype OwnedResource = Readonly<{ dispose?: Disposer; value: unknown }>;\ntype CacheEntry = { promise: Promise<unknown>; resolved: boolean; value?: unknown };\ntype Lifecycle = 'active' | 'disposed' | 'disposing';\n\nclass ContainerImpl implements Container {\n #cache = new Map<FactoryRegistration<unknown>, CacheEntry>();\n #children = new Set<ContainerImpl>();\n #cleanupFailures: unknown[] = [];\n #disposalController = new AbortController();\n #inFlight = new Set<Promise<unknown>>();\n #lifecycle: Lifecycle = 'active';\n #disposePromise?: Promise<void>;\n #owned: OwnedResource[] = [];\n #parent?: ContainerImpl;\n #registry = new Map<Token<unknown>, Registration<unknown>>();\n #scope?: ScopeToken;\n readonly name: string;\n\n constructor(\n parent: ContainerImpl | undefined,\n providers: readonly Provider<any, any>[],\n options: { name?: string; scope?: ScopeToken },\n ) {\n this.#parent = parent;\n this.#scope = options.scope;\n\n if (parent) parent.#children.add(this);\n\n this.name = options.name ?? (parent ? `${parent.name}:${options.scope?.description ?? 'child'}` : 'root');\n this.#registry.set(disposalSignalToken, { kind: 'value', value: this.disposalSignal });\n\n try {\n this.#registerProviders(providers);\n this.#validateGraph();\n this.#claimValues();\n } catch (error) {\n if (parent) parent.#children.delete(this);\n this.#registry.clear();\n throw error;\n }\n }\n\n get disposalSignal(): AbortSignal {\n return this.#disposalController.signal;\n }\n\n get disposed(): boolean {\n return this.#lifecycle === 'disposed';\n }\n\n has<T>(token: Token<T>): boolean {\n this.#assertActive();\n\n return this.#lookup(token) !== undefined;\n }\n\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n async resolve<T, M extends ServiceMap>(input: Token<T> | M): Promise<InferServices<M> | T> {\n this.#assertActive();\n\n if (typeof input === 'symbol') return this.#resolve(input, []);\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw new ConduitError('resolve() requires a token or service map');\n }\n\n const entries = Object.keys(input) as (keyof M & string)[];\n const values = await Promise.all(entries.map((key) => this.#resolve(input[key] as Token<unknown>, [])));\n const services = {} as InferServices<M>;\n\n entries.forEach((key, index) => {\n Object.defineProperty(services, key, {\n configurable: true,\n enumerable: true,\n value: values[index],\n writable: true,\n });\n });\n\n return services;\n }\n\n createScope(\n scope?: ScopeToken,\n options?: { readonly name?: string; readonly providers?: readonly Provider<any, any>[] },\n ): Container {\n this.#assertActive();\n\n return new ContainerImpl(this, options?.providers ?? [], { name: options?.name, scope });\n }\n\n dispose(): Promise<void> {\n if (this.#lifecycle === 'disposed') return Promise.resolve();\n\n if (this.#disposePromise) return this.#disposePromise;\n\n this.#lifecycle = 'disposing';\n this.#disposalController.abort();\n this.#disposePromise = this.#finishDisposal();\n\n return this.#disposePromise;\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.dispose();\n }\n\n async #finishDisposal(): Promise<void> {\n const childOutcomes = await Promise.allSettled([...this.#children].map((child) => child.dispose()));\n\n await Promise.allSettled([...this.#inFlight]);\n\n const failures = [\n ...this.#cleanupFailures,\n ...childOutcomes.flatMap((outcome) => {\n if (outcome.status !== 'rejected') return [];\n\n return outcome.reason instanceof ConduitDisposeError ? outcome.reason.errors : [outcome.reason];\n }),\n ];\n\n for (const resource of [...this.#owned].reverse()) {\n if (!resource.dispose) continue;\n\n try {\n await resource.dispose(resource.value);\n } catch (error) {\n failures.push(error);\n }\n }\n\n this.#cache.clear();\n this.#children.clear();\n this.#cleanupFailures = [];\n this.#owned = [];\n this.#registry.clear();\n\n if (this.#parent) this.#parent.#children.delete(this);\n\n this.#lifecycle = 'disposed';\n\n if (failures.length) throw new ConduitDisposeError(failures);\n }\n\n #assertActive(): void {\n if (this.#lifecycle !== 'active') throw new ConduitDisposedError(this.name);\n }\n\n #assertUnregistered(token: Token<unknown>): void {\n if (this.#registry.has(token)) throw new ConduitDuplicateRegistrationError(token);\n }\n\n #registerProviders(providers: readonly Provider<any, any>[]): void {\n if (!Array.isArray(providers)) throw new ConduitError('Container providers must be an array');\n\n for (const input of providers) {\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw new ConduitError('Each provider must be an object');\n }\n\n const provider = input as Provider;\n const hasDependencies = Object.hasOwn(provider, 'dependencies');\n const hasFactory = Object.hasOwn(provider, 'factory');\n const hasValue = Object.hasOwn(provider, 'value');\n\n if (typeof provider.token !== 'symbol') throw new ConduitError('Each provider requires a token');\n if (provider.dispose !== undefined && typeof provider.dispose !== 'function') {\n throw new ConduitError(`Provider \"${provider.token.description ?? 'anonymous'}\" has an invalid disposer`);\n }\n if (\n hasValue === hasFactory ||\n hasValue === hasDependencies ||\n (hasValue && Object.hasOwn(provider, 'lifetime'))\n ) {\n throw new ConduitError(\n `Provider \"${provider.token.description ?? 'anonymous'}\" must define exactly one value or factory`,\n );\n }\n\n this.#assertUnregistered(provider.token);\n\n if (hasFactory) {\n const factory = provider as FactoryProvider<unknown>;\n\n if (\n !Array.isArray(factory.dependencies) ||\n factory.dependencies.some((dependency) => typeof dependency !== 'symbol')\n ) {\n throw new ConduitError(\n `Factory provider \"${provider.token.description ?? 'anonymous'}\" has invalid dependencies`,\n );\n }\n if (typeof factory.factory !== 'function') {\n throw new ConduitError(`Factory provider \"${provider.token.description ?? 'anonymous'}\" requires a factory`);\n }\n if (\n factory.lifetime !== undefined &&\n factory.lifetime !== 'singleton' &&\n factory.lifetime !== 'transient' &&\n typeof factory.lifetime !== 'symbol'\n ) {\n throw new ConduitError(\n `Factory provider \"${provider.token.description ?? 'anonymous'}\" has an invalid lifetime`,\n );\n }\n\n this.#registry.set(provider.token, {\n dependencies: Object.freeze([...factory.dependencies]),\n dispose: factory.dispose as Disposer | undefined,\n factory: factory.factory as (...values: unknown[]) => Promise<unknown> | unknown,\n kind: 'factory',\n lifetime: factory.lifetime ?? 'singleton',\n });\n } else {\n const valueProvider = provider as ValueProvider<unknown>;\n\n this.#registry.set(provider.token, {\n dispose: valueProvider.dispose as Disposer | undefined,\n kind: 'value',\n value: valueProvider.value,\n });\n }\n }\n }\n\n #claimValues(): void {\n for (const registration of this.#registry.values()) {\n if (registration.kind === 'value' && registration.dispose) {\n this.#owned.push({ dispose: registration.dispose, value: registration.value });\n }\n }\n }\n\n #lookup<T>(token: Token<T>): { owner: ContainerImpl; registration: Registration<T> } | undefined {\n const local = this.#registry.get(token) as Registration<T> | undefined;\n\n if (local) return { owner: this, registration: local };\n\n if (!this.#parent) return undefined;\n\n return this.#parent.#lookup(token);\n }\n\n #factories(): { owner: ContainerImpl; registration: FactoryRegistration; token: Token<unknown> }[] {\n const parentFactories = this.#parent ? this.#parent.#factories() : [];\n const localFactories = [...this.#registry].flatMap(([token, registration]) =>\n registration.kind === 'factory' ? [{ owner: this, registration, token }] : [],\n );\n\n return [...parentFactories, ...localFactories];\n }\n\n #validateGraph(): void {\n for (const { owner, registration, token } of this.#factories()) {\n owner.#validatePath(token, registration, new Set(), []);\n }\n }\n\n #validatePath(\n token: Token<unknown>,\n registration: FactoryRegistration,\n visiting: Set<Token<unknown>>,\n path: Token<unknown>[],\n ): void {\n if (visiting.has(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n visiting.add(token);\n\n for (const dependency of registration.dependencies) {\n const found = this.#lookup(dependency);\n\n if (!found) throw new ConduitProviderNotFoundError(dependency, this.name);\n\n if (found.registration.kind === 'factory') {\n if (registration.lifetime === 'singleton' && found.registration.lifetime === 'transient') {\n throw new ConduitError(\n `Singleton \"${token.description ?? 'anonymous'}\" cannot depend on a transient factory`,\n );\n }\n if (registration.lifetime === 'singleton' && typeof found.registration.lifetime === 'symbol') {\n throw new ConduitScopedResolutionError(token, found.registration.lifetime);\n }\n if (\n typeof registration.lifetime === 'symbol' &&\n typeof found.registration.lifetime === 'symbol' &&\n registration.lifetime !== found.registration.lifetime\n ) {\n throw new ConduitScopedResolutionError(token, found.registration.lifetime);\n }\n\n found.owner.#validatePath(dependency, found.registration, visiting, [...path, token]);\n }\n }\n\n visiting.delete(token);\n }\n\n async #resolve<T>(token: Token<T>, path: Token<unknown>[]): Promise<T> {\n if (path.includes(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n const found = this.#lookup(token);\n\n if (!found) throw new ConduitProviderNotFoundError(token, this.name);\n\n const registration = found.registration;\n\n if (registration.kind === 'value') return registration.value as T;\n\n const owner = this.#ownerFor(found.owner, registration, token);\n\n if (registration.lifetime === 'transient') {\n return owner.#track(owner.#create(registration, owner, [...path, token])) as Promise<T>;\n }\n\n const existing = owner.#cache.get(registration);\n\n if (existing?.resolved) return existing.value as T;\n if (existing) return existing.promise as Promise<T>;\n\n const entry = { promise: Promise.resolve(), resolved: false } as CacheEntry;\n const creation = owner.#create(registration, owner, [...path, token]).then(\n (value) => {\n entry.resolved = true;\n entry.value = value;\n return value;\n },\n (error) => {\n if (owner.#cache.get(registration) === entry) owner.#cache.delete(registration);\n throw error;\n },\n );\n\n entry.promise = owner.#track(creation);\n owner.#cache.set(registration, entry);\n\n return entry.promise as Promise<T>;\n }\n\n #ownerFor(owner: ContainerImpl, registration: FactoryRegistration, token: Token<unknown>): ContainerImpl {\n if (registration.lifetime === 'singleton') return owner;\n if (registration.lifetime === 'transient') return this;\n\n const scopeOwner = this.#scopeOwner(registration.lifetime as ScopeToken);\n\n if (!scopeOwner) throw new ConduitScopedResolutionError(token, registration.lifetime as ScopeToken);\n\n return scopeOwner;\n }\n\n #scopeOwner(scope: ScopeToken): ContainerImpl | undefined {\n if (this.#scope === scope) return this;\n\n return this.#parent ? this.#parent.#scopeOwner(scope) : undefined;\n }\n\n #track<T>(promise: Promise<T>): Promise<T> {\n this.#inFlight.add(promise);\n void promise.then(\n () => this.#inFlight.delete(promise),\n () => this.#inFlight.delete(promise),\n );\n return promise;\n }\n\n async #create(registration: FactoryRegistration, owner: ContainerImpl, path: Token<unknown>[]): Promise<unknown> {\n const value = await Promise.all(\n registration.dependencies.map((dependency) => owner.#resolve(dependency, path)),\n ).then((dependencies) => registration.factory(...dependencies));\n\n if (owner.#lifecycle !== 'active') {\n if (registration.dispose) {\n try {\n await registration.dispose(value);\n } catch (error) {\n owner.#cleanupFailures.push(error);\n }\n }\n\n throw new ConduitDisposedError(owner.name);\n }\n\n if (registration.dispose) owner.#owned.push({ dispose: registration.dispose, value });\n\n return value;\n }\n}\n\nexport function createContainer(\n providers: readonly Provider<any, any>[],\n options?: { readonly name?: string },\n): Container {\n return new ContainerImpl(undefined, providers, { name: options?.name });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"conduit.iife.js","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/container.ts"],"sourcesContent":["import type { Token } from './types.js';\n\nfunction tokenName(token: Token<unknown>): string {\n return token.description ?? 'anonymous';\n}\n\nexport class ConduitError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class ConduitCircularDependencyError extends ConduitError {\n readonly cycle: readonly Token<unknown>[];\n\n constructor(cycle: readonly Token<unknown>[]) {\n super(`Circular dependency detected: ${cycle.map(tokenName).join(' -> ')}`);\n this.cycle = Object.freeze([...cycle]);\n }\n}\n\nexport class ConduitProviderNotFoundError extends ConduitError {\n readonly containerName: string;\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>, containerName: string) {\n super(`No provider registered for token: ${tokenName(token)} (in container '${containerName}')`);\n this.containerName = containerName;\n this.token = token;\n }\n}\n\nexport class ConduitDuplicateRegistrationError extends ConduitError {\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>) {\n super(`Token \"${tokenName(token)}\" is already registered.`);\n this.token = token;\n }\n}\n\nexport class ConduitDisposedError extends ConduitError {\n readonly containerName: string;\n\n constructor(containerName: string) {\n super(`Cannot use disposed container '${containerName}'.`);\n this.containerName = containerName;\n }\n}\n\nexport class ConduitDisposeError extends ConduitError {\n readonly errors: readonly unknown[];\n\n constructor(errors: readonly unknown[]) {\n super(`Container disposal failed with ${errors.length} cleanup error${errors.length === 1 ? '' : 's'}.`);\n this.errors = Object.freeze([...errors]);\n }\n}\n","declare const tokenBrand: unique symbol;\n\nexport type Token<T = unknown> = symbol & { readonly [tokenBrand]: T };\n\nexport function token<T>(description: string): Token<T> {\n return Symbol(description) as Token<T>;\n}\n\nexport const disposalSignalToken = token<AbortSignal>('Conduit disposal signal');\n\n/** Singleton results are cached on the registering container; transient results belong to the requesting container. */\nexport type Lifetime = 'singleton' | 'transient';\n\nexport type InferTokens<T extends readonly Token<unknown>[]> = {\n [K in keyof T]: T[K] extends Token<infer Value> ? Value : never;\n};\n\nexport type ValueOptions<T> = Readonly<{\n dispose?: (value: T) => Promise<void> | void;\n}>;\n\nexport type FactoryOptions<T> = Readonly<{\n dispose?: (value: T) => Promise<void> | void;\n lifetime?: Lifetime;\n}>;\n\nexport interface ValueProvider<T> {\n readonly dispose?: (value: T) => Promise<void> | void;\n readonly token: Token<T>;\n readonly value: T;\n}\n\nexport interface FactoryProvider<T, Dependencies extends readonly Token<unknown>[] = readonly Token<unknown>[]> {\n readonly dependencies: Dependencies;\n readonly dispose?: (value: T) => Promise<void> | void;\n readonly factory: (...values: InferTokens<Dependencies>) => Promise<T> | T;\n readonly lifetime?: Lifetime;\n readonly token: Token<T>;\n}\n\nexport type Provider<T = unknown, Dependencies extends readonly Token<unknown>[] = readonly Token<unknown>[]> =\n | ValueProvider<T>\n | FactoryProvider<T, Dependencies>;\n\n/**\n * Type-erased provider for the heterogeneous lists accepted by\n * `createContainer()` and `createScope()`. Providers are invariant in their\n * value type, so erasure needs `any` at this one boundary; registration\n * re-validates every provider at runtime.\n */\nexport type AnyProvider = Provider<any, any>;\n\nexport function valueProvider<T>(token: Token<T>, value: NoInfer<T>, options: ValueOptions<T> = {}): ValueProvider<T> {\n return Object.freeze({ ...options, token, value });\n}\n\nexport function factoryProvider<T, const Dependencies extends readonly Token<unknown>[]>(\n token: Token<T>,\n dependencies: Dependencies,\n factory: (...values: InferTokens<Dependencies>) => Promise<T> | T,\n options: FactoryOptions<T> = {},\n): FactoryProvider<T, Dependencies> {\n return Object.freeze({\n ...options,\n dependencies: Object.freeze([...dependencies]) as unknown as Dependencies,\n factory,\n token,\n });\n}\n\n/** Map of service name to dependency token, passed to `container.resolve()` at a composition root. */\nexport type ServiceMap = { readonly [key: string]: Token<unknown> };\n\nexport type InferServices<M extends ServiceMap> = {\n readonly [K in keyof M]: M[K] extends Token<infer Value> ? Value : never;\n};\n\nexport type CreateScopeOptions = Readonly<{\n name?: string;\n providers?: readonly AnyProvider[];\n}>;\n\nexport interface Container {\n /**\n * Create a child container that inherits parent registrations. Providers\n * registered on the child are local to it, which is how request-scoped\n * values are spelled: one child per request.\n */\n createScope(options?: CreateScopeOptions): Container;\n readonly disposalSignal: AbortSignal;\n dispose(): Promise<void>;\n readonly disposed: boolean;\n has<T>(token: Token<T>): boolean;\n readonly name: string;\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n","import {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n} from './errors.js';\nimport type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryProvider,\n InferServices,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueProvider,\n} from './types.js';\nimport { disposalSignalToken } from './types.js';\n\ntype Disposer = (value: unknown) => Promise<void> | void;\n\ntype ValueRegistration<T> = Readonly<{\n dispose?: Disposer;\n kind: 'value';\n value: T;\n}>;\n\ntype FactoryRegistration<T = unknown> = Readonly<{\n factory: (...values: unknown[]) => Promise<T> | T;\n dependencies: readonly Token<unknown>[];\n dispose?: Disposer;\n kind: 'factory';\n lifetime: Lifetime;\n}>;\n\ntype Registration<T = unknown> = FactoryRegistration<T> | ValueRegistration<T>;\ntype OwnedResource = Readonly<{ dispose?: Disposer; value: unknown }>;\ntype CacheEntry = { promise: Promise<unknown>; resolved: boolean; value?: unknown };\ntype Lifecycle = 'active' | 'disposed' | 'disposing';\n\nclass ContainerImpl implements Container {\n #cache = new Map<FactoryRegistration<unknown>, CacheEntry>();\n #children = new Set<ContainerImpl>();\n #cleanupFailures: unknown[] = [];\n #disposalController = new AbortController();\n #inFlight = new Set<Promise<unknown>>();\n #lifecycle: Lifecycle = 'active';\n #disposePromise?: Promise<void>;\n #owned: OwnedResource[] = [];\n #parent?: ContainerImpl;\n #registry = new Map<Token<unknown>, Registration<unknown>>();\n readonly name: string;\n\n constructor(parent: ContainerImpl | undefined, providers: readonly AnyProvider[], options: CreateScopeOptions) {\n this.#parent = parent;\n\n if (parent) parent.#children.add(this);\n\n this.name = options.name ?? (parent ? `${parent.name}:child` : 'root');\n this.#registry.set(disposalSignalToken, { kind: 'value', value: this.disposalSignal });\n\n try {\n this.#registerProviders(providers);\n this.#validateGraph();\n this.#claimValues();\n } catch (error) {\n if (parent) parent.#children.delete(this);\n this.#registry.clear();\n throw error;\n }\n }\n\n get disposalSignal(): AbortSignal {\n return this.#disposalController.signal;\n }\n\n get disposed(): boolean {\n return this.#lifecycle === 'disposed';\n }\n\n has<T>(token: Token<T>): boolean {\n this.#assertActive();\n\n return this.#lookup(token) !== undefined;\n }\n\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n async resolve<T, M extends ServiceMap>(input: Token<T> | M): Promise<InferServices<M> | T> {\n this.#assertActive();\n\n if (typeof input === 'symbol') return this.#resolve(input, []);\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw new ConduitError('resolve() requires a token or service map');\n }\n\n const entries = Object.keys(input) as (keyof M & string)[];\n const values = await Promise.all(entries.map((key) => this.#resolve(input[key] as Token<unknown>, [])));\n const services = {} as InferServices<M>;\n\n entries.forEach((key, index) => {\n Object.defineProperty(services, key, {\n configurable: true,\n enumerable: true,\n value: values[index],\n writable: true,\n });\n });\n\n return services;\n }\n\n createScope(options: CreateScopeOptions = {}): Container {\n this.#assertActive();\n\n return new ContainerImpl(this, options.providers ?? [], { name: options.name });\n }\n\n dispose(): Promise<void> {\n if (this.#lifecycle === 'disposed') return Promise.resolve();\n\n if (this.#disposePromise) return this.#disposePromise;\n\n this.#lifecycle = 'disposing';\n this.#disposalController.abort();\n this.#disposePromise = this.#finishDisposal();\n\n return this.#disposePromise;\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.dispose();\n }\n\n async #finishDisposal(): Promise<void> {\n const childOutcomes = await Promise.allSettled([...this.#children].map((child) => child.dispose()));\n\n await Promise.allSettled([...this.#inFlight]);\n\n const failures = [\n ...this.#cleanupFailures,\n ...childOutcomes.flatMap((outcome) => {\n if (outcome.status !== 'rejected') return [];\n\n return outcome.reason instanceof ConduitDisposeError ? outcome.reason.errors : [outcome.reason];\n }),\n ];\n\n for (const resource of [...this.#owned].reverse()) {\n if (!resource.dispose) continue;\n\n try {\n await resource.dispose(resource.value);\n } catch (error) {\n failures.push(error);\n }\n }\n\n this.#cache.clear();\n this.#children.clear();\n this.#cleanupFailures = [];\n this.#owned = [];\n this.#registry.clear();\n\n if (this.#parent) this.#parent.#children.delete(this);\n\n this.#lifecycle = 'disposed';\n\n if (failures.length) throw new ConduitDisposeError(failures);\n }\n\n #assertActive(): void {\n if (this.#lifecycle !== 'active') throw new ConduitDisposedError(this.name);\n }\n\n #assertUnregistered(token: Token<unknown>): void {\n if (this.#registry.has(token)) throw new ConduitDuplicateRegistrationError(token);\n }\n\n #registerProviders(providers: readonly AnyProvider[]): void {\n if (!Array.isArray(providers)) throw new ConduitError('Container providers must be an array');\n\n for (const input of providers) {\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw new ConduitError('Each provider must be an object');\n }\n\n const provider = input as Provider;\n const hasDependencies = Object.hasOwn(provider, 'dependencies');\n const hasFactory = Object.hasOwn(provider, 'factory');\n const hasValue = Object.hasOwn(provider, 'value');\n\n if (typeof provider.token !== 'symbol') throw new ConduitError('Each provider requires a token');\n if (provider.dispose !== undefined && typeof provider.dispose !== 'function') {\n throw new ConduitError(`Provider \"${provider.token.description ?? 'anonymous'}\" has an invalid disposer`);\n }\n if (\n hasValue === hasFactory ||\n hasValue === hasDependencies ||\n (hasValue && Object.hasOwn(provider, 'lifetime'))\n ) {\n throw new ConduitError(\n `Provider \"${provider.token.description ?? 'anonymous'}\" must define exactly one value or factory`,\n );\n }\n\n this.#assertUnregistered(provider.token);\n\n if (hasFactory) {\n const factory = provider as FactoryProvider<unknown>;\n\n if (\n !Array.isArray(factory.dependencies) ||\n factory.dependencies.some((dependency) => typeof dependency !== 'symbol')\n ) {\n throw new ConduitError(\n `Factory provider \"${provider.token.description ?? 'anonymous'}\" has invalid dependencies`,\n );\n }\n if (typeof factory.factory !== 'function') {\n throw new ConduitError(`Factory provider \"${provider.token.description ?? 'anonymous'}\" requires a factory`);\n }\n if (factory.lifetime !== undefined && factory.lifetime !== 'singleton' && factory.lifetime !== 'transient') {\n throw new ConduitError(\n `Factory provider \"${provider.token.description ?? 'anonymous'}\" has an invalid lifetime`,\n );\n }\n\n this.#registry.set(provider.token, {\n dependencies: Object.freeze([...factory.dependencies]),\n dispose: factory.dispose as Disposer | undefined,\n factory: factory.factory as (...values: unknown[]) => Promise<unknown> | unknown,\n kind: 'factory',\n lifetime: factory.lifetime ?? 'singleton',\n });\n } else {\n const valueProvider = provider as ValueProvider<unknown>;\n\n this.#registry.set(provider.token, {\n dispose: valueProvider.dispose as Disposer | undefined,\n kind: 'value',\n value: valueProvider.value,\n });\n }\n }\n }\n\n #claimValues(): void {\n for (const registration of this.#registry.values()) {\n if (registration.kind === 'value' && registration.dispose) {\n this.#owned.push({ dispose: registration.dispose, value: registration.value });\n }\n }\n }\n\n #lookup<T>(token: Token<T>): { owner: ContainerImpl; registration: Registration<T> } | undefined {\n const local = this.#registry.get(token) as Registration<T> | undefined;\n\n if (local) return { owner: this, registration: local };\n\n if (!this.#parent) return undefined;\n\n return this.#parent.#lookup(token);\n }\n\n #factories(): { owner: ContainerImpl; registration: FactoryRegistration; token: Token<unknown> }[] {\n const parentFactories = this.#parent ? this.#parent.#factories() : [];\n const localFactories = [...this.#registry].flatMap(([token, registration]) =>\n registration.kind === 'factory' ? [{ owner: this, registration, token }] : [],\n );\n\n return [...parentFactories, ...localFactories];\n }\n\n #validateGraph(): void {\n for (const { owner, registration, token } of this.#factories()) {\n owner.#validatePath(token, registration, new Set(), []);\n }\n }\n\n #validatePath(\n token: Token<unknown>,\n registration: FactoryRegistration,\n visiting: Set<Token<unknown>>,\n path: Token<unknown>[],\n ): void {\n if (visiting.has(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n visiting.add(token);\n\n for (const dependency of registration.dependencies) {\n const found = this.#lookup(dependency);\n\n if (!found) throw new ConduitProviderNotFoundError(dependency, this.name);\n\n if (found.registration.kind === 'factory') {\n if (registration.lifetime === 'singleton' && found.registration.lifetime === 'transient') {\n throw new ConduitError(\n `Singleton \"${token.description ?? 'anonymous'}\" cannot depend on a transient factory`,\n );\n }\n\n found.owner.#validatePath(dependency, found.registration, visiting, [...path, token]);\n }\n }\n\n visiting.delete(token);\n }\n\n async #resolve<T>(token: Token<T>, path: Token<unknown>[]): Promise<T> {\n if (path.includes(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n const found = this.#lookup(token);\n\n if (!found) throw new ConduitProviderNotFoundError(token, this.name);\n\n const registration = found.registration;\n\n if (registration.kind === 'value') return registration.value as T;\n\n if (registration.lifetime === 'transient') {\n return this.#track(this.#create(registration, this, [...path, token])) as Promise<T>;\n }\n\n const owner = found.owner;\n const existing = owner.#cache.get(registration);\n\n if (existing?.resolved) return existing.value as T;\n if (existing) return existing.promise as Promise<T>;\n\n const entry = { promise: Promise.resolve(), resolved: false } as CacheEntry;\n const creation = owner.#create(registration, owner, [...path, token]).then(\n (value) => {\n entry.resolved = true;\n entry.value = value;\n return value;\n },\n (error) => {\n if (owner.#cache.get(registration) === entry) owner.#cache.delete(registration);\n throw error;\n },\n );\n\n entry.promise = owner.#track(creation);\n owner.#cache.set(registration, entry);\n\n return entry.promise as Promise<T>;\n }\n\n #track<T>(promise: Promise<T>): Promise<T> {\n this.#inFlight.add(promise);\n void promise.then(\n () => this.#inFlight.delete(promise),\n () => this.#inFlight.delete(promise),\n );\n return promise;\n }\n\n async #create(registration: FactoryRegistration, owner: ContainerImpl, path: Token<unknown>[]): Promise<unknown> {\n const value = await Promise.all(\n registration.dependencies.map((dependency) => owner.#resolve(dependency, path)),\n ).then((dependencies) => registration.factory(...dependencies));\n\n if (owner.#lifecycle !== 'active') {\n if (registration.dispose) {\n try {\n await registration.dispose(value);\n } catch (error) {\n owner.#cleanupFailures.push(error);\n }\n }\n\n throw new ConduitDisposedError(owner.name);\n }\n\n if (registration.dispose) owner.#owned.push({ dispose: registration.dispose, value });\n\n return value;\n }\n}\n\nexport function createContainer(providers: readonly AnyProvider[], options?: { readonly name?: string }): Container {\n return new ContainerImpl(undefined, providers, { name: options?.name });\n}\n"],"mappings":"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"}
|
package/dist/conduit.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function
|
|
1
|
+
function tokenName(e){return e.description??`anonymous`}var ConduitError=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},ConduitCircularDependencyError=class extends ConduitError{cycle;constructor(e){super(`Circular dependency detected: ${e.map(tokenName).join(` -> `)}`),this.cycle=Object.freeze([...e])}},ConduitProviderNotFoundError=class extends ConduitError{containerName;token;constructor(e,t){super(`No provider registered for token: ${tokenName(e)} (in container '${t}')`),this.containerName=t,this.token=e}},ConduitDuplicateRegistrationError=class extends ConduitError{token;constructor(e){super(`Token "${tokenName(e)}" is already registered.`),this.token=e}},ConduitDisposedError=class extends ConduitError{containerName;constructor(e){super(`Cannot use disposed container '${e}'.`),this.containerName=e}},ConduitDisposeError=class extends ConduitError{errors;constructor(e){super(`Container disposal failed with ${e.length} cleanup error${e.length===1?``:`s`}.`),this.errors=Object.freeze([...e])}};function token(e){return Symbol(e)}var e=token(`Conduit disposal signal`);function valueProvider(e,t,n={}){return Object.freeze({...n,token:e,value:t})}function factoryProvider(e,t,n,r={}){return Object.freeze({...r,dependencies:Object.freeze([...t]),factory:n,token:e})}var t=class ContainerImpl{#e=new Map;#t=new Set;#n=[];#r=new AbortController;#i=new Set;#a=`active`;#o;#s=[];#c;#l=new Map;name;constructor(t,n,r){this.#c=t,t&&t.#t.add(this),this.name=r.name??(t?`${t.name}:child`:`root`),this.#l.set(e,{kind:`value`,value:this.disposalSignal});try{this.#p(n),this.#_(),this.#m()}catch(e){throw t&&t.#t.delete(this),this.#l.clear(),e}}get disposalSignal(){return this.#r.signal}get disposed(){return this.#a===`disposed`}has(e){return this.#d(),this.#h(e)!==void 0}async resolve(e){if(this.#d(),typeof e==`symbol`)return this.#y(e,[]);if(typeof e!=`object`||!e||Array.isArray(e))throw new ConduitError(`resolve() requires a token or service map`);let t=Object.keys(e),n=await Promise.all(t.map(t=>this.#y(e[t],[]))),r={};return t.forEach((e,t)=>{Object.defineProperty(r,e,{configurable:!0,enumerable:!0,value:n[t],writable:!0})}),r}createScope(e={}){return this.#d(),new ContainerImpl(this,e.providers??[],{name:e.name})}dispose(){return this.#a===`disposed`?Promise.resolve():this.#o?this.#o:(this.#a=`disposing`,this.#r.abort(),this.#o=this.#u(),this.#o)}async[Symbol.asyncDispose](){await this.dispose()}async#u(){let e=await Promise.allSettled([...this.#t].map(e=>e.dispose()));await Promise.allSettled([...this.#i]);let t=[...this.#n,...e.flatMap(e=>e.status===`rejected`?e.reason instanceof ConduitDisposeError?e.reason.errors:[e.reason]:[])];for(let e of[...this.#s].reverse())if(e.dispose)try{await e.dispose(e.value)}catch(e){t.push(e)}if(this.#e.clear(),this.#t.clear(),this.#n=[],this.#s=[],this.#l.clear(),this.#c&&this.#c.#t.delete(this),this.#a=`disposed`,t.length)throw new ConduitDisposeError(t)}#d(){if(this.#a!==`active`)throw new ConduitDisposedError(this.name)}#f(e){if(this.#l.has(e))throw new ConduitDuplicateRegistrationError(e)}#p(e){if(!Array.isArray(e))throw new ConduitError(`Container providers must be an array`);for(let t of e){if(typeof t!=`object`||!t||Array.isArray(t))throw new ConduitError(`Each provider must be an object`);let e=t,n=Object.hasOwn(e,`dependencies`),r=Object.hasOwn(e,`factory`),i=Object.hasOwn(e,`value`);if(typeof e.token!=`symbol`)throw new ConduitError(`Each provider requires a token`);if(e.dispose!==void 0&&typeof e.dispose!=`function`)throw new ConduitError(`Provider "${e.token.description??`anonymous`}" has an invalid disposer`);if(i===r||i===n||i&&Object.hasOwn(e,`lifetime`))throw new ConduitError(`Provider "${e.token.description??`anonymous`}" must define exactly one value or factory`);if(this.#f(e.token),r){let t=e;if(!Array.isArray(t.dependencies)||t.dependencies.some(e=>typeof e!=`symbol`))throw new ConduitError(`Factory provider "${e.token.description??`anonymous`}" has invalid dependencies`);if(typeof t.factory!=`function`)throw new ConduitError(`Factory provider "${e.token.description??`anonymous`}" requires a factory`);if(t.lifetime!==void 0&&t.lifetime!==`singleton`&&t.lifetime!==`transient`)throw new ConduitError(`Factory provider "${e.token.description??`anonymous`}" has an invalid lifetime`);this.#l.set(e.token,{dependencies:Object.freeze([...t.dependencies]),dispose:t.dispose,factory:t.factory,kind:`factory`,lifetime:t.lifetime??`singleton`})}else{let t=e;this.#l.set(e.token,{dispose:t.dispose,kind:`value`,value:t.value})}}}#m(){for(let e of this.#l.values())e.kind===`value`&&e.dispose&&this.#s.push({dispose:e.dispose,value:e.value})}#h(e){let t=this.#l.get(e);if(t)return{owner:this,registration:t};if(this.#c)return this.#c.#h(e)}#g(){let e=this.#c?this.#c.#g():[],t=[...this.#l].flatMap(([e,t])=>t.kind===`factory`?[{owner:this,registration:t,token:e}]:[]);return[...e,...t]}#_(){for(let{owner:e,registration:t,token:n}of this.#g())e.#v(n,t,new Set,[])}#v(e,t,n,r){if(n.has(e))throw new ConduitCircularDependencyError([...r,e]);n.add(e);for(let i of t.dependencies){let a=this.#h(i);if(!a)throw new ConduitProviderNotFoundError(i,this.name);if(a.registration.kind===`factory`){if(t.lifetime===`singleton`&&a.registration.lifetime===`transient`)throw new ConduitError(`Singleton "${e.description??`anonymous`}" cannot depend on a transient factory`);a.owner.#v(i,a.registration,n,[...r,e])}}n.delete(e)}async#y(e,t){if(t.includes(e))throw new ConduitCircularDependencyError([...t,e]);let n=this.#h(e);if(!n)throw new ConduitProviderNotFoundError(e,this.name);let r=n.registration;if(r.kind===`value`)return r.value;if(r.lifetime===`transient`)return this.#b(this.#x(r,this,[...t,e]));let i=n.owner,a=i.#e.get(r);if(a?.resolved)return a.value;if(a)return a.promise;let o={promise:Promise.resolve(),resolved:!1},s=i.#x(r,i,[...t,e]).then(e=>(o.resolved=!0,o.value=e,e),e=>{throw i.#e.get(r)===o&&i.#e.delete(r),e});return o.promise=i.#b(s),i.#e.set(r,o),o.promise}#b(e){return this.#i.add(e),e.then(()=>this.#i.delete(e),()=>this.#i.delete(e)),e}async#x(e,t,n){let r=await Promise.all(e.dependencies.map(e=>t.#y(e,n))).then(t=>e.factory(...t));if(t.#a!==`active`){if(e.dispose)try{await e.dispose(r)}catch(e){t.#n.push(e)}throw new ConduitDisposedError(t.name)}return e.dispose&&t.#s.push({dispose:e.dispose,value:r}),r}};function createContainer(e,n){return new t(void 0,e,{name:n?.name})}export{ConduitCircularDependencyError,ConduitDisposeError,ConduitDisposedError,ConduitDuplicateRegistrationError,ConduitError,ConduitProviderNotFoundError,createContainer,e as disposalSignalToken,factoryProvider,token,valueProvider};
|
|
2
2
|
//# sourceMappingURL=conduit.js.map
|
package/dist/conduit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conduit.js","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/container.ts"],"sourcesContent":["import type { ScopeToken, Token } from './types.js';\n\nexport function tokenName(token: Token<unknown>): string {\n return token.description ?? 'anonymous';\n}\n\nexport class ConduitError extends Error {\n protected static readonly errorName: string = 'ConduitError';\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = (new.target as typeof ConduitError).errorName;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class ConduitCircularDependencyError extends ConduitError {\n protected static override readonly errorName = 'ConduitCircularDependencyError';\n readonly cycle: readonly Token<unknown>[];\n\n constructor(cycle: readonly Token<unknown>[]) {\n super(`Circular dependency detected: ${cycle.map(tokenName).join(' -> ')}`);\n this.cycle = Object.freeze([...cycle]);\n }\n}\n\nexport class ConduitProviderNotFoundError extends ConduitError {\n protected static override readonly errorName = 'ConduitProviderNotFoundError';\n readonly containerName: string;\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>, containerName: string) {\n super(`No provider registered for token: ${tokenName(token)} (in container '${containerName}')`);\n this.containerName = containerName;\n this.token = token;\n }\n}\n\nexport class ConduitDuplicateRegistrationError extends ConduitError {\n protected static override readonly errorName = 'ConduitDuplicateRegistrationError';\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>) {\n super(`Token \"${tokenName(token)}\" is already registered.`);\n this.token = token;\n }\n}\n\nexport class ConduitScopedResolutionError extends ConduitError {\n protected static override readonly errorName = 'ConduitScopedResolutionError';\n readonly requiredScope: ScopeToken;\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>, requiredScope: ScopeToken) {\n super(`Token \"${tokenName(token)}\" requires scope \"${requiredScope.description ?? 'anonymous'}\".`);\n this.requiredScope = requiredScope;\n this.token = token;\n }\n}\n\nexport class ConduitDisposedError extends ConduitError {\n protected static override readonly errorName = 'ConduitDisposedError';\n readonly containerName: string;\n\n constructor(containerName: string) {\n super(`Cannot use disposed container '${containerName}'.`);\n this.containerName = containerName;\n }\n}\n\nexport class ConduitDisposeError extends ConduitError {\n protected static override readonly errorName = 'ConduitDisposeError';\n readonly errors: readonly unknown[];\n\n constructor(errors: readonly unknown[]) {\n super(`Container disposal failed with ${errors.length} cleanup error${errors.length === 1 ? '' : 's'}.`);\n this.errors = Object.freeze([...errors]);\n }\n}\n","declare const tokenBrand: unique symbol;\ndeclare const scopeBrand: unique symbol;\n\nexport type Token<T = unknown> = symbol & { readonly [tokenBrand]: T };\nexport type ScopeToken = symbol & { readonly [scopeBrand]: true };\n\nexport function token<T>(description: string): Token<T> {\n return Symbol(description) as Token<T>;\n}\n\nexport function scope(name: string): ScopeToken {\n return Symbol(name) as ScopeToken;\n}\n\nexport const disposalSignalToken = token<AbortSignal>('Conduit disposal signal');\n\n/** Singleton results are cached on the registering container; transient results belong to the requesting container; a `ScopeToken` caches on the matching child scope. */\nexport type Lifetime = 'singleton' | 'transient' | ScopeToken;\n\nexport type InferTokens<T extends readonly Token<unknown>[]> = {\n [K in keyof T]: T[K] extends Token<infer Value> ? Value : never;\n};\n\nexport type ValueOptions<T> = Readonly<{\n dispose?: (value: T) => Promise<void> | void;\n}>;\n\nexport type FactoryOptions<T> = Readonly<{\n dispose?: (value: T) => Promise<void> | void;\n lifetime?: Lifetime;\n}>;\n\nexport interface ValueProvider<T> {\n readonly dispose?: (value: T) => Promise<void> | void;\n readonly token: Token<T>;\n readonly value: T;\n}\n\nexport interface FactoryProvider<T, Dependencies extends readonly Token<unknown>[] = readonly Token<unknown>[]> {\n readonly dependencies: Dependencies;\n readonly dispose?: (value: T) => Promise<void> | void;\n readonly factory: (...values: InferTokens<Dependencies>) => Promise<T> | T;\n readonly lifetime?: Lifetime;\n readonly token: Token<T>;\n}\n\nexport type Provider<T = unknown, Dependencies extends readonly Token<unknown>[] = readonly Token<unknown>[]> =\n | ValueProvider<T>\n | FactoryProvider<T, Dependencies>;\n\nexport function valueProvider<T>(token: Token<T>, value: NoInfer<T>, options: ValueOptions<T> = {}): ValueProvider<T> {\n return Object.freeze({ ...options, token, value });\n}\n\nexport function factoryProvider<T, const Dependencies extends readonly Token<unknown>[]>(\n token: Token<T>,\n dependencies: Dependencies,\n factory: (...values: InferTokens<Dependencies>) => Promise<T> | T,\n options: FactoryOptions<T> = {},\n): FactoryProvider<T, Dependencies> {\n return Object.freeze({\n ...options,\n dependencies: Object.freeze([...dependencies]) as unknown as Dependencies,\n factory,\n token,\n });\n}\n\n/** Map of service name to dependency token, passed to `container.resolve()` at a composition root. */\nexport type ServiceMap = { readonly [key: string]: Token<unknown> };\n\nexport type InferServices<M extends ServiceMap> = {\n readonly [K in keyof M]: M[K] extends Token<infer Value> ? Value : never;\n};\n\nexport interface Container {\n createScope(\n scope?: ScopeToken,\n options?: { readonly name?: string; readonly providers?: readonly Provider<any, any>[] },\n ): Container;\n readonly disposalSignal: AbortSignal;\n dispose(): Promise<void>;\n readonly disposed: boolean;\n has<T>(token: Token<T>): boolean;\n readonly name: string;\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n","import {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n ConduitScopedResolutionError,\n} from './errors.js';\nimport type {\n Container,\n FactoryProvider,\n InferServices,\n Lifetime,\n Provider,\n ScopeToken,\n ServiceMap,\n Token,\n ValueProvider,\n} from './types.js';\nimport { disposalSignalToken } from './types.js';\n\ntype Disposer = (value: unknown) => Promise<void> | void;\n\ntype ValueRegistration<T> = Readonly<{\n dispose?: Disposer;\n kind: 'value';\n value: T;\n}>;\n\ntype FactoryRegistration<T = unknown> = Readonly<{\n factory: (...values: unknown[]) => Promise<T> | T;\n dependencies: readonly Token<unknown>[];\n dispose?: Disposer;\n kind: 'factory';\n lifetime: Lifetime;\n}>;\n\ntype Registration<T = unknown> = FactoryRegistration<T> | ValueRegistration<T>;\ntype OwnedResource = Readonly<{ dispose?: Disposer; value: unknown }>;\ntype CacheEntry = { promise: Promise<unknown>; resolved: boolean; value?: unknown };\ntype Lifecycle = 'active' | 'disposed' | 'disposing';\n\nclass ContainerImpl implements Container {\n #cache = new Map<FactoryRegistration<unknown>, CacheEntry>();\n #children = new Set<ContainerImpl>();\n #cleanupFailures: unknown[] = [];\n #disposalController = new AbortController();\n #inFlight = new Set<Promise<unknown>>();\n #lifecycle: Lifecycle = 'active';\n #disposePromise?: Promise<void>;\n #owned: OwnedResource[] = [];\n #parent?: ContainerImpl;\n #registry = new Map<Token<unknown>, Registration<unknown>>();\n #scope?: ScopeToken;\n readonly name: string;\n\n constructor(\n parent: ContainerImpl | undefined,\n providers: readonly Provider<any, any>[],\n options: { name?: string; scope?: ScopeToken },\n ) {\n this.#parent = parent;\n this.#scope = options.scope;\n\n if (parent) parent.#children.add(this);\n\n this.name = options.name ?? (parent ? `${parent.name}:${options.scope?.description ?? 'child'}` : 'root');\n this.#registry.set(disposalSignalToken, { kind: 'value', value: this.disposalSignal });\n\n try {\n this.#registerProviders(providers);\n this.#validateGraph();\n this.#claimValues();\n } catch (error) {\n if (parent) parent.#children.delete(this);\n this.#registry.clear();\n throw error;\n }\n }\n\n get disposalSignal(): AbortSignal {\n return this.#disposalController.signal;\n }\n\n get disposed(): boolean {\n return this.#lifecycle === 'disposed';\n }\n\n has<T>(token: Token<T>): boolean {\n this.#assertActive();\n\n return this.#lookup(token) !== undefined;\n }\n\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n async resolve<T, M extends ServiceMap>(input: Token<T> | M): Promise<InferServices<M> | T> {\n this.#assertActive();\n\n if (typeof input === 'symbol') return this.#resolve(input, []);\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw new ConduitError('resolve() requires a token or service map');\n }\n\n const entries = Object.keys(input) as (keyof M & string)[];\n const values = await Promise.all(entries.map((key) => this.#resolve(input[key] as Token<unknown>, [])));\n const services = {} as InferServices<M>;\n\n entries.forEach((key, index) => {\n Object.defineProperty(services, key, {\n configurable: true,\n enumerable: true,\n value: values[index],\n writable: true,\n });\n });\n\n return services;\n }\n\n createScope(\n scope?: ScopeToken,\n options?: { readonly name?: string; readonly providers?: readonly Provider<any, any>[] },\n ): Container {\n this.#assertActive();\n\n return new ContainerImpl(this, options?.providers ?? [], { name: options?.name, scope });\n }\n\n dispose(): Promise<void> {\n if (this.#lifecycle === 'disposed') return Promise.resolve();\n\n if (this.#disposePromise) return this.#disposePromise;\n\n this.#lifecycle = 'disposing';\n this.#disposalController.abort();\n this.#disposePromise = this.#finishDisposal();\n\n return this.#disposePromise;\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.dispose();\n }\n\n async #finishDisposal(): Promise<void> {\n const childOutcomes = await Promise.allSettled([...this.#children].map((child) => child.dispose()));\n\n await Promise.allSettled([...this.#inFlight]);\n\n const failures = [\n ...this.#cleanupFailures,\n ...childOutcomes.flatMap((outcome) => {\n if (outcome.status !== 'rejected') return [];\n\n return outcome.reason instanceof ConduitDisposeError ? outcome.reason.errors : [outcome.reason];\n }),\n ];\n\n for (const resource of [...this.#owned].reverse()) {\n if (!resource.dispose) continue;\n\n try {\n await resource.dispose(resource.value);\n } catch (error) {\n failures.push(error);\n }\n }\n\n this.#cache.clear();\n this.#children.clear();\n this.#cleanupFailures = [];\n this.#owned = [];\n this.#registry.clear();\n\n if (this.#parent) this.#parent.#children.delete(this);\n\n this.#lifecycle = 'disposed';\n\n if (failures.length) throw new ConduitDisposeError(failures);\n }\n\n #assertActive(): void {\n if (this.#lifecycle !== 'active') throw new ConduitDisposedError(this.name);\n }\n\n #assertUnregistered(token: Token<unknown>): void {\n if (this.#registry.has(token)) throw new ConduitDuplicateRegistrationError(token);\n }\n\n #registerProviders(providers: readonly Provider<any, any>[]): void {\n if (!Array.isArray(providers)) throw new ConduitError('Container providers must be an array');\n\n for (const input of providers) {\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw new ConduitError('Each provider must be an object');\n }\n\n const provider = input as Provider;\n const hasDependencies = Object.hasOwn(provider, 'dependencies');\n const hasFactory = Object.hasOwn(provider, 'factory');\n const hasValue = Object.hasOwn(provider, 'value');\n\n if (typeof provider.token !== 'symbol') throw new ConduitError('Each provider requires a token');\n if (provider.dispose !== undefined && typeof provider.dispose !== 'function') {\n throw new ConduitError(`Provider \"${provider.token.description ?? 'anonymous'}\" has an invalid disposer`);\n }\n if (\n hasValue === hasFactory ||\n hasValue === hasDependencies ||\n (hasValue && Object.hasOwn(provider, 'lifetime'))\n ) {\n throw new ConduitError(\n `Provider \"${provider.token.description ?? 'anonymous'}\" must define exactly one value or factory`,\n );\n }\n\n this.#assertUnregistered(provider.token);\n\n if (hasFactory) {\n const factory = provider as FactoryProvider<unknown>;\n\n if (\n !Array.isArray(factory.dependencies) ||\n factory.dependencies.some((dependency) => typeof dependency !== 'symbol')\n ) {\n throw new ConduitError(\n `Factory provider \"${provider.token.description ?? 'anonymous'}\" has invalid dependencies`,\n );\n }\n if (typeof factory.factory !== 'function') {\n throw new ConduitError(`Factory provider \"${provider.token.description ?? 'anonymous'}\" requires a factory`);\n }\n if (\n factory.lifetime !== undefined &&\n factory.lifetime !== 'singleton' &&\n factory.lifetime !== 'transient' &&\n typeof factory.lifetime !== 'symbol'\n ) {\n throw new ConduitError(\n `Factory provider \"${provider.token.description ?? 'anonymous'}\" has an invalid lifetime`,\n );\n }\n\n this.#registry.set(provider.token, {\n dependencies: Object.freeze([...factory.dependencies]),\n dispose: factory.dispose as Disposer | undefined,\n factory: factory.factory as (...values: unknown[]) => Promise<unknown> | unknown,\n kind: 'factory',\n lifetime: factory.lifetime ?? 'singleton',\n });\n } else {\n const valueProvider = provider as ValueProvider<unknown>;\n\n this.#registry.set(provider.token, {\n dispose: valueProvider.dispose as Disposer | undefined,\n kind: 'value',\n value: valueProvider.value,\n });\n }\n }\n }\n\n #claimValues(): void {\n for (const registration of this.#registry.values()) {\n if (registration.kind === 'value' && registration.dispose) {\n this.#owned.push({ dispose: registration.dispose, value: registration.value });\n }\n }\n }\n\n #lookup<T>(token: Token<T>): { owner: ContainerImpl; registration: Registration<T> } | undefined {\n const local = this.#registry.get(token) as Registration<T> | undefined;\n\n if (local) return { owner: this, registration: local };\n\n if (!this.#parent) return undefined;\n\n return this.#parent.#lookup(token);\n }\n\n #factories(): { owner: ContainerImpl; registration: FactoryRegistration; token: Token<unknown> }[] {\n const parentFactories = this.#parent ? this.#parent.#factories() : [];\n const localFactories = [...this.#registry].flatMap(([token, registration]) =>\n registration.kind === 'factory' ? [{ owner: this, registration, token }] : [],\n );\n\n return [...parentFactories, ...localFactories];\n }\n\n #validateGraph(): void {\n for (const { owner, registration, token } of this.#factories()) {\n owner.#validatePath(token, registration, new Set(), []);\n }\n }\n\n #validatePath(\n token: Token<unknown>,\n registration: FactoryRegistration,\n visiting: Set<Token<unknown>>,\n path: Token<unknown>[],\n ): void {\n if (visiting.has(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n visiting.add(token);\n\n for (const dependency of registration.dependencies) {\n const found = this.#lookup(dependency);\n\n if (!found) throw new ConduitProviderNotFoundError(dependency, this.name);\n\n if (found.registration.kind === 'factory') {\n if (registration.lifetime === 'singleton' && found.registration.lifetime === 'transient') {\n throw new ConduitError(\n `Singleton \"${token.description ?? 'anonymous'}\" cannot depend on a transient factory`,\n );\n }\n if (registration.lifetime === 'singleton' && typeof found.registration.lifetime === 'symbol') {\n throw new ConduitScopedResolutionError(token, found.registration.lifetime);\n }\n if (\n typeof registration.lifetime === 'symbol' &&\n typeof found.registration.lifetime === 'symbol' &&\n registration.lifetime !== found.registration.lifetime\n ) {\n throw new ConduitScopedResolutionError(token, found.registration.lifetime);\n }\n\n found.owner.#validatePath(dependency, found.registration, visiting, [...path, token]);\n }\n }\n\n visiting.delete(token);\n }\n\n async #resolve<T>(token: Token<T>, path: Token<unknown>[]): Promise<T> {\n if (path.includes(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n const found = this.#lookup(token);\n\n if (!found) throw new ConduitProviderNotFoundError(token, this.name);\n\n const registration = found.registration;\n\n if (registration.kind === 'value') return registration.value as T;\n\n const owner = this.#ownerFor(found.owner, registration, token);\n\n if (registration.lifetime === 'transient') {\n return owner.#track(owner.#create(registration, owner, [...path, token])) as Promise<T>;\n }\n\n const existing = owner.#cache.get(registration);\n\n if (existing?.resolved) return existing.value as T;\n if (existing) return existing.promise as Promise<T>;\n\n const entry = { promise: Promise.resolve(), resolved: false } as CacheEntry;\n const creation = owner.#create(registration, owner, [...path, token]).then(\n (value) => {\n entry.resolved = true;\n entry.value = value;\n return value;\n },\n (error) => {\n if (owner.#cache.get(registration) === entry) owner.#cache.delete(registration);\n throw error;\n },\n );\n\n entry.promise = owner.#track(creation);\n owner.#cache.set(registration, entry);\n\n return entry.promise as Promise<T>;\n }\n\n #ownerFor(owner: ContainerImpl, registration: FactoryRegistration, token: Token<unknown>): ContainerImpl {\n if (registration.lifetime === 'singleton') return owner;\n if (registration.lifetime === 'transient') return this;\n\n const scopeOwner = this.#scopeOwner(registration.lifetime as ScopeToken);\n\n if (!scopeOwner) throw new ConduitScopedResolutionError(token, registration.lifetime as ScopeToken);\n\n return scopeOwner;\n }\n\n #scopeOwner(scope: ScopeToken): ContainerImpl | undefined {\n if (this.#scope === scope) return this;\n\n return this.#parent ? this.#parent.#scopeOwner(scope) : undefined;\n }\n\n #track<T>(promise: Promise<T>): Promise<T> {\n this.#inFlight.add(promise);\n void promise.then(\n () => this.#inFlight.delete(promise),\n () => this.#inFlight.delete(promise),\n );\n return promise;\n }\n\n async #create(registration: FactoryRegistration, owner: ContainerImpl, path: Token<unknown>[]): Promise<unknown> {\n const value = await Promise.all(\n registration.dependencies.map((dependency) => owner.#resolve(dependency, path)),\n ).then((dependencies) => registration.factory(...dependencies));\n\n if (owner.#lifecycle !== 'active') {\n if (registration.dispose) {\n try {\n await registration.dispose(value);\n } catch (error) {\n owner.#cleanupFailures.push(error);\n }\n }\n\n throw new ConduitDisposedError(owner.name);\n }\n\n if (registration.dispose) owner.#owned.push({ dispose: registration.dispose, value });\n\n return value;\n }\n}\n\nexport function createContainer(\n providers: readonly Provider<any, any>[],\n options?: { readonly name?: string },\n): Container {\n return new ContainerImpl(undefined, providers, { name: options?.name });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"conduit.js","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/container.ts"],"sourcesContent":["import type { Token } from './types.js';\n\nfunction tokenName(token: Token<unknown>): string {\n return token.description ?? 'anonymous';\n}\n\nexport class ConduitError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class ConduitCircularDependencyError extends ConduitError {\n readonly cycle: readonly Token<unknown>[];\n\n constructor(cycle: readonly Token<unknown>[]) {\n super(`Circular dependency detected: ${cycle.map(tokenName).join(' -> ')}`);\n this.cycle = Object.freeze([...cycle]);\n }\n}\n\nexport class ConduitProviderNotFoundError extends ConduitError {\n readonly containerName: string;\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>, containerName: string) {\n super(`No provider registered for token: ${tokenName(token)} (in container '${containerName}')`);\n this.containerName = containerName;\n this.token = token;\n }\n}\n\nexport class ConduitDuplicateRegistrationError extends ConduitError {\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>) {\n super(`Token \"${tokenName(token)}\" is already registered.`);\n this.token = token;\n }\n}\n\nexport class ConduitDisposedError extends ConduitError {\n readonly containerName: string;\n\n constructor(containerName: string) {\n super(`Cannot use disposed container '${containerName}'.`);\n this.containerName = containerName;\n }\n}\n\nexport class ConduitDisposeError extends ConduitError {\n readonly errors: readonly unknown[];\n\n constructor(errors: readonly unknown[]) {\n super(`Container disposal failed with ${errors.length} cleanup error${errors.length === 1 ? '' : 's'}.`);\n this.errors = Object.freeze([...errors]);\n }\n}\n","declare const tokenBrand: unique symbol;\n\nexport type Token<T = unknown> = symbol & { readonly [tokenBrand]: T };\n\nexport function token<T>(description: string): Token<T> {\n return Symbol(description) as Token<T>;\n}\n\nexport const disposalSignalToken = token<AbortSignal>('Conduit disposal signal');\n\n/** Singleton results are cached on the registering container; transient results belong to the requesting container. */\nexport type Lifetime = 'singleton' | 'transient';\n\nexport type InferTokens<T extends readonly Token<unknown>[]> = {\n [K in keyof T]: T[K] extends Token<infer Value> ? Value : never;\n};\n\nexport type ValueOptions<T> = Readonly<{\n dispose?: (value: T) => Promise<void> | void;\n}>;\n\nexport type FactoryOptions<T> = Readonly<{\n dispose?: (value: T) => Promise<void> | void;\n lifetime?: Lifetime;\n}>;\n\nexport interface ValueProvider<T> {\n readonly dispose?: (value: T) => Promise<void> | void;\n readonly token: Token<T>;\n readonly value: T;\n}\n\nexport interface FactoryProvider<T, Dependencies extends readonly Token<unknown>[] = readonly Token<unknown>[]> {\n readonly dependencies: Dependencies;\n readonly dispose?: (value: T) => Promise<void> | void;\n readonly factory: (...values: InferTokens<Dependencies>) => Promise<T> | T;\n readonly lifetime?: Lifetime;\n readonly token: Token<T>;\n}\n\nexport type Provider<T = unknown, Dependencies extends readonly Token<unknown>[] = readonly Token<unknown>[]> =\n | ValueProvider<T>\n | FactoryProvider<T, Dependencies>;\n\n/**\n * Type-erased provider for the heterogeneous lists accepted by\n * `createContainer()` and `createScope()`. Providers are invariant in their\n * value type, so erasure needs `any` at this one boundary; registration\n * re-validates every provider at runtime.\n */\nexport type AnyProvider = Provider<any, any>;\n\nexport function valueProvider<T>(token: Token<T>, value: NoInfer<T>, options: ValueOptions<T> = {}): ValueProvider<T> {\n return Object.freeze({ ...options, token, value });\n}\n\nexport function factoryProvider<T, const Dependencies extends readonly Token<unknown>[]>(\n token: Token<T>,\n dependencies: Dependencies,\n factory: (...values: InferTokens<Dependencies>) => Promise<T> | T,\n options: FactoryOptions<T> = {},\n): FactoryProvider<T, Dependencies> {\n return Object.freeze({\n ...options,\n dependencies: Object.freeze([...dependencies]) as unknown as Dependencies,\n factory,\n token,\n });\n}\n\n/** Map of service name to dependency token, passed to `container.resolve()` at a composition root. */\nexport type ServiceMap = { readonly [key: string]: Token<unknown> };\n\nexport type InferServices<M extends ServiceMap> = {\n readonly [K in keyof M]: M[K] extends Token<infer Value> ? Value : never;\n};\n\nexport type CreateScopeOptions = Readonly<{\n name?: string;\n providers?: readonly AnyProvider[];\n}>;\n\nexport interface Container {\n /**\n * Create a child container that inherits parent registrations. Providers\n * registered on the child are local to it, which is how request-scoped\n * values are spelled: one child per request.\n */\n createScope(options?: CreateScopeOptions): Container;\n readonly disposalSignal: AbortSignal;\n dispose(): Promise<void>;\n readonly disposed: boolean;\n has<T>(token: Token<T>): boolean;\n readonly name: string;\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n","import {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitDisposeError,\n ConduitDuplicateRegistrationError,\n ConduitError,\n ConduitProviderNotFoundError,\n} from './errors.js';\nimport type {\n AnyProvider,\n Container,\n CreateScopeOptions,\n FactoryProvider,\n InferServices,\n Lifetime,\n Provider,\n ServiceMap,\n Token,\n ValueProvider,\n} from './types.js';\nimport { disposalSignalToken } from './types.js';\n\ntype Disposer = (value: unknown) => Promise<void> | void;\n\ntype ValueRegistration<T> = Readonly<{\n dispose?: Disposer;\n kind: 'value';\n value: T;\n}>;\n\ntype FactoryRegistration<T = unknown> = Readonly<{\n factory: (...values: unknown[]) => Promise<T> | T;\n dependencies: readonly Token<unknown>[];\n dispose?: Disposer;\n kind: 'factory';\n lifetime: Lifetime;\n}>;\n\ntype Registration<T = unknown> = FactoryRegistration<T> | ValueRegistration<T>;\ntype OwnedResource = Readonly<{ dispose?: Disposer; value: unknown }>;\ntype CacheEntry = { promise: Promise<unknown>; resolved: boolean; value?: unknown };\ntype Lifecycle = 'active' | 'disposed' | 'disposing';\n\nclass ContainerImpl implements Container {\n #cache = new Map<FactoryRegistration<unknown>, CacheEntry>();\n #children = new Set<ContainerImpl>();\n #cleanupFailures: unknown[] = [];\n #disposalController = new AbortController();\n #inFlight = new Set<Promise<unknown>>();\n #lifecycle: Lifecycle = 'active';\n #disposePromise?: Promise<void>;\n #owned: OwnedResource[] = [];\n #parent?: ContainerImpl;\n #registry = new Map<Token<unknown>, Registration<unknown>>();\n readonly name: string;\n\n constructor(parent: ContainerImpl | undefined, providers: readonly AnyProvider[], options: CreateScopeOptions) {\n this.#parent = parent;\n\n if (parent) parent.#children.add(this);\n\n this.name = options.name ?? (parent ? `${parent.name}:child` : 'root');\n this.#registry.set(disposalSignalToken, { kind: 'value', value: this.disposalSignal });\n\n try {\n this.#registerProviders(providers);\n this.#validateGraph();\n this.#claimValues();\n } catch (error) {\n if (parent) parent.#children.delete(this);\n this.#registry.clear();\n throw error;\n }\n }\n\n get disposalSignal(): AbortSignal {\n return this.#disposalController.signal;\n }\n\n get disposed(): boolean {\n return this.#lifecycle === 'disposed';\n }\n\n has<T>(token: Token<T>): boolean {\n this.#assertActive();\n\n return this.#lookup(token) !== undefined;\n }\n\n resolve<T>(token: Token<T>): Promise<T>;\n resolve<M extends ServiceMap>(map: M): Promise<InferServices<M>>;\n async resolve<T, M extends ServiceMap>(input: Token<T> | M): Promise<InferServices<M> | T> {\n this.#assertActive();\n\n if (typeof input === 'symbol') return this.#resolve(input, []);\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw new ConduitError('resolve() requires a token or service map');\n }\n\n const entries = Object.keys(input) as (keyof M & string)[];\n const values = await Promise.all(entries.map((key) => this.#resolve(input[key] as Token<unknown>, [])));\n const services = {} as InferServices<M>;\n\n entries.forEach((key, index) => {\n Object.defineProperty(services, key, {\n configurable: true,\n enumerable: true,\n value: values[index],\n writable: true,\n });\n });\n\n return services;\n }\n\n createScope(options: CreateScopeOptions = {}): Container {\n this.#assertActive();\n\n return new ContainerImpl(this, options.providers ?? [], { name: options.name });\n }\n\n dispose(): Promise<void> {\n if (this.#lifecycle === 'disposed') return Promise.resolve();\n\n if (this.#disposePromise) return this.#disposePromise;\n\n this.#lifecycle = 'disposing';\n this.#disposalController.abort();\n this.#disposePromise = this.#finishDisposal();\n\n return this.#disposePromise;\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.dispose();\n }\n\n async #finishDisposal(): Promise<void> {\n const childOutcomes = await Promise.allSettled([...this.#children].map((child) => child.dispose()));\n\n await Promise.allSettled([...this.#inFlight]);\n\n const failures = [\n ...this.#cleanupFailures,\n ...childOutcomes.flatMap((outcome) => {\n if (outcome.status !== 'rejected') return [];\n\n return outcome.reason instanceof ConduitDisposeError ? outcome.reason.errors : [outcome.reason];\n }),\n ];\n\n for (const resource of [...this.#owned].reverse()) {\n if (!resource.dispose) continue;\n\n try {\n await resource.dispose(resource.value);\n } catch (error) {\n failures.push(error);\n }\n }\n\n this.#cache.clear();\n this.#children.clear();\n this.#cleanupFailures = [];\n this.#owned = [];\n this.#registry.clear();\n\n if (this.#parent) this.#parent.#children.delete(this);\n\n this.#lifecycle = 'disposed';\n\n if (failures.length) throw new ConduitDisposeError(failures);\n }\n\n #assertActive(): void {\n if (this.#lifecycle !== 'active') throw new ConduitDisposedError(this.name);\n }\n\n #assertUnregistered(token: Token<unknown>): void {\n if (this.#registry.has(token)) throw new ConduitDuplicateRegistrationError(token);\n }\n\n #registerProviders(providers: readonly AnyProvider[]): void {\n if (!Array.isArray(providers)) throw new ConduitError('Container providers must be an array');\n\n for (const input of providers) {\n if (typeof input !== 'object' || input === null || Array.isArray(input)) {\n throw new ConduitError('Each provider must be an object');\n }\n\n const provider = input as Provider;\n const hasDependencies = Object.hasOwn(provider, 'dependencies');\n const hasFactory = Object.hasOwn(provider, 'factory');\n const hasValue = Object.hasOwn(provider, 'value');\n\n if (typeof provider.token !== 'symbol') throw new ConduitError('Each provider requires a token');\n if (provider.dispose !== undefined && typeof provider.dispose !== 'function') {\n throw new ConduitError(`Provider \"${provider.token.description ?? 'anonymous'}\" has an invalid disposer`);\n }\n if (\n hasValue === hasFactory ||\n hasValue === hasDependencies ||\n (hasValue && Object.hasOwn(provider, 'lifetime'))\n ) {\n throw new ConduitError(\n `Provider \"${provider.token.description ?? 'anonymous'}\" must define exactly one value or factory`,\n );\n }\n\n this.#assertUnregistered(provider.token);\n\n if (hasFactory) {\n const factory = provider as FactoryProvider<unknown>;\n\n if (\n !Array.isArray(factory.dependencies) ||\n factory.dependencies.some((dependency) => typeof dependency !== 'symbol')\n ) {\n throw new ConduitError(\n `Factory provider \"${provider.token.description ?? 'anonymous'}\" has invalid dependencies`,\n );\n }\n if (typeof factory.factory !== 'function') {\n throw new ConduitError(`Factory provider \"${provider.token.description ?? 'anonymous'}\" requires a factory`);\n }\n if (factory.lifetime !== undefined && factory.lifetime !== 'singleton' && factory.lifetime !== 'transient') {\n throw new ConduitError(\n `Factory provider \"${provider.token.description ?? 'anonymous'}\" has an invalid lifetime`,\n );\n }\n\n this.#registry.set(provider.token, {\n dependencies: Object.freeze([...factory.dependencies]),\n dispose: factory.dispose as Disposer | undefined,\n factory: factory.factory as (...values: unknown[]) => Promise<unknown> | unknown,\n kind: 'factory',\n lifetime: factory.lifetime ?? 'singleton',\n });\n } else {\n const valueProvider = provider as ValueProvider<unknown>;\n\n this.#registry.set(provider.token, {\n dispose: valueProvider.dispose as Disposer | undefined,\n kind: 'value',\n value: valueProvider.value,\n });\n }\n }\n }\n\n #claimValues(): void {\n for (const registration of this.#registry.values()) {\n if (registration.kind === 'value' && registration.dispose) {\n this.#owned.push({ dispose: registration.dispose, value: registration.value });\n }\n }\n }\n\n #lookup<T>(token: Token<T>): { owner: ContainerImpl; registration: Registration<T> } | undefined {\n const local = this.#registry.get(token) as Registration<T> | undefined;\n\n if (local) return { owner: this, registration: local };\n\n if (!this.#parent) return undefined;\n\n return this.#parent.#lookup(token);\n }\n\n #factories(): { owner: ContainerImpl; registration: FactoryRegistration; token: Token<unknown> }[] {\n const parentFactories = this.#parent ? this.#parent.#factories() : [];\n const localFactories = [...this.#registry].flatMap(([token, registration]) =>\n registration.kind === 'factory' ? [{ owner: this, registration, token }] : [],\n );\n\n return [...parentFactories, ...localFactories];\n }\n\n #validateGraph(): void {\n for (const { owner, registration, token } of this.#factories()) {\n owner.#validatePath(token, registration, new Set(), []);\n }\n }\n\n #validatePath(\n token: Token<unknown>,\n registration: FactoryRegistration,\n visiting: Set<Token<unknown>>,\n path: Token<unknown>[],\n ): void {\n if (visiting.has(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n visiting.add(token);\n\n for (const dependency of registration.dependencies) {\n const found = this.#lookup(dependency);\n\n if (!found) throw new ConduitProviderNotFoundError(dependency, this.name);\n\n if (found.registration.kind === 'factory') {\n if (registration.lifetime === 'singleton' && found.registration.lifetime === 'transient') {\n throw new ConduitError(\n `Singleton \"${token.description ?? 'anonymous'}\" cannot depend on a transient factory`,\n );\n }\n\n found.owner.#validatePath(dependency, found.registration, visiting, [...path, token]);\n }\n }\n\n visiting.delete(token);\n }\n\n async #resolve<T>(token: Token<T>, path: Token<unknown>[]): Promise<T> {\n if (path.includes(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n const found = this.#lookup(token);\n\n if (!found) throw new ConduitProviderNotFoundError(token, this.name);\n\n const registration = found.registration;\n\n if (registration.kind === 'value') return registration.value as T;\n\n if (registration.lifetime === 'transient') {\n return this.#track(this.#create(registration, this, [...path, token])) as Promise<T>;\n }\n\n const owner = found.owner;\n const existing = owner.#cache.get(registration);\n\n if (existing?.resolved) return existing.value as T;\n if (existing) return existing.promise as Promise<T>;\n\n const entry = { promise: Promise.resolve(), resolved: false } as CacheEntry;\n const creation = owner.#create(registration, owner, [...path, token]).then(\n (value) => {\n entry.resolved = true;\n entry.value = value;\n return value;\n },\n (error) => {\n if (owner.#cache.get(registration) === entry) owner.#cache.delete(registration);\n throw error;\n },\n );\n\n entry.promise = owner.#track(creation);\n owner.#cache.set(registration, entry);\n\n return entry.promise as Promise<T>;\n }\n\n #track<T>(promise: Promise<T>): Promise<T> {\n this.#inFlight.add(promise);\n void promise.then(\n () => this.#inFlight.delete(promise),\n () => this.#inFlight.delete(promise),\n );\n return promise;\n }\n\n async #create(registration: FactoryRegistration, owner: ContainerImpl, path: Token<unknown>[]): Promise<unknown> {\n const value = await Promise.all(\n registration.dependencies.map((dependency) => owner.#resolve(dependency, path)),\n ).then((dependencies) => registration.factory(...dependencies));\n\n if (owner.#lifecycle !== 'active') {\n if (registration.dispose) {\n try {\n await registration.dispose(value);\n } catch (error) {\n owner.#cleanupFailures.push(error);\n }\n }\n\n throw new ConduitDisposedError(owner.name);\n }\n\n if (registration.dispose) owner.#owned.push({ dispose: registration.dispose, value });\n\n return value;\n }\n}\n\nexport function createContainer(providers: readonly AnyProvider[], options?: { readonly name?: string }): Container {\n return new ContainerImpl(undefined, providers, { name: options?.name });\n}\n"],"mappings":"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"}
|