better-effect 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["storage","SCOPE_SUCCESS","SCOPE_SUCCESS"],"sources":["../src/service/runtime.ts","../src/service/service.ts","../src/layer/internal.ts","../src/layer/layer.ts","../src/scope/errors.ts","../src/scope/disposable.ts","../src/scope/runtime.ts","../src/scope/internal.ts","../src/scope/scope.ts","../src/runtime/outcome.ts","../src/layer/runtime.ts","../src/effect/combinators.ts","../src/effect/effect.ts","../src/function/pipe.ts","../src/resource/errors.ts","../src/resource/internal.ts","../src/resource/resource.ts","../src/runtime/runtime.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport { ServiceRuntimeNotConfiguredError } from './errors'\n\nimport type { AnyServiceToken } from './types'\n\nexport interface ServiceResolver {\n resolve<T extends AnyServiceToken>(token: T): InstanceType<T> | PromiseLike<InstanceType<T>>\n}\n\nconst storage = new AsyncLocalStorage<ServiceResolver>()\n\nexport class ServiceRuntime {\n static run<A>(resolver: ServiceResolver, program: () => A): A {\n return storage.run(resolver, program)\n }\n\n static current(): ServiceResolver {\n const resolver = storage.getStore()\n\n if (!resolver) {\n throw new ServiceRuntimeNotConfiguredError()\n }\n\n return resolver\n }\n\n static async resolve<T extends AnyServiceToken>(token: T): Promise<InstanceType<T>> {\n const resolver = ServiceRuntime.current()\n\n return await resolver.resolve(token)\n }\n}\n","import { ServiceRuntime } from './runtime'\n\nimport type { ServiceRequirement } from '../effect/types'\n\nimport type { ServiceToken } from './types'\n\nexport function Service<Self>() {\n return class {\n // oxlint-disable-next-line require-yield\n static async *[Symbol.asyncIterator](\n this: ServiceToken<Self>\n ): AsyncGenerator<ServiceRequirement<ServiceToken<Self>>, Self, unknown> {\n return await ServiceRuntime.resolve(this)\n }\n }\n}\n","import { LayerGeneratorYieldError } from './errors'\n\nimport type { ServiceRequirement } from '../effect/types'\nimport type { AnyServiceToken, ServiceClass } from '../service'\n\nimport type { LayerGenerator } from './types'\n\nexport const runLayerGenerator = async <\n S extends ServiceClass<any>,\n Yield extends ServiceRequirement<AnyServiceToken>\n>(\n service: S,\n factory: LayerGenerator<S, Yield>\n): Promise<InstanceType<S>> => {\n const iterator = factory()\n\n const state = await iterator.next()\n\n if (!state.done) {\n try {\n await iterator.return(undefined as InstanceType<S>)\n } finally {\n // oxlint-disable-next-line no-unsafe-finally\n throw new LayerGeneratorYieldError(service)\n }\n }\n\n return state.value\n}\n","import type { ServiceRequirement } from '../effect/types'\nimport type { AnyServiceToken, ServiceClass, ServiceRequirements } from '../service'\nimport type { ScopeOutcome } from '../scope'\nimport type { MaybePromise } from '../utils/types'\n\nimport { DuplicateServiceError } from './errors'\n\nimport { runLayerGenerator } from './internal'\n\nimport type { LayerGenerator, LayerGeneratorRequirements, LayerProvider, LayerSpec } from './types'\n\nimport type { AnyLayerSpec } from './types'\n\nimport type { OverrideLayerSpecs } from './inference'\n\ndeclare const LayerTypeId: unique symbol\n\nexport class Layer<Specs extends AnyLayerSpec = AnyLayerSpec> {\n declare readonly [LayerTypeId]: Specs\n\n readonly providers: readonly LayerProvider[]\n\n private constructor(providers: readonly LayerProvider[]) {\n this.providers = Object.freeze([...providers])\n }\n\n static make<S extends ServiceClass<any>>(\n service: S,\n\n acquire: () => MaybePromise<InstanceType<S>>\n ): Layer<LayerSpec<S, ServiceRequirements<S>>> {\n return new Layer([\n {\n service,\n acquire\n }\n ])\n }\n\n static succeed<S extends ServiceClass<any>>(\n service: S,\n instance: InstanceType<S>\n ): Layer<LayerSpec<S, ServiceRequirements<S>>> {\n return Layer.make(service, () => instance)\n }\n\n /**\n * Define a dependency-free provider with Runtime-root cleanup.\n *\n * The release callback intentionally keeps its compatibility-friendly\n * one-argument shape. Use `scopedGen` when cleanup needs `ScopeOutcome`.\n */\n static scoped<S extends ServiceClass<any>>(\n service: S,\n acquire: () => MaybePromise<InstanceType<S>>,\n release: (instance: InstanceType<S>) => MaybePromise<void>\n ): Layer<LayerSpec<S, ServiceRequirements<S>>> {\n return new Layer([\n {\n service,\n acquire,\n\n release: (instance) => release(instance as InstanceType<S>)\n }\n ])\n }\n\n /** Define a contextual provider with Runtime-root, outcome-aware cleanup. */\n static scopedGen<S extends ServiceClass<any>, Yield extends ServiceRequirement<AnyServiceToken>>(\n service: S,\n factory: LayerGenerator<S, Yield>,\n release: (instance: InstanceType<S>, outcome: ScopeOutcome) => MaybePromise<void>\n ): Layer<LayerSpec<S, LayerGeneratorRequirements<S, Yield>>> {\n return new Layer([\n {\n service,\n acquire: () => runLayerGenerator(service, factory),\n release: (instance, outcome) => release(instance as InstanceType<S>, outcome)\n }\n ])\n }\n\n static gen<S extends ServiceClass<any>, Yield extends ServiceRequirement<AnyServiceToken>>(\n service: S,\n factory: LayerGenerator<S, Yield>\n ): Layer<LayerSpec<S, LayerGeneratorRequirements<S, Yield>>> {\n return Layer.make(service, () => runLayerGenerator(service, factory))\n }\n\n static merge<const Layers extends readonly Layer<any>[]>(\n ...layers: Layers\n ): Layer<Layers[number] extends Layer<infer Specs> ? Specs : never> {\n const providers = new Map<ServiceClass<any>, LayerProvider>()\n\n for (const layer of layers) {\n for (const provider of layer.providers) {\n const service = provider.service\n\n if (providers.has(service)) {\n throw new DuplicateServiceError(service)\n }\n\n providers.set(service, provider)\n }\n }\n\n return new Layer([...providers.values()])\n }\n\n static override<Base extends Layer<any>, const Overrides extends readonly Layer<any>[]>(\n base: Base,\n ...overrides: Overrides\n ): Layer<OverrideLayerSpecs<Base extends Layer<infer Specs> ? Specs : never, Overrides>> {\n const providers = new Map<ServiceClass<any>, LayerProvider>()\n\n for (const provider of base.providers) {\n providers.set(provider.service, provider)\n }\n\n for (const layer of overrides) {\n for (const provider of layer.providers) {\n providers.set(provider.service, provider)\n }\n }\n\n return new Layer([...providers.values()])\n }\n}\n","export class ScopeRuntimeNotConfiguredError extends Error {\n constructor() {\n super('No Scope is available in the current execution context')\n\n this.name = 'ScopeRuntimeNotConfiguredError'\n }\n}\n\nexport class ScopeClosedError extends Error {\n constructor() {\n super('Cannot add resources or finalizers to a closed Scope')\n\n this.name = 'ScopeClosedError'\n }\n}\n\nexport class ScopeCloseError extends Error {\n constructor(readonly causes: readonly unknown[]) {\n super(\n `Failed to close Scope (${causes.length} finalizer${causes.length === 1 ? '' : 's'} failed)`\n )\n\n this.name = 'ScopeCloseError'\n }\n}\n\nexport class ResourceNotDisposableError extends Error {\n constructor() {\n super('Resource does not implement Symbol.dispose or Symbol.asyncDispose')\n\n this.name = 'ResourceNotDisposableError'\n }\n}\n","import type { ScopeFinalizer } from './types'\n\nconst SCOPE_SUCCESS = { status: 'success' } as const\n\ntype DisposableCandidate = {\n [Symbol.dispose]?: unknown\n\n [Symbol.asyncDispose]?: unknown\n}\n\nexport const getDisposeFinalizer = (resource: unknown): ScopeFinalizer | undefined => {\n const candidate = Object(resource) as DisposableCandidate\n const asyncDispose = candidate[Symbol.asyncDispose]\n\n if (typeof asyncDispose === 'function') {\n return () => asyncDispose.call(resource)\n }\n\n const dispose = candidate[Symbol.dispose]\n\n if (typeof dispose === 'function') {\n return () => dispose.call(resource)\n }\n\n return undefined\n}\n\nexport const disposeResource = (resource: unknown): void | PromiseLike<void> => {\n const finalizer = getDisposeFinalizer(resource)\n\n return finalizer?.(SCOPE_SUCCESS)\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport { ScopeRuntimeNotConfiguredError } from './errors'\n\nimport type { Scope } from './scope'\n\nconst storage = new AsyncLocalStorage<Scope>()\n\nexport class ScopeRuntime {\n static run<A>(scope: Scope, program: () => A): A {\n return storage.run(scope, program)\n }\n\n static current(): Scope {\n const scope = storage.getStore()\n\n if (!scope) {\n throw new ScopeRuntimeNotConfiguredError()\n }\n\n return scope\n }\n}\n","import { ScopeCloseError } from './errors'\n\nimport { ScopeRuntime } from './runtime'\n\nimport type { CloseableScope, Scope } from './scope'\n\nimport type { CleanupFailureDiagnostic, MaybePromise, ScopeOutcome } from './types'\n\nexport type OutcomeClassifier<A> = (value: A) => ScopeOutcome\n\nexport type RunScopedOptions<A> = {\n readonly classify: OutcomeClassifier<A>\n readonly onCleanupFailure?: (diagnostic: CleanupFailureDiagnostic) => MaybePromise<void>\n}\n\nconst notifyCleanupFailure = async (\n observer: ((diagnostic: CleanupFailureDiagnostic) => MaybePromise<void>) | undefined,\n diagnostic: CleanupFailureDiagnostic\n): Promise<void> => {\n if (!observer) {\n return\n }\n\n try {\n await observer(diagnostic)\n } catch {\n // Cleanup diagnostics are best effort and never affect the primary result.\n }\n}\n\nexport const runScoped = async <A>(\n scope: CloseableScope,\n program: () => A | PromiseLike<A>,\n options: RunScopedOptions<Awaited<A>>\n): Promise<Awaited<A>> => {\n let value!: Awaited<A>\n\n let programFailed = false\n let programFailure: unknown\n\n try {\n value = await ScopeRuntime.run(scope as Scope, program)\n } catch (cause) {\n programFailed = true\n programFailure = cause\n }\n\n const outcome: ScopeOutcome = programFailed\n ? {\n status: 'failure',\n cause: programFailure\n }\n : options.classify(value)\n\n let cleanupFailed = false\n let cleanupFailure: unknown\n\n try {\n await scope.close(outcome)\n } catch (cause) {\n cleanupFailed = true\n cleanupFailure = cause\n }\n\n if (cleanupFailed) {\n const error =\n cleanupFailure instanceof ScopeCloseError\n ? cleanupFailure\n : new ScopeCloseError([cleanupFailure])\n\n await notifyCleanupFailure(options.onCleanupFailure, {\n outcome,\n error\n })\n\n cleanupFailure = error\n }\n\n if (programFailed) {\n throw programFailure\n }\n\n if (outcome.status === 'failure') {\n return value\n }\n\n if (cleanupFailed) {\n throw cleanupFailure\n }\n\n return value\n}\n","import { ResourceNotDisposableError, ScopeCloseError, ScopeClosedError } from './errors'\n\nimport { getDisposeFinalizer } from './disposable'\n\nimport { runScoped } from './internal'\n\nimport { ScopeRuntime } from './runtime'\n\nimport type { DisposableResource, MaybePromise, ScopeFinalizer, ScopeOutcome } from './types'\n\nexport interface Scope {\n addFinalizer(finalizer: ScopeFinalizer): void\n\n acquire<R>(\n acquire: () => MaybePromise<R>,\n release: (resource: R, outcome: ScopeOutcome) => MaybePromise<void>\n ): Promise<R>\n\n add<R extends DisposableResource>(resource: R): Promise<R>\n\n fork(): CloseableScope\n}\n\nexport interface CloseableScope extends Scope {\n close(outcome?: ScopeOutcome): Promise<void>\n}\n\nconst SCOPE_SUCCESS: ScopeOutcome = Object.freeze({ status: 'success' })\n\nclass ScopeImpl implements CloseableScope {\n private readonly children = new Set<ScopeImpl>()\n\n private readonly finalizers: ScopeFinalizer[] = []\n\n private closePromise: Promise<void> | undefined\n\n private closeOutcome: ScopeOutcome | undefined\n\n constructor(private parent?: ScopeImpl) {}\n\n fork(): CloseableScope {\n this.assertOpen()\n\n const child = new ScopeImpl(this)\n\n this.children.add(child)\n\n return child\n }\n\n addFinalizer(finalizer: ScopeFinalizer): void {\n this.assertOpen()\n\n this.finalizers.push(finalizer)\n }\n\n async acquire<R>(\n acquire: () => MaybePromise<R>,\n release: (resource: R, outcome: ScopeOutcome) => MaybePromise<void>\n ): Promise<R> {\n this.assertOpen()\n\n const resource = await acquire()\n\n try {\n this.addFinalizer((outcome) => release(resource, outcome))\n\n return resource\n } catch (scopeFailure) {\n try {\n await release(resource, this.closeOutcome ?? SCOPE_SUCCESS)\n } catch (releaseFailure) {\n throw new AggregateError(\n [scopeFailure, releaseFailure],\n 'Scope closed while acquiring a resource and immediate cleanup also failed'\n )\n }\n\n throw scopeFailure\n }\n }\n\n async add<R extends DisposableResource>(resource: R): Promise<R> {\n const finalizer = getDisposeFinalizer(resource)\n\n if (!finalizer) {\n throw new ResourceNotDisposableError()\n }\n\n try {\n this.addFinalizer(finalizer)\n\n return resource\n } catch (scopeFailure) {\n try {\n await finalizer(this.closeOutcome ?? SCOPE_SUCCESS)\n } catch (releaseFailure) {\n throw new AggregateError(\n [scopeFailure, releaseFailure],\n 'Scope closed while adding a disposable resource and cleanup also failed'\n )\n }\n\n throw scopeFailure\n }\n }\n\n close(outcome: ScopeOutcome = SCOPE_SUCCESS): Promise<void> {\n if (this.closePromise) {\n return this.closePromise\n }\n\n this.closeOutcome = outcome\n this.closePromise = ScopeRuntime.run(this, () => this.closeInternal(outcome))\n\n return this.closePromise\n }\n\n private async closeInternal(outcome: ScopeOutcome): Promise<void> {\n const failures: unknown[] = []\n\n const children = [...this.children]\n\n this.children.clear()\n\n for (let index = children.length - 1; index >= 0; index--) {\n const child = children[index]\n\n if (!child) {\n continue\n }\n\n try {\n await child.close(outcome)\n } catch (cause) {\n if (cause instanceof ScopeCloseError) {\n failures.push(...cause.causes)\n } else {\n failures.push(cause)\n }\n }\n }\n\n for (let index = this.finalizers.length - 1; index >= 0; index--) {\n const finalizer = this.finalizers[index]\n\n if (!finalizer) {\n continue\n }\n\n try {\n await finalizer(outcome)\n } catch (cause) {\n failures.push(cause)\n }\n }\n\n this.finalizers.length = 0\n\n this.detach()\n\n if (failures.length > 0) {\n throw new ScopeCloseError(failures)\n }\n }\n\n private detach(): void {\n const parent = this.parent\n\n if (!parent) {\n return\n }\n\n parent.children.delete(this)\n this.parent = undefined\n }\n\n private assertOpen(): void {\n if (this.closePromise) {\n throw new ScopeClosedError()\n }\n }\n}\n\nexport const Scope = {\n make(): CloseableScope {\n return new ScopeImpl()\n },\n\n current(): Scope {\n return ScopeRuntime.current()\n },\n\n provide<A>(scope: Scope, program: () => A): A {\n return ScopeRuntime.run(scope, program)\n },\n\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<never, Scope, unknown> {\n return ScopeRuntime.current()\n },\n\n /**\n * Run a program in a newly owned Scope.\n *\n * Scope is independent from `better-result`, so returned values—including\n * `Result.err`—close this Scope with a successful outcome. Result-aware\n * outcome classification belongs to `Runtime.run`.\n */\n run<A>(program: (scope: Scope) => A | PromiseLike<A>): Promise<Awaited<A>> {\n const scope = new ScopeImpl()\n\n return runScoped(scope, () => program(scope), {\n classify: () => SCOPE_SUCCESS\n })\n }\n} as const\n","import { Result } from 'better-result'\n\nimport type { Result as ResultType } from 'better-result'\n\nimport type { LayerDisposeError } from '../layer/errors'\n\nimport type { CleanupFailureDiagnostic, MaybePromise, ScopeOutcome } from '../scope'\n\nexport type RuntimeShutdownDiagnostic = {\n readonly outcome: ScopeOutcome\n readonly error: LayerDisposeError\n}\n\nexport type CleanupFailureObserver = (\n diagnostic: CleanupFailureDiagnostic | RuntimeShutdownDiagnostic\n) => MaybePromise<void>\n\nexport type RuntimeOptions = {\n readonly onCleanupFailure?: CleanupFailureObserver\n}\n\nconst isResultLike = (value: unknown): value is ResultType<unknown, unknown> =>\n typeof value === 'object' &&\n value !== null &&\n 'status' in value &&\n (value.status === 'ok' || value.status === 'error')\n\nexport const classifyRuntimeOutcome = (value: unknown): ScopeOutcome => {\n if (isResultLike(value) && Result.isError(value)) {\n return {\n status: 'failure',\n cause: value.error\n }\n }\n\n return {\n status: 'success'\n }\n}\n","import { ServiceRuntime } from '../service'\n\nimport type { AnyServiceToken } from '../service'\n\nimport { Scope, type CloseableScope } from '../scope'\nimport { runScoped } from '../scope/internal'\nimport { ScopeRuntime } from '../scope/runtime'\n\nimport {\n classifyRuntimeOutcome,\n type CleanupFailureObserver,\n type RuntimeOptions,\n type RuntimeShutdownDiagnostic\n} from '../runtime/outcome'\n\nimport { BuiltLayerDisposedError, LayerDisposeError, LayerRegistrationError } from './errors'\n\nimport type { LayerBackend } from './backend'\n\nimport type { AnyLayer, CompleteExecution, CompleteLayer, LayerProvided } from './inference'\n\nimport type { LayerProvider } from './types'\n\nimport type { ScopeOutcome } from '../scope'\n\n/**\n * Low-level Layer handle retained for adapter and test integrations.\n *\n * @deprecated Prefer `Runtime.make()` for the public managed runtime API.\n */\nexport interface BuiltLayer<Provided extends AnyServiceToken = AnyServiceToken> {\n readonly backend: LayerBackend\n\n run<A>(program: CompleteExecution<Provided, A>): Promise<Awaited<A>>\n\n dispose(outcome?: ScopeOutcome): Promise<void>\n}\n\nconst SCOPE_SUCCESS: ScopeOutcome = Object.freeze({ status: 'success' })\n\nconst normalizeDisposeCauses = (cause: unknown): readonly unknown[] => {\n if (cause instanceof AggregateError) {\n return [...cause.errors]\n }\n\n return [cause]\n}\n\nconst notifyShutdownFailure = async (\n observer: CleanupFailureObserver | undefined,\n diagnostic: RuntimeShutdownDiagnostic\n): Promise<void> => {\n if (!observer) {\n return\n }\n\n try {\n await observer(diagnostic)\n } catch {\n // Shutdown diagnostics are best effort and never affect the primary result.\n }\n}\n\nconst bindProviderToScope = (\n provider: LayerProvider,\n rootScope: CloseableScope\n): LayerProvider => ({\n service: provider.service,\n\n acquire: () =>\n ScopeRuntime.run(rootScope, async () => {\n if (!provider.release) {\n return await provider.acquire()\n }\n\n return await rootScope.acquire(\n () => provider.acquire(),\n (resource, outcome) => provider.release!(resource, outcome)\n )\n })\n})\n\nclass BuiltLayerImpl<Provided extends AnyServiceToken> implements BuiltLayer<Provided> {\n private disposePromise: Promise<void> | undefined\n\n private readonly executions = new Set<Promise<unknown>>()\n\n private state: 'active' | 'disposing' | 'disposed' = 'active'\n\n constructor(\n readonly backend: LayerBackend,\n private readonly rootScope: CloseableScope,\n private readonly onCleanupFailure: CleanupFailureObserver | undefined\n ) {}\n\n run<A>(program: CompleteExecution<Provided, A>): Promise<Awaited<A>> {\n this.assertActive()\n\n const executionScope = this.rootScope.fork()\n\n let resolveExecution!: (value: Awaited<A> | PromiseLike<Awaited<A>>) => void\n let rejectExecution!: (cause?: unknown) => void\n\n const execution = new Promise<Awaited<A>>((resolve, reject) => {\n resolveExecution = resolve\n rejectExecution = reject\n })\n\n this.executions.add(execution)\n\n void execution.then(\n () => {\n this.executions.delete(execution)\n },\n () => {\n this.executions.delete(execution)\n }\n )\n\n try {\n const running = this.runExecution(executionScope, program)\n\n void running.then(\n (value) => {\n resolveExecution(value)\n },\n (cause) => {\n rejectExecution(cause)\n }\n )\n } catch (cause) {\n rejectExecution(cause)\n }\n\n return execution\n }\n\n private runExecution<A>(\n executionScope: CloseableScope,\n program: CompleteExecution<Provided, A>\n ): Promise<Awaited<A>> {\n const options = this.onCleanupFailure\n ? {\n classify: classifyRuntimeOutcome,\n onCleanupFailure: this.onCleanupFailure\n }\n : {\n classify: classifyRuntimeOutcome\n }\n\n return runScoped(executionScope, () => ServiceRuntime.run(this.backend, program), options)\n }\n\n dispose(outcome: ScopeOutcome = SCOPE_SUCCESS): Promise<void> {\n if (this.disposePromise) {\n return this.disposePromise\n }\n\n this.state = 'disposing'\n\n const executions = [...this.executions]\n\n this.disposePromise = this.performDispose(executions, outcome)\n\n return this.disposePromise\n }\n\n private async performDispose(\n executions: readonly Promise<unknown>[],\n outcome: ScopeOutcome\n ): Promise<void> {\n const failures: unknown[] = []\n\n await Promise.allSettled(executions)\n\n try {\n await ServiceRuntime.run(this.backend, () => this.rootScope.close(outcome))\n } catch (cause) {\n failures.push(cause)\n }\n\n try {\n await this.backend.disposeAll()\n } catch (cause) {\n failures.push(cause)\n }\n\n this.state = 'disposed'\n\n if (failures.length > 0) {\n const error = new LayerDisposeError(failures.flatMap(normalizeDisposeCauses))\n\n await notifyShutdownFailure(this.onCleanupFailure, {\n outcome,\n error\n })\n\n throw error\n }\n }\n\n private assertActive(): void {\n if (this.state !== 'active') {\n throw new BuiltLayerDisposedError()\n }\n }\n}\n\n/**\n * Build a low-level Layer handle.\n *\n * @deprecated Prefer `Runtime.make()` for application code.\n */\nexport const buildLayer = async <L extends AnyLayer>(\n layer: CompleteLayer<L>,\n backend: LayerBackend,\n options: RuntimeOptions = {}\n): Promise<BuiltLayer<LayerProvided<L>>> => {\n const rootScope = Scope.make()\n let current: LayerProvider | undefined\n\n try {\n for (const provider of layer.providers) {\n current = provider\n\n await backend.register(bindProviderToScope(provider, rootScope))\n }\n } catch (registrationCause) {\n const outcome: ScopeOutcome = {\n status: 'failure',\n cause: registrationCause\n }\n const cleanupCauses: unknown[] = []\n\n try {\n await ServiceRuntime.run(backend, () => rootScope.close(outcome))\n } catch (cause) {\n cleanupCauses.push(cause)\n }\n\n try {\n await backend.disposeAll()\n } catch (cause) {\n cleanupCauses.push(cause)\n }\n\n if (cleanupCauses.length > 0) {\n const shutdownError = new LayerDisposeError(cleanupCauses.flatMap(normalizeDisposeCauses))\n\n await notifyShutdownFailure(options.onCleanupFailure, {\n outcome,\n error: shutdownError\n })\n }\n\n let cleanupCause: unknown\n\n if (cleanupCauses.length === 1) {\n cleanupCause = cleanupCauses[0]\n } else if (cleanupCauses.length > 1) {\n cleanupCause = new LayerDisposeError(cleanupCauses.flatMap(normalizeDisposeCauses))\n }\n\n throw new LayerRegistrationError(current?.service, registrationCause, cleanupCause)\n }\n\n return new BuiltLayerImpl<LayerProvided<L>>(backend, rootScope, options.onCleanupFailure)\n}\n","import { Result } from 'better-result'\n\nimport type { Result as ResultType } from 'better-result'\n\nimport type { EffectError, EffectRequirements, EffectResult, EffectSuccess } from './types'\n\ntype EffectInput<A, E, Requirements> =\n | EffectResult<A, E, Requirements>\n | PromiseLike<EffectResult<A, E, Requirements>>\n\ntype AnyEffectInput = EffectInput<any, any, any>\n\ntype PreserveAsync<Input, Output> = Input extends PromiseLike<unknown> ? Promise<Output> : Output\n\ntype MappedResult<Input, B> = EffectResult<B, EffectError<Input>, EffectRequirements<Input>>\n\ntype ErrorMappedResult<Input, E2> = EffectResult<\n EffectSuccess<Input>,\n E2,\n EffectRequirements<Input>\n>\n\ntype ChainedResult<First, Next> = EffectResult<\n EffectSuccess<Next>,\n EffectError<First> | EffectError<Next>,\n EffectRequirements<First> | EffectRequirements<Next>\n>\n\ntype ChainedOutput<First, Next> =\n First extends PromiseLike<unknown>\n ? Promise<ChainedResult<First, Next>>\n : Next extends PromiseLike<unknown>\n ? Promise<ChainedResult<First, Next>>\n : ChainedResult<First, Next>\n\ntype MapOperation<A, B> = {\n <Input>(effect: Input & EffectInput<A, any, any>): PreserveAsync<Input, MappedResult<Input, B>>\n}\n\ntype MapErrorOperation<E1, E2> = {\n <Input>(\n effect: Input & EffectInput<any, E1, any>\n ): PreserveAsync<Input, ErrorMappedResult<Input, E2>>\n}\n\ntype AndThenOperation<A, Next> = {\n <Input>(effect: Input & EffectInput<A, any, any>): ChainedOutput<Input, Next>\n}\n\nconst isPromiseLike = (value: unknown): value is PromiseLike<unknown> => {\n if ((typeof value !== 'object' && typeof value !== 'function') || value === null) {\n return false\n }\n\n return 'then' in value && typeof value.then === 'function'\n}\n\nconst mapResult = <A, B, E, Requirements>(\n result: EffectResult<A, E, Requirements>,\n fn: (value: A) => B\n): EffectResult<B, E, Requirements> => Result.map(result, fn) as EffectResult<B, E, Requirements>\n\nconst mapErrorResult = <A, E1, E2, Requirements>(\n result: EffectResult<A, E1, Requirements>,\n fn: (error: E1) => E2\n): EffectResult<A, E2, Requirements> =>\n Result.mapError(result, fn) as EffectResult<A, E2, Requirements>\n\nconst andThenResult = <A, B, E1, E2, Requirements1, Requirements2>(\n result: EffectResult<A, E1, Requirements1>,\n next: (value: A) => EffectInput<B, E2, Requirements2>\n):\n | EffectResult<B, E1 | E2, Requirements1 | Requirements2>\n | Promise<EffectResult<B, E1 | E2, Requirements1 | Requirements2>> => {\n const chained = Result.andThen(result, next as (value: A) => ResultType<B, E2>) as\n | EffectResult<B, E1 | E2, Requirements1 | Requirements2>\n | PromiseLike<EffectResult<B, E1 | E2, Requirements1 | Requirements2>>\n\n if (!isPromiseLike(chained)) {\n return chained\n }\n\n // Result.andThenAsync supplies better-result's Panic handling for a\n // Promise returned by the next operation after Result.andThen invokes it.\n return Result.andThenAsync(result, () => Promise.resolve(chained)) as Promise<\n EffectResult<B, E1 | E2, Requirements1 | Requirements2>\n >\n}\n\nexport function map<A, B>(fn: (value: A) => B): MapOperation<A, B>\nexport function map<Input, B>(\n effect: Input & AnyEffectInput,\n fn: (value: EffectSuccess<Input>) => B\n): PreserveAsync<Input, MappedResult<Input, B>>\nexport function map(first: unknown, second?: unknown): unknown {\n if (typeof first === 'function' && second === undefined) {\n return (effect: unknown) => map(effect as never, first as never)\n }\n\n const fn = second as (value: unknown) => unknown\n\n if (isPromiseLike(first)) {\n return Promise.resolve(first).then((result) =>\n mapResult(result as EffectResult<unknown, unknown, never>, fn)\n )\n }\n\n return mapResult(first as EffectResult<unknown, unknown, never>, fn)\n}\n\nexport function mapError<E1, E2>(fn: (error: E1) => E2): MapErrorOperation<E1, E2>\nexport function mapError<Input, E2>(\n effect: Input & AnyEffectInput,\n fn: (error: EffectError<Input>) => E2\n): PreserveAsync<Input, ErrorMappedResult<Input, E2>>\nexport function mapError(first: unknown, second?: unknown): unknown {\n if (typeof first === 'function' && second === undefined) {\n return (effect: unknown) => mapError(effect as never, first as never)\n }\n\n const fn = second as (error: unknown) => unknown\n\n if (isPromiseLike(first)) {\n return Promise.resolve(first).then((result) =>\n mapErrorResult(result as EffectResult<unknown, unknown, never>, fn)\n )\n }\n\n return mapErrorResult(first as EffectResult<unknown, unknown, never>, fn)\n}\n\nexport function andThen<A, Next extends AnyEffectInput>(\n next: (value: A) => Next\n): AndThenOperation<A, Next>\nexport function andThen<Input, Next extends AnyEffectInput>(\n effect: Input & AnyEffectInput,\n next: (value: EffectSuccess<Input>) => Next\n): ChainedOutput<Input, Next>\nexport function andThen(first: unknown, second?: unknown): unknown {\n if (typeof first === 'function' && second === undefined) {\n return (effect: unknown) => andThen(effect as never, first as never)\n }\n\n const next = second as (value: unknown) => EffectInput<unknown, unknown, never>\n\n if (isPromiseLike(first)) {\n return Promise.resolve(first).then((result) =>\n andThenResult(result as EffectResult<unknown, unknown, never>, next)\n )\n }\n\n return andThenResult(first as EffectResult<unknown, unknown, never>, next)\n}\n","import { Result } from 'better-result'\n\nimport type { Err, Result as ResultType, UnhandledException } from 'better-result'\n\nimport { Scope } from '../scope'\n\nimport type { DisposableResource, MaybePromise, ScopeOutcome } from '../scope'\n\nimport type { EffectFromGenerator, EffectYield } from './types'\n\nimport { andThen, map, mapError } from './combinators'\n\ntype AnyResult = ResultType<any, any>\n\ntype RuntimeGenerator =\n | (() => Generator<Err<never, unknown>, AnyResult, unknown>)\n | (() => AsyncGenerator<Err<never, unknown>, AnyResult, unknown>)\n\ntype EffectGenerator =\n | (() => Generator<EffectYield, AnyResult, unknown>)\n | (() => AsyncGenerator<EffectYield, AnyResult, unknown>)\n\n/**\n * Compose better-result operations while preserving Service requirements in\n * a phantom type channel.\n */\nexport function gen<Yield extends EffectYield, Returned extends AnyResult>(\n body: () => Generator<Yield, Returned, unknown>\n): EffectFromGenerator<Yield, Returned>\n\nexport function gen<Yield extends EffectYield, Returned extends AnyResult>(\n body: () => AsyncGenerator<Yield, Returned, unknown>\n): Promise<EffectFromGenerator<Yield, Returned>>\n\nexport function gen(body: EffectGenerator): AnyResult | Promise<AnyResult> {\n /*\n * ServiceRequirement is phantom. The Service iterator returns its resolved\n * instance without yielding a marker, so Result.gen still receives only\n * the Err values that exist at runtime.\n */\n return (Result.gen as unknown as (body: RuntimeGenerator) => AnyResult | Promise<AnyResult>)(\n body as RuntimeGenerator\n )\n}\n\n/**\n * Acquire a resource in the current Scope and register its release callback.\n *\n * Acquisition failures are represented in the Effect Result error channel;\n * release failures remain owned by Scope cleanup.\n */\nexport function acquireRelease<R>(\n acquire: () => MaybePromise<R>,\n release: (resource: R, outcome: ScopeOutcome) => MaybePromise<void>\n): AsyncGenerator<Err<never, UnhandledException>, R, unknown> {\n const scope = Scope.current()\n\n return Result.await(Result.tryPromise(() => scope.acquire(acquire, release)))\n}\n\n/**\n * Register an already-acquired disposable resource in the current Scope.\n *\n * Registration failures are represented in the Effect Result error channel;\n * disposal failures remain owned by Scope cleanup.\n */\nexport function add<R extends DisposableResource>(\n resource: R\n): AsyncGenerator<Err<never, UnhandledException>, R, unknown> {\n const scope = Scope.current()\n\n return Result.await(Result.tryPromise(() => scope.add(resource)))\n}\n\nexport const Effect = {\n gen,\n acquireRelease,\n add,\n map,\n mapError,\n andThen\n} as const\n","type Unary<A, B> = (value: A) => B\n\n/** Compose a value through a sequence of unary functions. */\nexport function pipe<A>(value: A): A\nexport function pipe<A, B>(value: A, ab: Unary<A, B>): B\nexport function pipe<A, B, C>(value: A, ab: Unary<A, B>, bc: Unary<B, C>): C\nexport function pipe<A, B, C, D>(value: A, ab: Unary<A, B>, bc: Unary<B, C>, cd: Unary<C, D>): D\nexport function pipe<A, B, C, D, E>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>\n): E\nexport function pipe<A, B, C, D, E, F>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>,\n ef: Unary<E, F>\n): F\nexport function pipe<A, B, C, D, E, F, G>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>,\n ef: Unary<E, F>,\n fg: Unary<F, G>\n): G\nexport function pipe<A, B, C, D, E, F, G, H>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>,\n ef: Unary<E, F>,\n fg: Unary<F, G>,\n gh: Unary<G, H>\n): H\nexport function pipe<A, B, C, D, E, F, G, H, I>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>,\n ef: Unary<E, F>,\n fg: Unary<F, G>,\n gh: Unary<G, H>,\n hi: Unary<H, I>\n): I\nexport function pipe<A, B, C, D, E, F, G, H, I, J>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>,\n ef: Unary<E, F>,\n fg: Unary<F, G>,\n gh: Unary<G, H>,\n hi: Unary<H, I>,\n ij: Unary<I, J>\n): J\nexport function pipe<A, B, C, D, E, F, G, H, I, J, K>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>,\n ef: Unary<E, F>,\n fg: Unary<F, G>,\n gh: Unary<G, H>,\n hi: Unary<H, I>,\n ij: Unary<I, J>,\n jk: Unary<J, K>\n): K\nexport function pipe(\n value: unknown,\n ...operations: ReadonlyArray<Unary<unknown, unknown>>\n): unknown {\n return operations.reduce((current, operation) => operation(current), value)\n}\n","import { TaggedError } from 'better-result'\n\nexport class ResourceReleaseFailure extends TaggedError('ResourceReleaseFailure')<{\n readonly resource: string\n readonly cause: unknown\n readonly message: string\n}> {}\n","import { Result, type Result as ResultType, type UnhandledException } from 'better-result'\n\nimport { ResourceReleaseFailure } from './errors'\n\nimport { disposeResource } from '../scope/disposable'\n\nexport { disposeResource }\n\nimport type { AsyncResult, MaybePromise, ReleaseFailureObserver, ReleaseOutcome } from './types'\n\nconst toReleaseFailure = (resource: string, cause: unknown): ResourceReleaseFailure =>\n new ResourceReleaseFailure({\n resource,\n cause,\n message: `Failed to release resource: ${resource}`\n })\n\nexport const runResult = async <T, E>(\n operation: () => AsyncResult<T, E>\n): Promise<ResultType<T, E | UnhandledException>> => {\n const execution = await Result.tryPromise(() => Promise.resolve(operation()))\n\n return execution.andThen((result) => result)\n}\n\nconst normalizeReleaseOutcome = (\n name: string,\n outcome: ReleaseOutcome\n): ResultType<void, ResourceReleaseFailure> => {\n if (outcome === undefined) {\n return Result.ok()\n }\n\n return outcome.mapError((cause) => toReleaseFailure(name, cause))\n}\n\nexport const runRelease = async <R>(\n name: string,\n resource: R,\n release: (resource: R) => MaybePromise<ReleaseOutcome>\n): Promise<ResultType<void, ResourceReleaseFailure>> => {\n const execution = await Result.tryPromise({\n try: () => Promise.resolve(release(resource)),\n catch: (cause) => toReleaseFailure(name, cause)\n })\n\n return execution.andThen((outcome) => normalizeReleaseOutcome(name, outcome))\n}\n\nconst notifyReleaseFailure = async (\n observer: ReleaseFailureObserver | undefined,\n\n failure: ResourceReleaseFailure\n): Promise<void> => {\n if (!observer) {\n return\n }\n\n try {\n await observer(failure)\n } catch {\n /*\n * Diagnostics must never replace\n * the actual operation error.\n */\n }\n}\n\nexport const combineUseAndRelease = async <A, E>(\n used: ResultType<A, E>,\n\n released: ResultType<void, ResourceReleaseFailure>,\n\n onReleaseFailure?: ReleaseFailureObserver\n): Promise<ResultType<A, E | ResourceReleaseFailure>> => {\n if (Result.isError(used)) {\n if (Result.isError(released)) {\n await notifyReleaseFailure(onReleaseFailure, released.error)\n }\n\n return Result.err<A, E | ResourceReleaseFailure>(used.error)\n }\n\n if (Result.isError(released)) {\n await notifyReleaseFailure(onReleaseFailure, released.error)\n\n return Result.err<A, E | ResourceReleaseFailure>(released.error)\n }\n\n return Result.ok<A, E | ResourceReleaseFailure>(used.value)\n}\n","import { Result, type Result as ResultType, type UnhandledException } from 'better-result'\n\nimport { Scope } from '../scope'\n\nimport { ResourceReleaseFailure } from './errors'\n\nimport { combineUseAndRelease, disposeResource, runRelease, runResult } from './internal'\n\nimport type { AcquireUseReleaseOptions } from './types'\n\nconst acquireUseRelease = <R, A, AcquireError, UseError>({\n name,\n acquire,\n use,\n release = disposeResource,\n onReleaseFailure\n}: AcquireUseReleaseOptions<R, A, AcquireError, UseError>): Promise<\n ResultType<A, AcquireError | UseError | UnhandledException | ResourceReleaseFailure>\n> =>\n Result.gen(async function* () {\n const resource = yield* Result.await(runResult(acquire))\n\n const scope = Scope.make()\n\n let released: ResultType<void, ResourceReleaseFailure> = Result.ok()\n\n scope.addFinalizer(async () => {\n released = await runRelease(name, resource, release)\n })\n\n const used = await runResult(() => use(resource))\n\n await scope.close()\n\n return await combineUseAndRelease(used, released, onReleaseFailure)\n })\n\nexport const Resource = {\n acquireUseRelease\n} as const\n","import {\n buildLayer,\n type AnyLayer,\n type BuiltLayer,\n type CompleteLayer,\n type LayerProvided,\n type LayerBackend\n} from '../layer'\n\nimport type { CompleteExecution } from '../layer/inference'\n\nimport type { AnyServiceToken } from '../service'\n\nimport { classifyRuntimeOutcome, type RuntimeOptions } from './outcome'\n\nimport type { ScopeOutcome } from '../scope'\n\nexport class Runtime<Provided extends AnyServiceToken = AnyServiceToken> {\n private constructor(private readonly built: BuiltLayer<Provided>) {}\n\n /** Create a long-lived Runtime that owns its Layer resources. */\n static async make<L extends AnyLayer>(\n layer: CompleteLayer<L>,\n backend: LayerBackend,\n options: RuntimeOptions = {}\n ): Promise<Runtime<LayerProvided<L>>> {\n const built = await buildLayer(layer, backend, options)\n\n return new Runtime<LayerProvided<L>>(built)\n }\n\n /** Run one program and dispose its Layer resources before resolving. */\n static async run<A, L extends AnyLayer>(\n layer: CompleteLayer<L>,\n backend: LayerBackend,\n program: CompleteExecution<LayerProvided<L>, A>,\n options: RuntimeOptions = {}\n ): Promise<Awaited<A>> {\n const runtime = await Runtime.make(layer, backend, options)\n\n let value!: Awaited<A>\n let executionFailed = false\n let executionFailure: unknown\n let programOutcome: ScopeOutcome | undefined\n\n try {\n value = await runtime.runUnchecked(async () => {\n try {\n const programValue = await program()\n\n programOutcome = classifyRuntimeOutcome(programValue)\n\n return programValue\n } catch (cause) {\n programOutcome = {\n status: 'failure',\n cause\n }\n\n throw cause\n }\n })\n } catch (cause) {\n executionFailed = true\n executionFailure = cause\n }\n\n const outcome: ScopeOutcome =\n programOutcome ??\n ({\n status: 'failure',\n cause: executionFailure\n } as const)\n\n try {\n await runtime.disposeWithOutcome(outcome)\n } catch (shutdownFailure) {\n if (!executionFailed && outcome.status === 'success') {\n throw shutdownFailure\n }\n }\n\n if (executionFailed) {\n throw executionFailure\n }\n\n return value\n }\n\n /** Run one execution in this Runtime's child Scope. */\n run<A>(program: CompleteExecution<Provided, A>): Promise<Awaited<A>> {\n return this.built.run(program)\n }\n\n private runUnchecked<A>(program: () => A | PromiseLike<A>): Promise<Awaited<A>> {\n return this.built.run(program as CompleteExecution<Provided, A>)\n }\n\n /** Stop new executions and release the Runtime's Layer resources. */\n dispose(): Promise<void> {\n return this.built.dispose()\n }\n\n private disposeWithOutcome(outcome: ScopeOutcome): Promise<void> {\n return this.built.dispose(outcome)\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["storage","Constructor","SCOPE_SUCCESS","SCOPE_SUCCESS","next"],"sources":["../src/service/runtime.ts","../src/service/service.ts","../src/layer/internal.ts","../src/layer/layer.ts","../src/scope/errors.ts","../src/scope/disposable.ts","../src/scope/runtime.ts","../src/scope/internal.ts","../src/scope/scope.ts","../src/effect/combinators.ts","../src/effect/effect.ts","../src/function/pipe.ts","../src/resource/errors.ts","../src/resource/internal.ts","../src/resource/resource.ts","../src/runtime/outcome.ts","../src/layer/runtime.ts","../src/runtime/runtime.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport { ServiceRuntimeNotConfiguredError } from './errors'\n\nimport type { AnyServiceToken } from './types'\n\n/** Resolves class-backed Service tokens for a runtime execution. */\nexport interface ServiceResolver {\n /** Resolve a token to its corresponding Service instance. */\n resolve<T extends AnyServiceToken>(token: T): InstanceType<T> | PromiseLike<InstanceType<T>>\n}\n\nconst storage = new AsyncLocalStorage<ServiceResolver>()\n\n/** Provides the resolver context used by Service tokens during execution. */\nexport class ServiceRuntime {\n /**\n * Run a callback with a resolver available to `yield* Service` expressions.\n *\n * The context is scoped to the callback and is restored afterward.\n *\n * @example\n * ```ts\n * const value = ServiceRuntime.run(resolver, () => {\n * return ServiceRuntime.resolve(Database)\n * })\n * ```\n */\n static run<A>(resolver: ServiceResolver, program: () => A): A {\n return storage.run(resolver, program)\n }\n\n /** Return the resolver active in the current execution context. */\n static current(): ServiceResolver {\n const resolver = storage.getStore()\n\n if (!resolver) {\n throw new ServiceRuntimeNotConfiguredError()\n }\n\n return resolver\n }\n\n /** Resolve a Service token using the active resolver. */\n static async resolve<T extends AnyServiceToken>(token: T): Promise<InstanceType<T>> {\n const resolver = ServiceRuntime.current()\n\n return await resolver.resolve(token)\n }\n}\n","import { ServiceRuntime } from './runtime'\n\nimport type { ServiceRequirement } from '../effect/types'\n\nimport type { ServiceToken } from './types'\n\ntype ServiceTagLiteral<Tag extends string> = string extends Tag\n ? never\n : Tag extends ''\n ? never\n : Tag\n\n/**\n * Declare a class-backed Service with a stable string-literal identity.\n *\n * The returned class is simultaneously the implementation type, the runtime\n * dependency token, and the value yielded by `yield*` in an Effect generator.\n * The explicit self type preserves exact instance inference, while the second\n * call captures the tag as a literal for Layer composition and diagnostics.\n *\n * @example\n * ```ts\n * class Database extends Service<Database>()('Database') {\n * query(): string {\n * return 'ok'\n * }\n * }\n *\n * const database = yield* Database\n * database.query()\n * ```\n *\n * @typeParam Self The instance type implemented by the declared Service.\n */\nexport function Service<Self>() {\n return function <const Tag extends string>(tag: ServiceTagLiteral<Tag>) {\n if (tag.length === 0) {\n throw new TypeError('Service tags must not be empty')\n }\n\n abstract class BaseService {\n /** The stable logical identity used by Layers and resolver backends. */\n static readonly serviceTag: Tag = tag\n\n /**\n * Type-check a structural implementation of this Service.\n *\n * This is an identity helper. It returns the supplied value unchanged\n * and does not invoke a constructor or modify its prototype.\n *\n * @example\n * ```ts\n * class Database extends Service<Database>()('Database') {\n * query(sql: string): string {\n * return sql\n * }\n * }\n *\n * const database = Database.of({\n * query: (sql) => `Result: ${sql}`\n * })\n *\n * database.query('SELECT 1')\n * // 'Result: SELECT 1'\n * // database is the original object, not an instance of Database\n * ```\n */\n static of(this: void, implementation: Self): Self {\n return implementation\n }\n\n /** Resolve this Service from the resolver active in the current runtime. */\n // oxlint-disable-next-line require-yield\n static async *[Symbol.asyncIterator](\n this: ServiceToken<Tag, Self>\n ): AsyncGenerator<ServiceRequirement<ServiceToken<Tag, Self>>, Self, unknown> {\n return await ServiceRuntime.resolve(this)\n }\n }\n\n return BaseService\n }\n}\n","import { LayerGeneratorYieldError } from './errors'\n\nimport type { ServiceRequirement } from '../effect/types'\nimport type { AnyServiceToken, ServiceClass } from '../service'\n\nimport type { LayerGenerator } from './types'\n\nexport const runLayerGenerator = async <\n S extends ServiceClass<any, any>,\n Yield extends ServiceRequirement<AnyServiceToken>\n>(\n service: S,\n factory: LayerGenerator<S, Yield>\n): Promise<InstanceType<S>> => {\n const iterator = factory()\n\n const state = await iterator.next()\n\n if (!state.done) {\n try {\n await iterator.return(undefined as InstanceType<S>)\n } finally {\n // oxlint-disable-next-line no-unsafe-finally\n throw new LayerGeneratorYieldError(service)\n }\n }\n\n return state.value\n}\n","import type { ServiceRequirement } from '../effect/types'\nimport type { AnyServiceToken, ServiceClass, ServiceRequirements } from '../service'\nimport type { ScopeOutcome } from '../scope'\nimport type { MaybePromise } from '../utils/types'\n\nimport { DuplicateServiceError, ServiceTagCollisionError } from './errors'\n\nimport { runLayerGenerator } from './internal'\n\nimport type {\n LayerGenerator,\n LayerGeneratorRequirements,\n LayerRegistration,\n LayerSpec\n} from './types'\n\nimport type { AnyLayerSpec } from './types'\n\nimport type { OverrideLayerCollisions, OverrideLayerSpecs } from './inference'\n\ndeclare const LayerTypeId: unique symbol\ndeclare const LayerCollisionTypeId: unique symbol\n\ninterface LayerProvider extends LayerRegistration {\n readonly release?: (instance: unknown, outcome: ScopeOutcome) => MaybePromise<void>\n}\n\n/** A Service class whose constructor can be called without arguments. */\ntype DefaultConstructibleServiceClass<Tag extends string = string, Instance = any> = ServiceClass<\n Tag,\n Instance\n> &\n (new () => Instance)\n\n/**\n * Declarative collection of Service providers.\n *\n * A Layer describes how to acquire implementations; it does not execute\n * providers until a `Runtime` is created. Use `merge` to compose distinct\n * providers and `override` when replacing an existing provider intentionally.\n *\n * @example\n * ```ts\n * const AppLive = Layer.merge(\n * Layer.succeed(Database, database),\n * Layer.make(UserRepository)\n * )\n *\n * const runtime = await Runtime.make(AppLive, backend)\n * ```\n */\nexport class Layer<\n Specs extends AnyLayerSpec = AnyLayerSpec,\n Collisions extends AnyServiceToken = never\n> {\n declare readonly [LayerTypeId]: Specs\n declare readonly [LayerCollisionTypeId]: Collisions\n\n /** The provider registrations retained by this Layer. */\n readonly providers: readonly LayerProvider[]\n\n private constructor(providers: readonly LayerProvider[]) {\n this.providers = Object.freeze([...providers])\n }\n\n /**\n * Create a Layer that lazily acquires a Service instance.\n *\n * When the acquire callback is omitted, the Service must be constructible\n * without required constructor arguments and is instantiated with `new`.\n * Supplying an acquire callback remains available for custom construction.\n *\n * The acquire callback runs when the provider is first resolved by a\n * Runtime. Dependencies declared by Effect-returning Service methods are\n * tracked in the Layer's type.\n *\n * @example\n * ```ts\n * const DatabaseLive = Layer.make(Database)\n * ```\n *\n * @example\n * ```ts\n * const DatabaseLive = Layer.make(Database, () => new Database(config))\n * ```\n */\n static make<S extends DefaultConstructibleServiceClass<any, any>>(\n service: S\n ): Layer<LayerSpec<S, ServiceRequirements<S>>>\n\n static make<S extends ServiceClass<any, any>>(\n service: S,\n acquire: () => MaybePromise<InstanceType<S>>\n ): Layer<LayerSpec<S, ServiceRequirements<S>>>\n\n static make<S extends ServiceClass<any, any>>(\n service: S,\n acquire?: () => MaybePromise<InstanceType<S>>\n ): Layer<LayerSpec<S, ServiceRequirements<S>>> {\n const defaultAcquire = (): InstanceType<S> => {\n const Constructor = service as new () => InstanceType<S>\n\n return new Constructor()\n }\n\n return new Layer([\n {\n service,\n acquire: acquire ?? defaultAcquire\n }\n ])\n }\n\n /**\n * Create a Layer from an already-constructed Service instance.\n *\n * The instance is returned as-is whenever the Service is resolved.\n *\n * @example\n * ```ts\n * const DatabaseLive = Layer.succeed(Database, database)\n * ```\n */\n static succeed<S extends ServiceClass<any, any>>(\n service: S,\n instance: InstanceType<S>\n ): Layer<LayerSpec<S, ServiceRequirements<S>>> {\n return Layer.make(service, () => instance)\n }\n\n /**\n * Define a provider with Runtime-root cleanup.\n *\n * The release callback intentionally keeps its compatibility-friendly\n * one-argument shape and runs when the owning Runtime is disposed. Use\n * `scopedGen` when acquisition needs contextual Services or cleanup needs\n * `ScopeOutcome`.\n *\n * @example\n * ```ts\n * const DatabaseLive = Layer.scoped(\n * Database,\n * () => openDatabase(),\n * (database) => database.close()\n * )\n * ```\n */\n static scoped<S extends ServiceClass<any, any>>(\n service: S,\n acquire: () => MaybePromise<InstanceType<S>>,\n release: (instance: InstanceType<S>) => MaybePromise<void>\n ): Layer<LayerSpec<S, ServiceRequirements<S>>> {\n return new Layer([\n {\n service,\n acquire,\n\n release: (instance) => release(instance as InstanceType<S>)\n }\n ])\n }\n\n /**\n * Define a provider whose acquisition can yield contextual Services.\n *\n * The release callback receives the acquired instance and the final\n * `ScopeOutcome` selected by the owning Runtime.\n *\n * @example\n * ```ts\n * const RepositoryLive = Layer.scopedGen(\n * UserRepository,\n * async function* () {\n * const database = yield* Database\n * return new UserRepository(database)\n * },\n * (repository, outcome) => repository.close(outcome)\n * )\n * ```\n */\n static scopedGen<\n S extends ServiceClass<any, any>,\n Yield extends ServiceRequirement<AnyServiceToken>\n >(\n service: S,\n factory: LayerGenerator<S, Yield>,\n release: (instance: InstanceType<S>, outcome: ScopeOutcome) => MaybePromise<void>\n ): Layer<LayerSpec<S, LayerGeneratorRequirements<S, Yield>>> {\n return new Layer([\n {\n service,\n acquire: () => runLayerGenerator(service, factory),\n release: (instance, outcome) => release(instance as InstanceType<S>, outcome)\n }\n ])\n }\n\n /**\n * Define a provider whose acquisition can yield contextual Services.\n *\n * Unlike `scopedGen`, this variant has no release callback. Use it for\n * providers whose lifetime is managed elsewhere or that need no cleanup.\n *\n * @example\n * ```ts\n * const RepositoryLive = Layer.gen(UserRepository, async function* () {\n * const database = yield* Database\n * return new UserRepository(database)\n * })\n * ```\n */\n static gen<S extends ServiceClass<any, any>, Yield extends ServiceRequirement<AnyServiceToken>>(\n service: S,\n factory: LayerGenerator<S, Yield>\n ): Layer<LayerSpec<S, LayerGeneratorRequirements<S, Yield>>> {\n return Layer.make(service, () => runLayerGenerator(service, factory))\n }\n\n /**\n * Compose Layers without replacing providers.\n *\n * Each Service tag may appear only once. Duplicate tags are rejected at\n * runtime; use `override` when replacement is intentional.\n *\n * @example\n * ```ts\n * const AppLive = Layer.merge(DatabaseLive, RepositoryLive)\n * ```\n */\n static merge<const Layers extends readonly Layer<any, any>[]>(\n ...layers: Layers\n ): Layer<\n Layers[number] extends Layer<infer Specs, any> ? Specs : never,\n Layers[number] extends Layer<any, infer Collisions> ? Collisions : never\n > {\n const providers = new Map<string, LayerProvider>()\n\n for (const layer of layers) {\n for (const provider of layer.providers) {\n const service = provider.service\n\n const existing = providers.get(service.serviceTag)\n\n if (existing) {\n if (existing.service !== service) {\n throw new ServiceTagCollisionError(existing.service, service)\n }\n\n throw new DuplicateServiceError(service)\n }\n\n providers.set(service.serviceTag, provider)\n }\n }\n\n return new Layer([...providers.values()])\n }\n\n /**\n * Replace providers in a base Layer, using tag identity and compatible\n * instance contracts.\n *\n * Overrides are applied from left to right; the last compatible provider for\n * a tag wins. Incompatible same-tag replacements remain visible as a type\n * diagnostic and cannot be passed as a complete Layer.\n *\n * @example\n * ```ts\n * const TestLive = Layer.override(AppLive, Layer.succeed(Database, fakeDb))\n * ```\n */\n static override<Base extends Layer<any, any>, const Overrides extends readonly Layer<any, any>[]>(\n base: Base,\n ...overrides: Overrides\n ): Layer<\n OverrideLayerSpecs<Base extends Layer<infer Specs, any> ? Specs : never, Overrides>,\n | (Base extends Layer<any, infer Collisions> ? Collisions : never)\n | (Overrides[number] extends Layer<any, infer Collisions> ? Collisions : never)\n | OverrideLayerCollisions<Base extends Layer<infer Specs, any> ? Specs : never, Overrides>\n > {\n const providers = new Map<string, LayerProvider>()\n\n for (const provider of base.providers) {\n providers.set(provider.service.serviceTag, provider)\n }\n\n for (const layer of overrides) {\n for (const provider of layer.providers) {\n providers.set(provider.service.serviceTag, provider)\n }\n }\n\n return new Layer([...providers.values()]) as Layer<\n OverrideLayerSpecs<Base extends Layer<infer Specs, any> ? Specs : never, Overrides>,\n | (Base extends Layer<any, infer Collisions> ? Collisions : never)\n | (Overrides[number] extends Layer<any, infer Collisions> ? Collisions : never)\n | OverrideLayerCollisions<Base extends Layer<infer Specs, any> ? Specs : never, Overrides>\n >\n }\n}\n","/** Thrown when Scope context is accessed outside an active Scope execution. */\nexport class ScopeRuntimeNotConfiguredError extends Error {\n constructor() {\n super('No Scope is available in the current execution context')\n\n this.name = 'ScopeRuntimeNotConfiguredError'\n }\n}\n\n/** Thrown when a resource or finalizer is added after Scope closure begins. */\nexport class ScopeClosedError extends Error {\n constructor() {\n super('Cannot add resources or finalizers to a closed Scope')\n\n this.name = 'ScopeClosedError'\n }\n}\n\n/** Aggregates finalizer failures encountered while closing a Scope. */\nexport class ScopeCloseError extends Error {\n constructor(readonly causes: readonly unknown[]) {\n super(\n `Failed to close Scope (${causes.length} finalizer${causes.length === 1 ? '' : 's'} failed)`\n )\n\n this.name = 'ScopeCloseError'\n }\n}\n\n/** Thrown when a value has neither Symbol.dispose nor Symbol.asyncDispose. */\nexport class ResourceNotDisposableError extends Error {\n constructor() {\n super('Resource does not implement Symbol.dispose or Symbol.asyncDispose')\n\n this.name = 'ResourceNotDisposableError'\n }\n}\n","import type { ScopeFinalizer } from './types'\n\nconst SCOPE_SUCCESS = { status: 'success' } as const\n\ntype DisposableCandidate = {\n [Symbol.dispose]?: unknown\n\n [Symbol.asyncDispose]?: unknown\n}\n\n/** Return a Scope finalizer for a value's async or sync disposal protocol. */\nexport const getDisposeFinalizer = (resource: unknown): ScopeFinalizer | undefined => {\n const candidate = Object(resource) as DisposableCandidate\n const asyncDispose = candidate[Symbol.asyncDispose]\n\n if (typeof asyncDispose === 'function') {\n return () => asyncDispose.call(resource)\n }\n\n const dispose = candidate[Symbol.dispose]\n\n if (typeof dispose === 'function') {\n return () => dispose.call(resource)\n }\n\n return undefined\n}\n\n/** Dispose a value immediately when it implements a disposal protocol. */\nexport const disposeResource = (resource: unknown): void | PromiseLike<void> => {\n const finalizer = getDisposeFinalizer(resource)\n\n return finalizer?.(SCOPE_SUCCESS)\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport { ScopeRuntimeNotConfiguredError } from './errors'\n\nimport type { Scope } from './scope'\n\nconst storage = new AsyncLocalStorage<Scope>()\n\n/** Bridges the current Scope through async execution context. */\nexport class ScopeRuntime {\n /** Supply a Scope while invoking a callback. */\n static run<A>(scope: Scope, program: () => A): A {\n return storage.run(scope, program)\n }\n\n /** Return the Scope active in the current execution context. */\n static current(): Scope {\n const scope = storage.getStore()\n\n if (!scope) {\n throw new ScopeRuntimeNotConfiguredError()\n }\n\n return scope\n }\n}\n","import { ScopeCloseError } from './errors'\n\nimport { ScopeRuntime } from './runtime'\n\nimport type { CloseableScope, Scope } from './scope'\n\nimport type { CleanupFailureDiagnostic, MaybePromise, ScopeOutcome } from './types'\n\nexport type OutcomeClassifier<A> = (value: A) => ScopeOutcome\n\nexport type RunScopedOptions<A> = {\n readonly classify: OutcomeClassifier<A>\n readonly onCleanupFailure?: (diagnostic: CleanupFailureDiagnostic) => MaybePromise<void>\n}\n\nconst notifyCleanupFailure = async (\n observer: ((diagnostic: CleanupFailureDiagnostic) => MaybePromise<void>) | undefined,\n diagnostic: CleanupFailureDiagnostic\n): Promise<void> => {\n if (!observer) {\n return\n }\n\n try {\n await observer(diagnostic)\n } catch {\n // Cleanup diagnostics are best effort and never affect the primary result.\n }\n}\n\nexport const runScoped = async <A>(\n scope: CloseableScope,\n program: () => A | PromiseLike<A>,\n options: RunScopedOptions<Awaited<A>>\n): Promise<Awaited<A>> => {\n let value!: Awaited<A>\n\n let programFailed = false\n let programFailure: unknown\n\n try {\n value = await ScopeRuntime.run(scope as Scope, program)\n } catch (cause) {\n programFailed = true\n programFailure = cause\n }\n\n const outcome: ScopeOutcome = programFailed\n ? {\n status: 'failure',\n cause: programFailure\n }\n : options.classify(value)\n\n let cleanupFailed = false\n let cleanupFailure: unknown\n\n try {\n await scope.close(outcome)\n } catch (cause) {\n cleanupFailed = true\n cleanupFailure = cause\n }\n\n if (cleanupFailed) {\n const error =\n cleanupFailure instanceof ScopeCloseError\n ? cleanupFailure\n : new ScopeCloseError([cleanupFailure])\n\n await notifyCleanupFailure(options.onCleanupFailure, {\n outcome,\n error\n })\n\n cleanupFailure = error\n }\n\n if (programFailed) {\n throw programFailure\n }\n\n if (outcome.status === 'failure') {\n return value\n }\n\n if (cleanupFailed) {\n throw cleanupFailure\n }\n\n return value\n}\n","import { ResourceNotDisposableError, ScopeCloseError, ScopeClosedError } from './errors'\n\nimport { getDisposeFinalizer } from './disposable'\n\nimport { runScoped } from './internal'\n\nimport { ScopeRuntime } from './runtime'\n\nimport type { DisposableResource, MaybePromise, ScopeFinalizer, ScopeOutcome } from './types'\n\n/**\n * Non-owning lifecycle context for finalizers and child Scopes.\n *\n * A Scope can register cleanup and create children, but it cannot close\n * itself. Use `Scope.make()` or `Scope.run()` when your code owns the Scope.\n */\nexport interface Scope {\n /** Register a finalizer that runs when the owning Scope closes. */\n addFinalizer(finalizer: ScopeFinalizer): void\n\n /** Acquire a resource and register its outcome-aware release callback. */\n acquire<R>(\n acquire: () => MaybePromise<R>,\n release: (resource: R, outcome: ScopeOutcome) => MaybePromise<void>\n ): Promise<R>\n\n /** Register an already-acquired disposable resource. */\n add<R extends DisposableResource>(resource: R): Promise<R>\n\n /** Create a child Scope owned by this Scope. */\n fork(): CloseableScope\n}\n\n/** A Scope whose owner is responsible for calling `close()`. */\nexport interface CloseableScope extends Scope {\n /** Close the Scope and run children and finalizers in child-first LIFO order. */\n close(outcome?: ScopeOutcome): Promise<void>\n}\n\nconst SCOPE_SUCCESS: ScopeOutcome = Object.freeze({ status: 'success' })\n\nclass ScopeImpl implements CloseableScope {\n private readonly children = new Set<ScopeImpl>()\n\n private readonly finalizers: ScopeFinalizer[] = []\n\n private closePromise: Promise<void> | undefined\n\n private closeOutcome: ScopeOutcome | undefined\n\n constructor(private parent?: ScopeImpl) {}\n\n fork(): CloseableScope {\n this.assertOpen()\n\n const child = new ScopeImpl(this)\n\n this.children.add(child)\n\n return child\n }\n\n addFinalizer(finalizer: ScopeFinalizer): void {\n this.assertOpen()\n\n this.finalizers.push(finalizer)\n }\n\n async acquire<R>(\n acquire: () => MaybePromise<R>,\n release: (resource: R, outcome: ScopeOutcome) => MaybePromise<void>\n ): Promise<R> {\n this.assertOpen()\n\n const resource = await acquire()\n\n try {\n this.addFinalizer((outcome) => release(resource, outcome))\n\n return resource\n } catch (scopeFailure) {\n try {\n await release(resource, this.closeOutcome ?? SCOPE_SUCCESS)\n } catch (releaseFailure) {\n throw new AggregateError(\n [scopeFailure, releaseFailure],\n 'Scope closed while acquiring a resource and immediate cleanup also failed'\n )\n }\n\n throw scopeFailure\n }\n }\n\n async add<R extends DisposableResource>(resource: R): Promise<R> {\n const finalizer = getDisposeFinalizer(resource)\n\n if (!finalizer) {\n throw new ResourceNotDisposableError()\n }\n\n try {\n this.addFinalizer(finalizer)\n\n return resource\n } catch (scopeFailure) {\n try {\n await finalizer(this.closeOutcome ?? SCOPE_SUCCESS)\n } catch (releaseFailure) {\n throw new AggregateError(\n [scopeFailure, releaseFailure],\n 'Scope closed while adding a disposable resource and cleanup also failed'\n )\n }\n\n throw scopeFailure\n }\n }\n\n close(outcome: ScopeOutcome = SCOPE_SUCCESS): Promise<void> {\n if (this.closePromise) {\n return this.closePromise\n }\n\n this.closeOutcome = outcome\n this.closePromise = ScopeRuntime.run(this, () => this.closeInternal(outcome))\n\n return this.closePromise\n }\n\n private async closeInternal(outcome: ScopeOutcome): Promise<void> {\n const failures: unknown[] = []\n\n const children = [...this.children]\n\n this.children.clear()\n\n for (let index = children.length - 1; index >= 0; index--) {\n const child = children[index]\n\n if (!child) {\n continue\n }\n\n try {\n await child.close(outcome)\n } catch (cause) {\n if (cause instanceof ScopeCloseError) {\n failures.push(...cause.causes)\n } else {\n failures.push(cause)\n }\n }\n }\n\n for (let index = this.finalizers.length - 1; index >= 0; index--) {\n const finalizer = this.finalizers[index]\n\n if (!finalizer) {\n continue\n }\n\n try {\n await finalizer(outcome)\n } catch (cause) {\n failures.push(cause)\n }\n }\n\n this.finalizers.length = 0\n\n this.detach()\n\n if (failures.length > 0) {\n throw new ScopeCloseError(failures)\n }\n }\n\n private detach(): void {\n const parent = this.parent\n\n if (!parent) {\n return\n }\n\n parent.children.delete(this)\n this.parent = undefined\n }\n\n private assertOpen(): void {\n if (this.closePromise) {\n throw new ScopeClosedError()\n }\n }\n}\n\nexport const Scope = {\n /** Create an owned, initially open Scope. */\n make(): CloseableScope {\n return new ScopeImpl()\n },\n\n /** Return the non-owning Scope available in the current execution context. */\n current(): Scope {\n return ScopeRuntime.current()\n },\n\n /** Run a callback with an existing Scope supplied as the current context. */\n provide<A>(scope: Scope, program: () => A): A {\n return ScopeRuntime.run(scope, program)\n },\n\n /** Resolve the current Scope through `yield* Scope` inside an Effect. */\n // oxlint-disable-next-line require-yield\n *[Symbol.iterator](): Generator<never, Scope, unknown> {\n return ScopeRuntime.current()\n },\n\n /**\n * Run a program in a newly owned Scope.\n *\n * Scope is independent from `better-result`, so returned values—including\n * `Result.err`—close this Scope with a successful outcome. Result-aware\n * outcome classification belongs to `Runtime.run`.\n *\n * @example\n * ```ts\n * await Scope.run(async (scope) => {\n * const connection = await scope.acquire(connect, (connection) => connection.close())\n * return connection.query()\n * })\n * ```\n */\n run<A>(program: (scope: Scope) => A | PromiseLike<A>): Promise<Awaited<A>> {\n const scope = new ScopeImpl()\n\n return runScoped(scope, () => program(scope), {\n classify: () => SCOPE_SUCCESS\n })\n }\n} as const\n","import { Result } from 'better-result'\n\nimport type { Result as ResultType } from 'better-result'\n\nimport type { EffectError, EffectRequirements, EffectResult, EffectSuccess } from './types'\n\ntype EffectInput<A, E, Requirements> =\n | EffectResult<A, E, Requirements>\n | PromiseLike<EffectResult<A, E, Requirements>>\n\ntype AnyEffectInput = EffectInput<any, any, any>\ntype AnyEffectResult = EffectResult<any, any, any>\ntype AnyAsyncEffectInput = PromiseLike<AnyEffectResult>\n\ntype PreserveAsync<Input, Output> = Input extends PromiseLike<unknown> ? Promise<Output> : Output\n\ntype MappedResult<Input, B> = EffectResult<B, EffectError<Input>, EffectRequirements<Input>>\n\ntype ErrorMappedResult<Input, E2> = EffectResult<\n EffectSuccess<Input>,\n E2,\n EffectRequirements<Input>\n>\n\ntype ChainedResult<First, Next> = EffectResult<\n EffectSuccess<Next>,\n EffectError<First> | EffectError<Next>,\n EffectRequirements<First> | EffectRequirements<Next>\n>\n\ntype ChainedOutput<First, Next> = ChainedResult<First, Next>\n\ntype AsyncChainedOutput<First, Next> = Promise<ChainedResult<First, Next>>\n\ntype MapOperation<A, B> = {\n <Input>(effect: Input & EffectInput<A, any, any>): PreserveAsync<Input, MappedResult<Input, B>>\n}\n\ntype MapErrorOperation<E1, E2> = {\n <Input>(\n effect: Input & EffectInput<any, E1, any>\n ): PreserveAsync<Input, ErrorMappedResult<Input, E2>>\n}\n\ntype AndThenOperation<A, Next> = {\n <Input>(effect: Input & EffectResult<A, any, any>): ChainedOutput<Input, Next>\n}\n\ntype AndThenAsyncOperation<A, Next> = {\n <Input>(effect: Input & EffectInput<A, any, any>): AsyncChainedOutput<Input, Next>\n}\n\nconst isPromiseLike = (value: unknown): value is PromiseLike<unknown> => {\n if ((typeof value !== 'object' && typeof value !== 'function') || value === null) {\n return false\n }\n\n return 'then' in value && typeof value.then === 'function'\n}\n\nconst mapResult = <A, B, E, Requirements>(\n result: EffectResult<A, E, Requirements>,\n fn: (value: A) => B\n): EffectResult<B, E, Requirements> => Result.map(result, fn) as EffectResult<B, E, Requirements>\n\nconst mapErrorResult = <A, E1, E2, Requirements>(\n result: EffectResult<A, E1, Requirements>,\n fn: (error: E1) => E2\n): EffectResult<A, E2, Requirements> =>\n Result.mapError(result, fn) as EffectResult<A, E2, Requirements>\n\nconst andThenResult = <A, B, E1, E2, Requirements1, Requirements2>(\n result: EffectResult<A, E1, Requirements1>,\n next: (value: A) => EffectResult<B, E2, Requirements2>\n): EffectResult<B, E1 | E2, Requirements1 | Requirements2> =>\n Result.andThen(result, next as (value: A) => ResultType<B, E2>) as EffectResult<\n B,\n E1 | E2,\n Requirements1 | Requirements2\n >\n\nconst andThenAsyncResult = <A, B, E1, E2, Requirements1, Requirements2>(\n result: EffectResult<A, E1, Requirements1>,\n next: (value: A) => PromiseLike<EffectResult<B, E2, Requirements2>>\n): Promise<EffectResult<B, E1 | E2, Requirements1 | Requirements2>> =>\n Result.andThenAsync(\n result,\n (value) => Promise.resolve(next(value)) as Promise<ResultType<B, E2>>\n ) as Promise<EffectResult<B, E1 | E2, Requirements1 | Requirements2>>\n\n/**\n * Map the successful value of a Result or Effect result.\n *\n * Supports both data-first and data-last forms and preserves asynchronous\n * results and phantom Service requirements.\n *\n * @example\n * ```ts\n * const doubled = Effect.map(Result.ok(2), (value) => value * 2)\n * const toLabel = Effect.map((value: number) => `#${value}`)\n * ```\n */\nexport function map<A, B>(fn: (value: A) => B): MapOperation<A, B>\nexport function map<Input, B>(\n effect: Input & AnyEffectInput,\n fn: (value: EffectSuccess<Input>) => B\n): PreserveAsync<Input, MappedResult<Input, B>>\nexport function map(first: unknown, second?: unknown): unknown {\n if (typeof first === 'function' && second === undefined) {\n return (effect: unknown) => map(effect as never, first as never)\n }\n\n const fn = second as (value: unknown) => unknown\n\n if (isPromiseLike(first)) {\n return Promise.resolve(first).then((result) =>\n mapResult(result as EffectResult<unknown, unknown, never>, fn)\n )\n }\n\n return mapResult(first as EffectResult<unknown, unknown, never>, fn)\n}\n\n/**\n * Map the error value of a Result or Effect result while preserving its\n * successful value, asynchronous shape, and Service requirements.\n *\n * @example\n * ```ts\n * const labelled = Effect.mapError(Result.err('missing'), (error) => ({ error }))\n * ```\n */\nexport function mapError<E1, E2>(fn: (error: E1) => E2): MapErrorOperation<E1, E2>\nexport function mapError<Input, E2>(\n effect: Input & AnyEffectInput,\n fn: (error: EffectError<Input>) => E2\n): PreserveAsync<Input, ErrorMappedResult<Input, E2>>\nexport function mapError(first: unknown, second?: unknown): unknown {\n if (typeof first === 'function' && second === undefined) {\n return (effect: unknown) => mapError(effect as never, first as never)\n }\n\n const fn = second as (error: unknown) => unknown\n\n if (isPromiseLike(first)) {\n return Promise.resolve(first).then((result) =>\n mapErrorResult(result as EffectResult<unknown, unknown, never>, fn)\n )\n }\n\n return mapErrorResult(first as EffectResult<unknown, unknown, never>, fn)\n}\n\n/**\n * Chain a synchronous Result-producing operation after a successful result.\n *\n * The next operation is skipped when the input is an error. Both error types\n * and both sets of Service requirements are preserved in the output.\n *\n * @example\n * ```ts\n * const user = Effect.andThen(Result.ok('u1'), (id) => repository.find(id))\n * ```\n */\nexport function andThen<A, Next extends AnyEffectResult>(\n next: (value: A) => Next\n): AndThenOperation<A, Next>\nexport function andThen<Input, Next extends AnyEffectResult>(\n effect: Input & AnyEffectResult,\n next: (value: EffectSuccess<Input>) => Next\n): ChainedOutput<Input, Next>\nexport function andThen(first: unknown, second?: unknown): unknown {\n if (typeof first === 'function' && second === undefined) {\n return (effect: unknown) => andThen(effect as never, first as never)\n }\n\n const next = second as (value: unknown) => EffectResult<unknown, unknown, never>\n\n return andThenResult(first as EffectResult<unknown, unknown, never>, next)\n}\n\n/**\n * Chain an asynchronous Result-producing operation after a successful result.\n *\n * The returned value is always a Promise and retains both operations' error\n * and Service-requirement metadata.\n *\n * @example\n * ```ts\n * const user = Effect.andThenAsync(loadUser(), (user) => fetchProfile(user.id))\n * ```\n */\nexport function andThenAsync<A, Next extends AnyAsyncEffectInput>(\n next: (value: A) => Next\n): AndThenAsyncOperation<A, Next>\nexport function andThenAsync<Input, Next extends AnyAsyncEffectInput>(\n effect: Input & AnyEffectInput,\n next: (value: EffectSuccess<Input>) => Next\n): AsyncChainedOutput<Input, Next>\nexport function andThenAsync(first: unknown, second?: unknown): unknown {\n if (typeof first === 'function' && second === undefined) {\n return (effect: unknown) => andThenAsync(effect as never, first as never)\n }\n\n const next = second as (value: unknown) => PromiseLike<EffectResult<unknown, unknown, never>>\n\n if (isPromiseLike(first)) {\n return Promise.resolve(first).then((result) =>\n andThenAsyncResult(result as EffectResult<unknown, unknown, never>, next)\n )\n }\n\n return andThenAsyncResult(first as EffectResult<unknown, unknown, never>, next)\n}\n","import { Result } from 'better-result'\n\nimport type { Err, Result as ResultType, UnhandledException } from 'better-result'\n\nimport { Scope } from '../scope'\n\nimport type { DisposableResource, MaybePromise, ScopeOutcome } from '../scope'\n\nimport type { EffectFromGenerator, EffectYield } from './types'\n\nimport { andThen, andThenAsync, map, mapError } from './combinators'\n\ntype AnyResult = ResultType<any, any>\n\ntype RuntimeGenerator =\n | (() => Generator<Err<never, unknown>, AnyResult, unknown>)\n | (() => AsyncGenerator<Err<never, unknown>, AnyResult, unknown>)\n\ntype EffectGenerator =\n | (() => Generator<EffectYield, AnyResult, unknown>)\n | (() => AsyncGenerator<EffectYield, AnyResult, unknown>)\n\n/**\n * Compose `better-result` operations while preserving Service requirements in\n * a phantom type channel.\n *\n * A generator may yield Service tokens and Result operations. It must return a\n * `Result` as its final value; Service yields are resolved by the active\n * Runtime and do not add runtime values to the Result stream.\n *\n * @example\n * ```ts\n * const loadUser = Effect.gen(async function* () {\n * const database = yield* Database\n * const user = yield* Result.await(database.findUser('u1'))\n *\n * return Result.ok(user)\n * })\n * ```\n */\nexport function gen<Yield extends EffectYield, Returned extends AnyResult>(\n body: () => Generator<Yield, Returned, unknown>\n): EffectFromGenerator<Yield, Returned>\n\nexport function gen<Yield extends EffectYield, Returned extends AnyResult>(\n body: () => AsyncGenerator<Yield, Returned, unknown>\n): Promise<EffectFromGenerator<Yield, Returned>>\n\nexport function gen(body: EffectGenerator): AnyResult | Promise<AnyResult> {\n /*\n * ServiceRequirement is phantom. The Service iterator returns its resolved\n * instance without yielding a marker, so Result.gen still receives only\n * the Err values that exist at runtime.\n */\n return (Result.gen as unknown as (body: RuntimeGenerator) => AnyResult | Promise<AnyResult>)(\n body as RuntimeGenerator\n )\n}\n\n/**\n * Acquire a resource in the current Scope and register its release callback.\n *\n * Acquisition failures are represented in the Effect Result error channel;\n * release failures remain owned by Scope cleanup. The release callback\n * receives the final outcome chosen by the enclosing execution boundary.\n *\n * @example\n * ```ts\n * const connection = yield* Effect.acquireRelease(\n * () => pool.connect(),\n * (connection, outcome) => connection.close(outcome)\n * )\n * ```\n */\nexport function acquireRelease<R>(\n acquire: () => MaybePromise<R>,\n release: (resource: R, outcome: ScopeOutcome) => MaybePromise<void>\n): AsyncGenerator<Err<never, UnhandledException>, R, unknown> {\n const scope = Scope.current()\n\n return Result.await(Result.tryPromise(() => scope.acquire(acquire, release)))\n}\n\n/**\n * Register an already-acquired disposable resource in the current Scope.\n *\n * The resource is not acquired by this helper. Registration failures are\n * represented in the Effect Result error channel; disposal failures remain\n * owned by Scope cleanup.\n *\n * @example\n * ```ts\n * const file = yield* Effect.add(await openFile('notes.txt'))\n * ```\n */\nexport function add<R extends DisposableResource>(\n resource: R\n): AsyncGenerator<Err<never, UnhandledException>, R, unknown> {\n const scope = Scope.current()\n\n return Result.await(Result.tryPromise(() => scope.add(resource)))\n}\n\n/**\n * Effect namespace containing generator, resource, and Result combinators.\n *\n * Prefer these helpers when a program needs typed Service requirements or\n * Scope-aware acquisition and cleanup.\n */\nexport const Effect = {\n /** Compose a generator-based Effect program. */\n gen,\n /** Acquire and register a resource in the current Scope. */\n acquireRelease,\n /** Register an already-acquired disposable in the current Scope. */\n add,\n /** Map a successful Effect result. */\n map,\n /** Map an Effect error. */\n mapError,\n /** Chain a synchronous Effect result. */\n andThen,\n /** Chain an asynchronous Effect result. */\n andThenAsync\n} as const\n","type Unary<A, B> = (value: A) => B\n\n/**\n * Compose a value through a sequence of unary functions.\n *\n * `pipe` is deliberately independent of Effect, Result, Promise, Scope, and\n * Service metadata.\n *\n * @example\n * ```ts\n * const label = pipe(\n * 'alice',\n * (name) => name.trim(),\n * (name) => name.toUpperCase()\n * )\n * ```\n */\nexport function pipe<A>(value: A): A\nexport function pipe<A, B>(value: A, ab: Unary<A, B>): B\nexport function pipe<A, B, C>(value: A, ab: Unary<A, B>, bc: Unary<B, C>): C\nexport function pipe<A, B, C, D>(value: A, ab: Unary<A, B>, bc: Unary<B, C>, cd: Unary<C, D>): D\nexport function pipe<A, B, C, D, E>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>\n): E\nexport function pipe<A, B, C, D, E, F>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>,\n ef: Unary<E, F>\n): F\nexport function pipe<A, B, C, D, E, F, G>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>,\n ef: Unary<E, F>,\n fg: Unary<F, G>\n): G\nexport function pipe<A, B, C, D, E, F, G, H>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>,\n ef: Unary<E, F>,\n fg: Unary<F, G>,\n gh: Unary<G, H>\n): H\nexport function pipe<A, B, C, D, E, F, G, H, I>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>,\n ef: Unary<E, F>,\n fg: Unary<F, G>,\n gh: Unary<G, H>,\n hi: Unary<H, I>\n): I\nexport function pipe<A, B, C, D, E, F, G, H, I, J>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>,\n ef: Unary<E, F>,\n fg: Unary<F, G>,\n gh: Unary<G, H>,\n hi: Unary<H, I>,\n ij: Unary<I, J>\n): J\nexport function pipe<A, B, C, D, E, F, G, H, I, J, K>(\n value: A,\n ab: Unary<A, B>,\n bc: Unary<B, C>,\n cd: Unary<C, D>,\n de: Unary<D, E>,\n ef: Unary<E, F>,\n fg: Unary<F, G>,\n gh: Unary<G, H>,\n hi: Unary<H, I>,\n ij: Unary<I, J>,\n jk: Unary<J, K>\n): K\nexport function pipe(\n value: unknown,\n ...operations: ReadonlyArray<Unary<unknown, unknown>>\n): unknown {\n return operations.reduce((current, operation) => operation(current), value)\n}\n","import { TaggedError } from 'better-result'\n\n/** Describes a failure encountered while releasing a Resource. */\nexport class ResourceReleaseFailure extends TaggedError('ResourceReleaseFailure')<{\n readonly resource: string\n readonly cause: unknown\n readonly message: string\n}> {}\n","import { Result, type Result as ResultType, type UnhandledException } from 'better-result'\n\nimport { ResourceReleaseFailure } from './errors'\n\nimport { disposeResource } from '../scope/disposable'\n\nexport { disposeResource }\n\nimport type { AsyncResult, MaybePromise, ReleaseFailureObserver, ReleaseOutcome } from './types'\n\nconst toReleaseFailure = (resource: string, cause: unknown): ResourceReleaseFailure =>\n new ResourceReleaseFailure({\n resource,\n cause,\n message: `Failed to release resource: ${resource}`\n })\n\nexport const runResult = async <T, E>(\n operation: () => AsyncResult<T, E>\n): Promise<ResultType<T, E | UnhandledException>> => {\n const execution = await Result.tryPromise(() => Promise.resolve(operation()))\n\n return execution.andThen((result) => result)\n}\n\nconst normalizeReleaseOutcome = (\n name: string,\n outcome: ReleaseOutcome\n): ResultType<void, ResourceReleaseFailure> => {\n if (outcome === undefined) {\n return Result.ok()\n }\n\n return outcome.mapError((cause) => toReleaseFailure(name, cause))\n}\n\nexport const runRelease = async <R>(\n name: string,\n resource: R,\n release: (resource: R) => MaybePromise<ReleaseOutcome>\n): Promise<ResultType<void, ResourceReleaseFailure>> => {\n const execution = await Result.tryPromise({\n try: () => Promise.resolve(release(resource)),\n catch: (cause) => toReleaseFailure(name, cause)\n })\n\n return execution.andThen((outcome) => normalizeReleaseOutcome(name, outcome))\n}\n\nconst notifyReleaseFailure = async (\n observer: ReleaseFailureObserver | undefined,\n\n failure: ResourceReleaseFailure\n): Promise<void> => {\n if (!observer) {\n return\n }\n\n try {\n await observer(failure)\n } catch {\n /*\n * Diagnostics must never replace\n * the actual operation error.\n */\n }\n}\n\nexport const combineUseAndRelease = async <A, E>(\n used: ResultType<A, E>,\n\n released: ResultType<void, ResourceReleaseFailure>,\n\n onReleaseFailure?: ReleaseFailureObserver\n): Promise<ResultType<A, E | ResourceReleaseFailure>> => {\n if (Result.isError(used)) {\n if (Result.isError(released)) {\n await notifyReleaseFailure(onReleaseFailure, released.error)\n }\n\n return Result.err<A, E | ResourceReleaseFailure>(used.error)\n }\n\n if (Result.isError(released)) {\n await notifyReleaseFailure(onReleaseFailure, released.error)\n\n return Result.err<A, E | ResourceReleaseFailure>(released.error)\n }\n\n return Result.ok<A, E | ResourceReleaseFailure>(used.value)\n}\n","import { Result, type Result as ResultType, type UnhandledException } from 'better-result'\n\nimport { Scope } from '../scope'\n\nimport { ResourceReleaseFailure } from './errors'\n\nimport { combineUseAndRelease, disposeResource, runRelease, runResult } from './internal'\n\nimport type { AcquireUseReleaseOptions } from './types'\n\n/**\n * Acquire a resource, use it, and always attempt release afterward.\n *\n * Acquisition, use, and release may be synchronous or asynchronous Result\n * operations. If both use and release fail, the use error remains primary and\n * `onReleaseFailure` receives the cleanup failure as a diagnostic.\n *\n * When `release` is omitted, `Symbol.asyncDispose` is preferred over\n * `Symbol.dispose`.\n *\n * @example\n * ```ts\n * const result = await Resource.acquireUseRelease({\n * name: 'database connection',\n * acquire: () => connect(),\n * use: (connection) => query(connection),\n * release: (connection) => connection.close()\n * })\n * ```\n */\nconst acquireUseRelease = <R, A, AcquireError, UseError>({\n name,\n acquire,\n use,\n release = disposeResource,\n onReleaseFailure\n}: AcquireUseReleaseOptions<R, A, AcquireError, UseError>): Promise<\n ResultType<A, AcquireError | UseError | UnhandledException | ResourceReleaseFailure>\n> =>\n Result.gen(async function* () {\n const resource = yield* Result.await(runResult(acquire))\n\n const scope = Scope.make()\n\n let released: ResultType<void, ResourceReleaseFailure> = Result.ok()\n\n scope.addFinalizer(async () => {\n released = await runRelease(name, resource, release)\n })\n\n const used = await runResult(() => use(resource))\n\n await scope.close()\n\n return await combineUseAndRelease(used, released, onReleaseFailure)\n })\n\nexport const Resource = {\n /** Acquire, use, and release a resource with deterministic error precedence. */\n acquireUseRelease\n} as const\n","import { Result } from 'better-result'\n\nimport type { Result as ResultType } from 'better-result'\n\nimport type { LayerDisposeError } from '../layer/errors'\n\nimport type { CleanupFailureDiagnostic, MaybePromise, ScopeOutcome } from '../scope'\n\n/** Aggregated cleanup information reported during Runtime shutdown. */\nexport type RuntimeShutdownDiagnostic = {\n /** Final outcome supplied to the Runtime root Scope. */\n readonly outcome: ScopeOutcome\n /** Aggregated root-Scope and backend cleanup failure. */\n readonly error: LayerDisposeError\n}\n\n/** Observer notified about cleanup failures without changing primary results. */\nexport type CleanupFailureObserver = (\n diagnostic: CleanupFailureDiagnostic | RuntimeShutdownDiagnostic\n) => MaybePromise<void>\n\n/** Optional Runtime configuration for cleanup diagnostics. */\nexport type RuntimeOptions = {\n /** Optional observer for best-effort cleanup diagnostics. */\n readonly onCleanupFailure?: CleanupFailureObserver\n}\n\nconst isResultLike = (value: unknown): value is ResultType<unknown, unknown> =>\n typeof value === 'object' &&\n value !== null &&\n 'status' in value &&\n (value.status === 'ok' || value.status === 'error')\n\nexport const classifyRuntimeOutcome = (value: unknown): ScopeOutcome => {\n if (isResultLike(value) && Result.isError(value)) {\n return {\n status: 'failure',\n cause: value.error\n }\n }\n\n return {\n status: 'success'\n }\n}\n","import { ServiceRuntime } from '../service'\n\nimport type { AnyServiceToken } from '../service'\n\nimport { Scope, type CloseableScope } from '../scope'\nimport { runScoped } from '../scope/internal'\nimport { ScopeRuntime } from '../scope/runtime'\n\nimport {\n classifyRuntimeOutcome,\n type CleanupFailureObserver,\n type RuntimeOptions,\n type RuntimeShutdownDiagnostic\n} from '../runtime/outcome'\n\nimport { LayerDisposeError, LayerRegistrationError } from './errors'\n\nimport type { LayerBackend } from './backend'\n\nimport type { AnyLayer, CompleteExecution, CompleteLayer, LayerProvided } from './inference'\n\nimport type { LayerRegistration } from './types'\n\nimport type { ScopeOutcome } from '../scope'\n\ntype LayerProvider = AnyLayer['providers'][number]\n\n/** Runtime-facing handle that owns a Layer's resources and execution scopes. */\nexport interface RuntimeHandle<Provided extends AnyServiceToken = AnyServiceToken> {\n /** The backend used to resolve this Layer's providers. */\n readonly backend: LayerBackend\n\n /** Run a program in a child Scope of the Layer's root Scope. */\n run<A>(program: CompleteExecution<Provided, A>): Promise<Awaited<A>>\n\n /** Stop new executions and release Layer-owned resources. */\n dispose(outcome?: ScopeOutcome): Promise<void>\n}\n\nconst SCOPE_SUCCESS: ScopeOutcome = Object.freeze({ status: 'success' })\n\nclass RuntimeHandleDisposedError extends Error {\n constructor() {\n super('Cannot run a program using a disposed Layer')\n\n this.name = 'RuntimeHandleDisposedError'\n }\n}\n\nconst normalizeDisposeCauses = (cause: unknown): readonly unknown[] => {\n if (cause instanceof AggregateError) {\n return [...cause.errors]\n }\n\n return [cause]\n}\n\nconst notifyShutdownFailure = async (\n observer: CleanupFailureObserver | undefined,\n diagnostic: RuntimeShutdownDiagnostic\n): Promise<void> => {\n if (!observer) {\n return\n }\n\n try {\n await observer(diagnostic)\n } catch {\n // Shutdown diagnostics are best effort and never affect the primary result.\n }\n}\n\nconst bindProviderToScope = (\n provider: LayerProvider,\n rootScope: CloseableScope\n): LayerRegistration => ({\n service: provider.service,\n\n acquire: () =>\n ScopeRuntime.run(rootScope, async () => {\n if (!provider.release) {\n return await provider.acquire()\n }\n\n return await rootScope.acquire(\n () => provider.acquire(),\n (resource, outcome) => provider.release!(resource, outcome)\n )\n })\n})\n\nclass RuntimeHandleImpl<Provided extends AnyServiceToken> implements RuntimeHandle<Provided> {\n private disposePromise: Promise<void> | undefined\n\n private readonly executions = new Set<Promise<unknown>>()\n\n private state: 'active' | 'disposing' | 'disposed' = 'active'\n\n constructor(\n readonly backend: LayerBackend,\n private readonly rootScope: CloseableScope,\n private readonly onCleanupFailure: CleanupFailureObserver | undefined\n ) {}\n\n run<A>(program: CompleteExecution<Provided, A>): Promise<Awaited<A>> {\n this.assertActive()\n\n const executionScope = this.rootScope.fork()\n\n let resolveExecution!: (value: Awaited<A> | PromiseLike<Awaited<A>>) => void\n let rejectExecution!: (cause?: unknown) => void\n\n const execution = new Promise<Awaited<A>>((resolve, reject) => {\n resolveExecution = resolve\n rejectExecution = reject\n })\n\n this.executions.add(execution)\n\n void execution.then(\n () => {\n this.executions.delete(execution)\n },\n () => {\n this.executions.delete(execution)\n }\n )\n\n try {\n const running = this.runExecution(executionScope, program)\n\n void running.then(\n (value) => {\n resolveExecution(value)\n },\n (cause) => {\n rejectExecution(cause)\n }\n )\n } catch (cause) {\n rejectExecution(cause)\n }\n\n return execution\n }\n\n private runExecution<A>(\n executionScope: CloseableScope,\n program: CompleteExecution<Provided, A>\n ): Promise<Awaited<A>> {\n const options = this.onCleanupFailure\n ? {\n classify: classifyRuntimeOutcome,\n onCleanupFailure: this.onCleanupFailure\n }\n : {\n classify: classifyRuntimeOutcome\n }\n\n return runScoped(executionScope, () => ServiceRuntime.run(this.backend, program), options)\n }\n\n dispose(outcome: ScopeOutcome = SCOPE_SUCCESS): Promise<void> {\n if (this.disposePromise) {\n return this.disposePromise\n }\n\n this.state = 'disposing'\n\n const executions = [...this.executions]\n\n this.disposePromise = this.performDispose(executions, outcome)\n\n return this.disposePromise\n }\n\n private async performDispose(\n executions: readonly Promise<unknown>[],\n outcome: ScopeOutcome\n ): Promise<void> {\n const failures: unknown[] = []\n\n await Promise.allSettled(executions)\n\n try {\n await ServiceRuntime.run(this.backend, () => this.rootScope.close(outcome))\n } catch (cause) {\n failures.push(cause)\n }\n\n try {\n await this.backend.disposeAll()\n } catch (cause) {\n failures.push(cause)\n }\n\n this.state = 'disposed'\n\n if (failures.length > 0) {\n const error = new LayerDisposeError(failures.flatMap(normalizeDisposeCauses))\n\n await notifyShutdownFailure(this.onCleanupFailure, {\n outcome,\n error\n })\n\n throw error\n }\n }\n\n private assertActive(): void {\n if (this.state !== 'active') {\n throw new RuntimeHandleDisposedError()\n }\n }\n}\n\n/** Build a Runtime handle for a complete Layer and register its providers. */\nexport const createRuntimeHandle = async <L extends AnyLayer>(\n layer: CompleteLayer<L>,\n backend: LayerBackend,\n options: RuntimeOptions = {}\n): Promise<RuntimeHandle<LayerProvided<L>>> => {\n const rootScope = Scope.make()\n let current: LayerProvider | undefined\n\n try {\n for (const provider of layer.providers) {\n current = provider\n\n await backend.register(bindProviderToScope(provider, rootScope))\n }\n } catch (registrationCause) {\n const outcome: ScopeOutcome = {\n status: 'failure',\n cause: registrationCause\n }\n const cleanupCauses: unknown[] = []\n\n try {\n await ServiceRuntime.run(backend, () => rootScope.close(outcome))\n } catch (cause) {\n cleanupCauses.push(cause)\n }\n\n try {\n await backend.disposeAll()\n } catch (cause) {\n cleanupCauses.push(cause)\n }\n\n if (cleanupCauses.length > 0) {\n const shutdownError = new LayerDisposeError(cleanupCauses.flatMap(normalizeDisposeCauses))\n\n await notifyShutdownFailure(options.onCleanupFailure, {\n outcome,\n error: shutdownError\n })\n }\n\n let cleanupCause: unknown\n\n if (cleanupCauses.length === 1) {\n cleanupCause = cleanupCauses[0]\n } else if (cleanupCauses.length > 1) {\n cleanupCause = new LayerDisposeError(cleanupCauses.flatMap(normalizeDisposeCauses))\n }\n\n throw new LayerRegistrationError(current?.service, registrationCause, cleanupCause)\n }\n\n return new RuntimeHandleImpl<LayerProvided<L>>(backend, rootScope, options.onCleanupFailure)\n}\n","import type { LayerBackend } from '../layer'\n\nimport { createRuntimeHandle, type RuntimeHandle } from '../layer/runtime'\n\nimport type { AnyLayer, CompleteLayer, LayerProvided } from '../layer/inference'\n\nimport type { CompleteExecution } from '../layer/inference'\n\nimport type { AnyServiceToken } from '../service'\n\nimport { classifyRuntimeOutcome, type RuntimeOptions } from './outcome'\n\nimport type { ScopeOutcome } from '../scope'\n\n/**\n * Long-lived execution environment backed by a complete Layer.\n *\n * A Runtime owns Layer resources until `dispose()` is called. Each `run()` is\n * isolated in a child Scope, while Layer-scoped resources remain shared.\n *\n * @example\n * ```ts\n * const runtime = await Runtime.make(AppLive, new MemoryLayerBackend())\n * const result = await runtime.run(loadUser('u1'))\n * await runtime.dispose()\n * ```\n *\n * @typeParam Provided The Service constructors supplied by the Layer.\n */\nexport class Runtime<Provided extends AnyServiceToken = AnyServiceToken> {\n private constructor(private readonly handle: RuntimeHandle<Provided>) {}\n\n /**\n * Create a long-lived Runtime that owns its Layer resources.\n *\n * @example\n * ```ts\n * const runtime = await Runtime.make(AppLive, backend)\n * const result = await runtime.run(program)\n * await runtime.dispose()\n * ```\n */\n static async make<L extends AnyLayer>(\n layer: CompleteLayer<L>,\n backend: LayerBackend,\n options: RuntimeOptions = {}\n ): Promise<Runtime<LayerProvided<L>>> {\n const handle = await createRuntimeHandle(layer, backend, options)\n\n return new Runtime<LayerProvided<L>>(handle)\n }\n\n /**\n * Run one program and dispose its Layer resources before resolving.\n *\n * This is convenient for request-style or command-style execution where a\n * Runtime should not outlive the operation.\n */\n static async run<A, L extends AnyLayer>(\n layer: CompleteLayer<L>,\n backend: LayerBackend,\n program: CompleteExecution<LayerProvided<L>, A>,\n options: RuntimeOptions = {}\n ): Promise<Awaited<A>> {\n const runtime = await Runtime.make(layer, backend, options)\n\n let value!: Awaited<A>\n let executionFailed = false\n let executionFailure: unknown\n let programOutcome: ScopeOutcome | undefined\n\n try {\n value = await runtime.runUnchecked(async () => {\n try {\n const programValue = await program()\n\n programOutcome = classifyRuntimeOutcome(programValue)\n\n return programValue\n } catch (cause) {\n programOutcome = {\n status: 'failure',\n cause\n }\n\n throw cause\n }\n })\n } catch (cause) {\n executionFailed = true\n executionFailure = cause\n }\n\n const outcome: ScopeOutcome =\n programOutcome ??\n ({\n status: 'failure',\n cause: executionFailure\n } as const)\n\n try {\n await runtime.disposeWithOutcome(outcome)\n } catch (shutdownFailure) {\n if (!executionFailed && outcome.status === 'success') {\n throw shutdownFailure\n }\n }\n\n if (executionFailed) {\n throw executionFailure\n }\n\n return value\n }\n\n /** Run one execution in this Runtime's child Scope. */\n run<A>(program: CompleteExecution<Provided, A>): Promise<Awaited<A>> {\n return this.handle.run(program)\n }\n\n private runUnchecked<A>(program: () => A | PromiseLike<A>): Promise<Awaited<A>> {\n return this.handle.run(program as CompleteExecution<Provided, A>)\n }\n\n /** Stop new executions and release the Runtime's Layer resources. */\n dispose(): Promise<void> {\n return this.handle.dispose()\n }\n\n private disposeWithOutcome(outcome: ScopeOutcome): Promise<void> {\n return this.handle.dispose(outcome)\n }\n}\n"],"mappings":";;;;AAYA,MAAMA,YAAU,IAAI,kBAAmC;;AAGvD,IAAa,iBAAb,MAAa,eAAe;;;;;;;;;;;;;CAa1B,OAAO,IAAO,UAA2B,SAAqB;EAC5D,OAAOA,UAAQ,IAAI,UAAU,OAAO;CACtC;;CAGA,OAAO,UAA2B;EAChC,MAAM,WAAWA,UAAQ,SAAS;EAElC,IAAI,CAAC,UACH,MAAM,IAAI,iCAAiC;EAG7C,OAAO;CACT;;CAGA,aAAa,QAAmC,OAAoC;EAGlF,OAAO,MAFU,eAAe,QAEZ,CAAC,CAAC,QAAQ,KAAK;CACrC;AACF;;;;;;;;;;;;;;;;;;;;;;;;;ACfA,SAAgB,UAAgB;CAC9B,OAAO,SAAoC,KAA6B;EACtE,IAAI,IAAI,WAAW,GACjB,MAAM,IAAI,UAAU,gCAAgC;EAGtD,MAAe,YAAY;;GAEzB,OAAgB,aAAkB;;;;;;;;;;;;;;;;;;;;;;;;GAyBlC,OAAO,GAAe,gBAA4B;IAChD,OAAO;GACT;;GAIA,eAAe,OAAO,iBAEwD;IAC5E,OAAO,MAAM,eAAe,QAAQ,IAAI;GAC1C;EACF;EAEA,OAAO;CACT;AACF;;;AC3EA,MAAa,oBAAoB,OAI/B,SACA,YAC6B;CAC7B,MAAM,WAAW,QAAQ;CAEzB,MAAM,QAAQ,MAAM,SAAS,KAAK;CAElC,IAAI,CAAC,MAAM,MACT,IAAI;EACF,MAAM,SAAS,OAAO,KAAA,CAA4B;CACpD,UAAU;EAER,MAAM,IAAI,yBAAyB,OAAO;CAC5C;CAGF,OAAO,MAAM;AACf;;;;;;;;;;;;;;;;;;;;ACuBA,IAAa,QAAb,MAAa,MAGX;;CAKA;CAEA,YAAoB,WAAqC;EACvD,KAAK,YAAY,OAAO,OAAO,CAAC,GAAG,SAAS,CAAC;CAC/C;CAgCA,OAAO,KACL,SACA,SAC6C;EAC7C,MAAM,uBAAwC;GAG5C,OAAO,IAAIC,QAAY;EACzB;EAEA,OAAO,IAAI,MAAM,CACf;GACE;GACA,SAAS,WAAW;EACtB,CACF,CAAC;CACH;;;;;;;;;;;CAYA,OAAO,QACL,SACA,UAC6C;EAC7C,OAAO,MAAM,KAAK,eAAe,QAAQ;CAC3C;;;;;;;;;;;;;;;;;;CAmBA,OAAO,OACL,SACA,SACA,SAC6C;EAC7C,OAAO,IAAI,MAAM,CACf;GACE;GACA;GAEA,UAAU,aAAa,QAAQ,QAA2B;EAC5D,CACF,CAAC;CACH;;;;;;;;;;;;;;;;;;;CAoBA,OAAO,UAIL,SACA,SACA,SAC2D;EAC3D,OAAO,IAAI,MAAM,CACf;GACE;GACA,eAAe,kBAAkB,SAAS,OAAO;GACjD,UAAU,UAAU,YAAY,QAAQ,UAA6B,OAAO;EAC9E,CACF,CAAC;CACH;;;;;;;;;;;;;;;CAgBA,OAAO,IACL,SACA,SAC2D;EAC3D,OAAO,MAAM,KAAK,eAAe,kBAAkB,SAAS,OAAO,CAAC;CACtE;;;;;;;;;;;;CAaA,OAAO,MACL,GAAG,QAIH;EACA,MAAM,4BAAY,IAAI,IAA2B;EAEjD,KAAK,MAAM,SAAS,QAClB,KAAK,MAAM,YAAY,MAAM,WAAW;GACtC,MAAM,UAAU,SAAS;GAEzB,MAAM,WAAW,UAAU,IAAI,QAAQ,UAAU;GAEjD,IAAI,UAAU;IACZ,IAAI,SAAS,YAAY,SACvB,MAAM,IAAI,yBAAyB,SAAS,SAAS,OAAO;IAG9D,MAAM,IAAI,sBAAsB,OAAO;GACzC;GAEA,UAAU,IAAI,QAAQ,YAAY,QAAQ;EAC5C;EAGF,OAAO,IAAI,MAAM,CAAC,GAAG,UAAU,OAAO,CAAC,CAAC;CAC1C;;;;;;;;;;;;;;CAeA,OAAO,SACL,MACA,GAAG,WAMH;EACA,MAAM,4BAAY,IAAI,IAA2B;EAEjD,KAAK,MAAM,YAAY,KAAK,WAC1B,UAAU,IAAI,SAAS,QAAQ,YAAY,QAAQ;EAGrD,KAAK,MAAM,SAAS,WAClB,KAAK,MAAM,YAAY,MAAM,WAC3B,UAAU,IAAI,SAAS,QAAQ,YAAY,QAAQ;EAIvD,OAAO,IAAI,MAAM,CAAC,GAAG,UAAU,OAAO,CAAC,CAAC;CAM1C;AACF;;;;AC1SA,IAAa,iCAAb,cAAoD,MAAM;CACxD,cAAc;EACZ,MAAM,wDAAwD;EAE9D,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,mBAAb,cAAsC,MAAM;CAC1C,cAAc;EACZ,MAAM,sDAAsD;EAE5D,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,kBAAb,cAAqC,MAAM;CACpB;CAArB,YAAY,QAAqC;EAC/C,MACE,0BAA0B,OAAO,OAAO,YAAY,OAAO,WAAW,IAAI,KAAK,IAAI,SACrF;EAHmB,KAAA,SAAA;EAKnB,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,6BAAb,cAAgD,MAAM;CACpD,cAAc;EACZ,MAAM,mEAAmE;EAEzE,KAAK,OAAO;CACd;AACF;;;AClCA,MAAMC,kBAAgB,EAAE,QAAQ,UAAU;;AAS1C,MAAa,uBAAuB,aAAkD;CACpF,MAAM,YAAY,OAAO,QAAQ;CACjC,MAAM,eAAe,UAAU,OAAO;CAEtC,IAAI,OAAO,iBAAiB,YAC1B,aAAa,aAAa,KAAK,QAAQ;CAGzC,MAAM,UAAU,UAAU,OAAO;CAEjC,IAAI,OAAO,YAAY,YACrB,aAAa,QAAQ,KAAK,QAAQ;AAItC;;AAGA,MAAa,mBAAmB,aAAgD;CAG9E,OAFkB,oBAAoB,QAEvB,CAAC,GAAGA,eAAa;AAClC;;;AC3BA,MAAM,UAAU,IAAI,kBAAyB;;AAG7C,IAAa,eAAb,MAA0B;;CAExB,OAAO,IAAO,OAAc,SAAqB;EAC/C,OAAO,QAAQ,IAAI,OAAO,OAAO;CACnC;;CAGA,OAAO,UAAiB;EACtB,MAAM,QAAQ,QAAQ,SAAS;EAE/B,IAAI,CAAC,OACH,MAAM,IAAI,+BAA+B;EAG3C,OAAO;CACT;AACF;;;ACVA,MAAM,uBAAuB,OAC3B,UACA,eACkB;CAClB,IAAI,CAAC,UACH;CAGF,IAAI;EACF,MAAM,SAAS,UAAU;CAC3B,QAAQ,CAER;AACF;AAEA,MAAa,YAAY,OACvB,OACA,SACA,YACwB;CACxB,IAAI;CAEJ,IAAI,gBAAgB;CACpB,IAAI;CAEJ,IAAI;EACF,QAAQ,MAAM,aAAa,IAAI,OAAgB,OAAO;CACxD,SAAS,OAAO;EACd,gBAAgB;EAChB,iBAAiB;CACnB;CAEA,MAAM,UAAwB,gBAC1B;EACE,QAAQ;EACR,OAAO;CACT,IACA,QAAQ,SAAS,KAAK;CAE1B,IAAI,gBAAgB;CACpB,IAAI;CAEJ,IAAI;EACF,MAAM,MAAM,MAAM,OAAO;CAC3B,SAAS,OAAO;EACd,gBAAgB;EAChB,iBAAiB;CACnB;CAEA,IAAI,eAAe;EACjB,MAAM,QACJ,0BAA0B,kBACtB,iBACA,IAAI,gBAAgB,CAAC,cAAc,CAAC;EAE1C,MAAM,qBAAqB,QAAQ,kBAAkB;GACnD;GACA;EACF,CAAC;EAED,iBAAiB;CACnB;CAEA,IAAI,eACF,MAAM;CAGR,IAAI,QAAQ,WAAW,WACrB,OAAO;CAGT,IAAI,eACF,MAAM;CAGR,OAAO;AACT;;;ACpDA,MAAMC,kBAA8B,OAAO,OAAO,EAAE,QAAQ,UAAU,CAAC;AAEvE,IAAM,YAAN,MAAM,UAAoC;CASpB;CARpB,2BAA4B,IAAI,IAAe;CAE/C,aAAgD,CAAC;CAEjD;CAEA;CAEA,YAAY,QAA4B;EAApB,KAAA,SAAA;CAAqB;CAEzC,OAAuB;EACrB,KAAK,WAAW;EAEhB,MAAM,QAAQ,IAAI,UAAU,IAAI;EAEhC,KAAK,SAAS,IAAI,KAAK;EAEvB,OAAO;CACT;CAEA,aAAa,WAAiC;EAC5C,KAAK,WAAW;EAEhB,KAAK,WAAW,KAAK,SAAS;CAChC;CAEA,MAAM,QACJ,SACA,SACY;EACZ,KAAK,WAAW;EAEhB,MAAM,WAAW,MAAM,QAAQ;EAE/B,IAAI;GACF,KAAK,cAAc,YAAY,QAAQ,UAAU,OAAO,CAAC;GAEzD,OAAO;EACT,SAAS,cAAc;GACrB,IAAI;IACF,MAAM,QAAQ,UAAU,KAAK,gBAAgBA,eAAa;GAC5D,SAAS,gBAAgB;IACvB,MAAM,IAAI,eACR,CAAC,cAAc,cAAc,GAC7B,2EACF;GACF;GAEA,MAAM;EACR;CACF;CAEA,MAAM,IAAkC,UAAyB;EAC/D,MAAM,YAAY,oBAAoB,QAAQ;EAE9C,IAAI,CAAC,WACH,MAAM,IAAI,2BAA2B;EAGvC,IAAI;GACF,KAAK,aAAa,SAAS;GAE3B,OAAO;EACT,SAAS,cAAc;GACrB,IAAI;IACF,MAAM,UAAU,KAAK,gBAAgBA,eAAa;GACpD,SAAS,gBAAgB;IACvB,MAAM,IAAI,eACR,CAAC,cAAc,cAAc,GAC7B,yEACF;GACF;GAEA,MAAM;EACR;CACF;CAEA,MAAM,UAAwBA,iBAA8B;EAC1D,IAAI,KAAK,cACP,OAAO,KAAK;EAGd,KAAK,eAAe;EACpB,KAAK,eAAe,aAAa,IAAI,YAAY,KAAK,cAAc,OAAO,CAAC;EAE5E,OAAO,KAAK;CACd;CAEA,MAAc,cAAc,SAAsC;EAChE,MAAM,WAAsB,CAAC;EAE7B,MAAM,WAAW,CAAC,GAAG,KAAK,QAAQ;EAElC,KAAK,SAAS,MAAM;EAEpB,KAAK,IAAI,QAAQ,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS;GACzD,MAAM,QAAQ,SAAS;GAEvB,IAAI,CAAC,OACH;GAGF,IAAI;IACF,MAAM,MAAM,MAAM,OAAO;GAC3B,SAAS,OAAO;IACd,IAAI,iBAAiB,iBACnB,SAAS,KAAK,GAAG,MAAM,MAAM;SAE7B,SAAS,KAAK,KAAK;GAEvB;EACF;EAEA,KAAK,IAAI,QAAQ,KAAK,WAAW,SAAS,GAAG,SAAS,GAAG,SAAS;GAChE,MAAM,YAAY,KAAK,WAAW;GAElC,IAAI,CAAC,WACH;GAGF,IAAI;IACF,MAAM,UAAU,OAAO;GACzB,SAAS,OAAO;IACd,SAAS,KAAK,KAAK;GACrB;EACF;EAEA,KAAK,WAAW,SAAS;EAEzB,KAAK,OAAO;EAEZ,IAAI,SAAS,SAAS,GACpB,MAAM,IAAI,gBAAgB,QAAQ;CAEtC;CAEA,SAAuB;EACrB,MAAM,SAAS,KAAK;EAEpB,IAAI,CAAC,QACH;EAGF,OAAO,SAAS,OAAO,IAAI;EAC3B,KAAK,SAAS,KAAA;CAChB;CAEA,aAA2B;EACzB,IAAI,KAAK,cACP,MAAM,IAAI,iBAAiB;CAE/B;AACF;AAEA,MAAa,QAAQ;;CAEnB,OAAuB;EACrB,OAAO,IAAI,UAAU;CACvB;;CAGA,UAAiB;EACf,OAAO,aAAa,QAAQ;CAC9B;;CAGA,QAAW,OAAc,SAAqB;EAC5C,OAAO,aAAa,IAAI,OAAO,OAAO;CACxC;;CAIA,EAAE,OAAO,YAA8C;EACrD,OAAO,aAAa,QAAQ;CAC9B;;;;;;;;;;;;;;;;CAiBA,IAAO,SAAoE;EACzE,MAAM,QAAQ,IAAI,UAAU;EAE5B,OAAO,UAAU,aAAa,QAAQ,KAAK,GAAG,EAC5C,gBAAgBA,gBAClB,CAAC;CACH;AACF;;;AC5LA,MAAM,iBAAiB,UAAkD;CACvE,IAAK,OAAO,UAAU,YAAY,OAAO,UAAU,cAAe,UAAU,MAC1E,OAAO;CAGT,OAAO,UAAU,SAAS,OAAO,MAAM,SAAS;AAClD;AAEA,MAAM,aACJ,QACA,OACqC,OAAO,IAAI,QAAQ,EAAE;AAE5D,MAAM,kBACJ,QACA,OAEA,OAAO,SAAS,QAAQ,EAAE;AAE5B,MAAM,iBACJ,QACA,SAEA,OAAO,QAAQ,QAAQ,IAAuC;AAMhE,MAAM,sBACJ,QACA,SAEA,OAAO,aACL,SACC,UAAU,QAAQ,QAAQ,KAAK,KAAK,CAAC,CACxC;AAmBF,SAAgB,IAAI,OAAgB,QAA2B;CAC7D,IAAI,OAAO,UAAU,cAAc,WAAW,KAAA,GAC5C,QAAQ,WAAoB,IAAI,QAAiB,KAAc;CAGjE,MAAM,KAAK;CAEX,IAAI,cAAc,KAAK,GACrB,OAAO,QAAQ,QAAQ,KAAK,CAAC,CAAC,MAAM,WAClC,UAAU,QAAiD,EAAE,CAC/D;CAGF,OAAO,UAAU,OAAgD,EAAE;AACrE;AAgBA,SAAgB,SAAS,OAAgB,QAA2B;CAClE,IAAI,OAAO,UAAU,cAAc,WAAW,KAAA,GAC5C,QAAQ,WAAoB,SAAS,QAAiB,KAAc;CAGtE,MAAM,KAAK;CAEX,IAAI,cAAc,KAAK,GACrB,OAAO,QAAQ,QAAQ,KAAK,CAAC,CAAC,MAAM,WAClC,eAAe,QAAiD,EAAE,CACpE;CAGF,OAAO,eAAe,OAAgD,EAAE;AAC1E;AAoBA,SAAgB,QAAQ,OAAgB,QAA2B;CACjE,IAAI,OAAO,UAAU,cAAc,WAAW,KAAA,GAC5C,QAAQ,WAAoB,QAAQ,QAAiB,KAAc;CAKrE,OAAO,cAAc,OAAgDC,MAAI;AAC3E;AAoBA,SAAgB,aAAa,OAAgB,QAA2B;CACtE,IAAI,OAAO,UAAU,cAAc,WAAW,KAAA,GAC5C,QAAQ,WAAoB,aAAa,QAAiB,KAAc;CAG1E,MAAM,OAAO;CAEb,IAAI,cAAc,KAAK,GACrB,OAAO,QAAQ,QAAQ,KAAK,CAAC,CAAC,MAAM,WAClC,mBAAmB,QAAiD,IAAI,CAC1E;CAGF,OAAO,mBAAmB,OAAgD,IAAI;AAChF;;;ACrKA,SAAgB,IAAI,MAAuD;CAMzE,OAAQ,OAAO,IACb,IACF;AACF;;;;;;;;;;;;;;;;AAiBA,SAAgB,eACd,SACA,SAC4D;CAC5D,MAAM,QAAQ,MAAM,QAAQ;CAE5B,OAAO,OAAO,MAAM,OAAO,iBAAiB,MAAM,QAAQ,SAAS,OAAO,CAAC,CAAC;AAC9E;;;;;;;;;;;;;AAcA,SAAgB,IACd,UAC4D;CAC5D,MAAM,QAAQ,MAAM,QAAQ;CAE5B,OAAO,OAAO,MAAM,OAAO,iBAAiB,MAAM,IAAI,QAAQ,CAAC,CAAC;AAClE;;;;;;;AAQA,MAAa,SAAS;;CAEpB;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;;CAEA;AACF;;;ACjCA,SAAgB,KACd,OACA,GAAG,YACM;CACT,OAAO,WAAW,QAAQ,SAAS,cAAc,UAAU,OAAO,GAAG,KAAK;AAC5E;;;;AC7FA,IAAa,yBAAb,cAA4C,YAAY,wBAAwB,CAAC,CAI9E,CAAC;;;ACGJ,MAAM,oBAAoB,UAAkB,UAC1C,IAAI,uBAAuB;CACzB;CACA;CACA,SAAS,+BAA+B;AAC1C,CAAC;AAEH,MAAa,YAAY,OACvB,cACmD;CAGnD,QAAO,MAFiB,OAAO,iBAAiB,QAAQ,QAAQ,UAAU,CAAC,CAAC,EAAA,CAE3D,SAAS,WAAW,MAAM;AAC7C;AAEA,MAAM,2BACJ,MACA,YAC6C;CAC7C,IAAI,YAAY,KAAA,GACd,OAAO,OAAO,GAAG;CAGnB,OAAO,QAAQ,UAAU,UAAU,iBAAiB,MAAM,KAAK,CAAC;AAClE;AAEA,MAAa,aAAa,OACxB,MACA,UACA,YACsD;CAMtD,QAAO,MALiB,OAAO,WAAW;EACxC,WAAW,QAAQ,QAAQ,QAAQ,QAAQ,CAAC;EAC5C,QAAQ,UAAU,iBAAiB,MAAM,KAAK;CAChD,CAAC,EAAA,CAEgB,SAAS,YAAY,wBAAwB,MAAM,OAAO,CAAC;AAC9E;AAEA,MAAM,uBAAuB,OAC3B,UAEA,YACkB;CAClB,IAAI,CAAC,UACH;CAGF,IAAI;EACF,MAAM,SAAS,OAAO;CACxB,QAAQ,CAKR;AACF;AAEA,MAAa,uBAAuB,OAClC,MAEA,UAEA,qBACuD;CACvD,IAAI,OAAO,QAAQ,IAAI,GAAG;EACxB,IAAI,OAAO,QAAQ,QAAQ,GACzB,MAAM,qBAAqB,kBAAkB,SAAS,KAAK;EAG7D,OAAO,OAAO,IAAmC,KAAK,KAAK;CAC7D;CAEA,IAAI,OAAO,QAAQ,QAAQ,GAAG;EAC5B,MAAM,qBAAqB,kBAAkB,SAAS,KAAK;EAE3D,OAAO,OAAO,IAAmC,SAAS,KAAK;CACjE;CAEA,OAAO,OAAO,GAAkC,KAAK,KAAK;AAC5D;;;;;;;;;;;;;;;;;;;;;;;AC5DA,MAAM,qBAAmD,EACvD,MACA,SACA,KACA,UAAU,iBACV,uBAIA,OAAO,IAAI,mBAAmB;CAC5B,MAAM,WAAW,OAAO,OAAO,MAAM,UAAU,OAAO,CAAC;CAEvD,MAAM,QAAQ,MAAM,KAAK;CAEzB,IAAI,WAAqD,OAAO,GAAG;CAEnE,MAAM,aAAa,YAAY;EAC7B,WAAW,MAAM,WAAW,MAAM,UAAU,OAAO;CACrD,CAAC;CAED,MAAM,OAAO,MAAM,gBAAgB,IAAI,QAAQ,CAAC;CAEhD,MAAM,MAAM,MAAM;CAElB,OAAO,MAAM,qBAAqB,MAAM,UAAU,gBAAgB;AACpE,CAAC;AAEH,MAAa,WAAW;;AAEtB,kBACF;;;ACjCA,MAAM,gBAAgB,UACpB,OAAO,UAAU,YACjB,UAAU,QACV,YAAY,UACX,MAAM,WAAW,QAAQ,MAAM,WAAW;AAE7C,MAAa,0BAA0B,UAAiC;CACtE,IAAI,aAAa,KAAK,KAAK,OAAO,QAAQ,KAAK,GAC7C,OAAO;EACL,QAAQ;EACR,OAAO,MAAM;CACf;CAGF,OAAO,EACL,QAAQ,UACV;AACF;;;ACLA,MAAM,gBAA8B,OAAO,OAAO,EAAE,QAAQ,UAAU,CAAC;AAEvE,IAAM,6BAAN,cAAyC,MAAM;CAC7C,cAAc;EACZ,MAAM,6CAA6C;EAEnD,KAAK,OAAO;CACd;AACF;AAEA,MAAM,0BAA0B,UAAuC;CACrE,IAAI,iBAAiB,gBACnB,OAAO,CAAC,GAAG,MAAM,MAAM;CAGzB,OAAO,CAAC,KAAK;AACf;AAEA,MAAM,wBAAwB,OAC5B,UACA,eACkB;CAClB,IAAI,CAAC,UACH;CAGF,IAAI;EACF,MAAM,SAAS,UAAU;CAC3B,QAAQ,CAER;AACF;AAEA,MAAM,uBACJ,UACA,eACuB;CACvB,SAAS,SAAS;CAElB,eACE,aAAa,IAAI,WAAW,YAAY;EACtC,IAAI,CAAC,SAAS,SACZ,OAAO,MAAM,SAAS,QAAQ;EAGhC,OAAO,MAAM,UAAU,cACf,SAAS,QAAQ,IACtB,UAAU,YAAY,SAAS,QAAS,UAAU,OAAO,CAC5D;CACF,CAAC;AACL;AAEA,IAAM,oBAAN,MAA6F;CAQhF;CACQ;CACA;CATnB;CAEA,6BAA8B,IAAI,IAAsB;CAExD,QAAqD;CAErD,YACE,SACA,WACA,kBACA;EAHS,KAAA,UAAA;EACQ,KAAA,YAAA;EACA,KAAA,mBAAA;CAChB;CAEH,IAAO,SAA8D;EACnE,KAAK,aAAa;EAElB,MAAM,iBAAiB,KAAK,UAAU,KAAK;EAE3C,IAAI;EACJ,IAAI;EAEJ,MAAM,YAAY,IAAI,SAAqB,SAAS,WAAW;GAC7D,mBAAmB;GACnB,kBAAkB;EACpB,CAAC;EAED,KAAK,WAAW,IAAI,SAAS;EAE7B,UAAe,WACP;GACJ,KAAK,WAAW,OAAO,SAAS;EAClC,SACM;GACJ,KAAK,WAAW,OAAO,SAAS;EAClC,CACF;EAEA,IAAI;GAGF,KAFqB,aAAa,gBAAgB,OAEvC,CAAC,CAAC,MACV,UAAU;IACT,iBAAiB,KAAK;GACxB,IACC,UAAU;IACT,gBAAgB,KAAK;GACvB,CACF;EACF,SAAS,OAAO;GACd,gBAAgB,KAAK;EACvB;EAEA,OAAO;CACT;CAEA,aACE,gBACA,SACqB;EACrB,MAAM,UAAU,KAAK,mBACjB;GACE,UAAU;GACV,kBAAkB,KAAK;EACzB,IACA,EACE,UAAU,uBACZ;EAEJ,OAAO,UAAU,sBAAsB,eAAe,IAAI,KAAK,SAAS,OAAO,GAAG,OAAO;CAC3F;CAEA,QAAQ,UAAwB,eAA8B;EAC5D,IAAI,KAAK,gBACP,OAAO,KAAK;EAGd,KAAK,QAAQ;EAEb,MAAM,aAAa,CAAC,GAAG,KAAK,UAAU;EAEtC,KAAK,iBAAiB,KAAK,eAAe,YAAY,OAAO;EAE7D,OAAO,KAAK;CACd;CAEA,MAAc,eACZ,YACA,SACe;EACf,MAAM,WAAsB,CAAC;EAE7B,MAAM,QAAQ,WAAW,UAAU;EAEnC,IAAI;GACF,MAAM,eAAe,IAAI,KAAK,eAAe,KAAK,UAAU,MAAM,OAAO,CAAC;EAC5E,SAAS,OAAO;GACd,SAAS,KAAK,KAAK;EACrB;EAEA,IAAI;GACF,MAAM,KAAK,QAAQ,WAAW;EAChC,SAAS,OAAO;GACd,SAAS,KAAK,KAAK;EACrB;EAEA,KAAK,QAAQ;EAEb,IAAI,SAAS,SAAS,GAAG;GACvB,MAAM,QAAQ,IAAI,kBAAkB,SAAS,QAAQ,sBAAsB,CAAC;GAE5E,MAAM,sBAAsB,KAAK,kBAAkB;IACjD;IACA;GACF,CAAC;GAED,MAAM;EACR;CACF;CAEA,eAA6B;EAC3B,IAAI,KAAK,UAAU,UACjB,MAAM,IAAI,2BAA2B;CAEzC;AACF;;AAGA,MAAa,sBAAsB,OACjC,OACA,SACA,UAA0B,CAAC,MACkB;CAC7C,MAAM,YAAY,MAAM,KAAK;CAC7B,IAAI;CAEJ,IAAI;EACF,KAAK,MAAM,YAAY,MAAM,WAAW;GACtC,UAAU;GAEV,MAAM,QAAQ,SAAS,oBAAoB,UAAU,SAAS,CAAC;EACjE;CACF,SAAS,mBAAmB;EAC1B,MAAM,UAAwB;GAC5B,QAAQ;GACR,OAAO;EACT;EACA,MAAM,gBAA2B,CAAC;EAElC,IAAI;GACF,MAAM,eAAe,IAAI,eAAe,UAAU,MAAM,OAAO,CAAC;EAClE,SAAS,OAAO;GACd,cAAc,KAAK,KAAK;EAC1B;EAEA,IAAI;GACF,MAAM,QAAQ,WAAW;EAC3B,SAAS,OAAO;GACd,cAAc,KAAK,KAAK;EAC1B;EAEA,IAAI,cAAc,SAAS,GAAG;GAC5B,MAAM,gBAAgB,IAAI,kBAAkB,cAAc,QAAQ,sBAAsB,CAAC;GAEzF,MAAM,sBAAsB,QAAQ,kBAAkB;IACpD;IACA,OAAO;GACT,CAAC;EACH;EAEA,IAAI;EAEJ,IAAI,cAAc,WAAW,GAC3B,eAAe,cAAc;OACxB,IAAI,cAAc,SAAS,GAChC,eAAe,IAAI,kBAAkB,cAAc,QAAQ,sBAAsB,CAAC;EAGpF,MAAM,IAAI,uBAAuB,SAAS,SAAS,mBAAmB,YAAY;CACpF;CAEA,OAAO,IAAI,kBAAoC,SAAS,WAAW,QAAQ,gBAAgB;AAC7F;;;;;;;;;;;;;;;;;;ACnPA,IAAa,UAAb,MAAa,QAA4D;CAClC;CAArC,YAAoB,QAAkD;EAAjC,KAAA,SAAA;CAAkC;;;;;;;;;;;CAYvE,aAAa,KACX,OACA,SACA,UAA0B,CAAC,GACS;EACpC,MAAM,SAAS,MAAM,oBAAoB,OAAO,SAAS,OAAO;EAEhE,OAAO,IAAI,QAA0B,MAAM;CAC7C;;;;;;;CAQA,aAAa,IACX,OACA,SACA,SACA,UAA0B,CAAC,GACN;EACrB,MAAM,UAAU,MAAM,QAAQ,KAAK,OAAO,SAAS,OAAO;EAE1D,IAAI;EACJ,IAAI,kBAAkB;EACtB,IAAI;EACJ,IAAI;EAEJ,IAAI;GACF,QAAQ,MAAM,QAAQ,aAAa,YAAY;IAC7C,IAAI;KACF,MAAM,eAAe,MAAM,QAAQ;KAEnC,iBAAiB,uBAAuB,YAAY;KAEpD,OAAO;IACT,SAAS,OAAO;KACd,iBAAiB;MACf,QAAQ;MACR;KACF;KAEA,MAAM;IACR;GACF,CAAC;EACH,SAAS,OAAO;GACd,kBAAkB;GAClB,mBAAmB;EACrB;EAEA,MAAM,UACJ,kBACC;GACC,QAAQ;GACR,OAAO;EACT;EAEF,IAAI;GACF,MAAM,QAAQ,mBAAmB,OAAO;EAC1C,SAAS,iBAAiB;GACxB,IAAI,CAAC,mBAAmB,QAAQ,WAAW,WACzC,MAAM;EAEV;EAEA,IAAI,iBACF,MAAM;EAGR,OAAO;CACT;;CAGA,IAAO,SAA8D;EACnE,OAAO,KAAK,OAAO,IAAI,OAAO;CAChC;CAEA,aAAwB,SAAwD;EAC9E,OAAO,KAAK,OAAO,IAAI,OAAyC;CAClE;;CAGA,UAAyB;EACvB,OAAO,KAAK,OAAO,QAAQ;CAC7B;CAEA,mBAA2B,SAAsC;EAC/D,OAAO,KAAK,OAAO,QAAQ,OAAO;CACpC;AACF"}
@@ -0,0 +1,26 @@
1
+ import { a as ServiceTagCollisionError } from "./errors-GR3K_nRu.mjs";
2
+ //#region src/layer/internal-identity.ts
3
+ const serviceMemberNames = (token) => {
4
+ const names = /* @__PURE__ */ new Set();
5
+ let prototype = token.prototype;
6
+ while (prototype && prototype !== Object.prototype) {
7
+ for (const name of Object.getOwnPropertyNames(prototype)) if (name !== "constructor") names.add(name);
8
+ for (const symbol of Object.getOwnPropertySymbols(prototype)) names.add(symbol);
9
+ prototype = Object.getPrototypeOf(prototype);
10
+ }
11
+ return [...names];
12
+ };
13
+ /**
14
+ * Check the runtime portion of a same-tag association before returning it.
15
+ * TypeScript remains authoritative for full structural compatibility; this
16
+ * check catches the common incompatible-method collision after erasure.
17
+ */
18
+ const assertServiceCompatibility = (requested, registered, instance) => {
19
+ if (requested === registered || requested.serviceTag !== registered.serviceTag) return;
20
+ if (typeof instance !== "object" && typeof instance !== "function" || instance === null) throw new ServiceTagCollisionError(registered, requested);
21
+ for (const name of serviceMemberNames(requested)) if (!(name in instance)) throw new ServiceTagCollisionError(registered, requested);
22
+ };
23
+ //#endregion
24
+ export { assertServiceCompatibility as t };
25
+
26
+ //# sourceMappingURL=internal-identity-BnZC3Au-.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-identity-BnZC3Au-.mjs","names":[],"sources":["../src/layer/internal-identity.ts"],"sourcesContent":["import type { AnyServiceToken } from '../service'\n\nimport { ServiceTagCollisionError } from './errors'\n\nconst serviceMemberNames = (token: AnyServiceToken): readonly (string | symbol)[] => {\n const names = new Set<string | symbol>()\n let prototype = token.prototype\n\n while (prototype && prototype !== Object.prototype) {\n for (const name of Object.getOwnPropertyNames(prototype)) {\n if (name !== 'constructor') {\n names.add(name)\n }\n }\n\n for (const symbol of Object.getOwnPropertySymbols(prototype)) {\n names.add(symbol)\n }\n\n prototype = Object.getPrototypeOf(prototype)\n }\n\n return [...names]\n}\n\n/**\n * Check the runtime portion of a same-tag association before returning it.\n * TypeScript remains authoritative for full structural compatibility; this\n * check catches the common incompatible-method collision after erasure.\n */\nexport const assertServiceCompatibility = (\n requested: AnyServiceToken,\n registered: AnyServiceToken,\n instance: unknown\n): void => {\n if (requested === registered || requested.serviceTag !== registered.serviceTag) {\n return\n }\n\n if ((typeof instance !== 'object' && typeof instance !== 'function') || instance === null) {\n throw new ServiceTagCollisionError(registered, requested)\n }\n\n for (const name of serviceMemberNames(requested)) {\n if (!(name in instance)) {\n throw new ServiceTagCollisionError(registered, requested)\n }\n }\n}\n"],"mappings":";;AAIA,MAAM,sBAAsB,UAAyD;CACnF,MAAM,wBAAQ,IAAI,IAAqB;CACvC,IAAI,YAAY,MAAM;CAEtB,OAAO,aAAa,cAAc,OAAO,WAAW;EAClD,KAAK,MAAM,QAAQ,OAAO,oBAAoB,SAAS,GACrD,IAAI,SAAS,eACX,MAAM,IAAI,IAAI;EAIlB,KAAK,MAAM,UAAU,OAAO,sBAAsB,SAAS,GACzD,MAAM,IAAI,MAAM;EAGlB,YAAY,OAAO,eAAe,SAAS;CAC7C;CAEA,OAAO,CAAC,GAAG,KAAK;AAClB;;;;;;AAOA,MAAa,8BACX,WACA,YACA,aACS;CACT,IAAI,cAAc,cAAc,UAAU,eAAe,WAAW,YAClE;CAGF,IAAK,OAAO,aAAa,YAAY,OAAO,aAAa,cAAe,aAAa,MACnF,MAAM,IAAI,yBAAyB,YAAY,SAAS;CAG1D,KAAK,MAAM,QAAQ,mBAAmB,SAAS,GAC7C,IAAI,EAAE,QAAQ,WACZ,MAAM,IAAI,yBAAyB,YAAY,SAAS;AAG9D"}
@@ -1,11 +1,20 @@
1
- import { V as AnyServiceToken, t as LayerBackend, v as LayerProvider } from "./index-BYQKfyeJ.mjs";
1
+ import { V as AnyServiceToken, t as LayerBackend, v as LayerRegistration } from "./index-D77AvuBl.mjs";
2
2
  //#region src/testing/memory-layer-backend.d.ts
3
+ /**
4
+ * In-memory Layer backend for tests and small local programs.
5
+ *
6
+ * Providers are lazy, instances are cached by Service tag, and all cached
7
+ * state is cleared by `disposeAll()`.
8
+ */
3
9
  declare class MemoryLayerBackend implements LayerBackend {
4
10
  private readonly providers;
5
11
  private readonly instances;
6
12
  private readonly pending;
7
- register(provider: LayerProvider): void;
13
+ /** Register a provider, rejecting duplicate or colliding Service tags. */
14
+ register(registration: LayerRegistration): void;
15
+ /** Resolve and cache a provider instance by Service tag. */
8
16
  resolve<T extends AnyServiceToken>(token: T): Promise<InstanceType<T>>;
17
+ /** Clear pending acquisitions, cached instances, and provider registrations. */
9
18
  disposeAll(): Promise<void>;
10
19
  }
11
20
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.mts","names":[],"sources":["../src/testing/memory-layer-backend.ts"],"mappings":";;cAIa,8BAA8B;mBACxB;mBAEA;mBAEA;EAEjB,SAAS,UAAU;EAQb,QAAQ,UAAU,iBAAiB,OAAO,IAAI,QAAQ,aAAa;EAgCnE,cAAc"}
1
+ {"version":3,"file":"testing.d.mts","names":[],"sources":["../src/testing/memory-layer-backend.ts"],"mappings":";;;;;;;;cAiBa,8BAA8B;mBACxB;mBAEA;mBAEA;;EAGjB,SAAS,cAAc;;EAgBjB,QAAQ,UAAU,iBAAiB,OAAO,IAAI,QAAQ,aAAa;;EAyCnE,cAAc"}
package/dist/testing.mjs CHANGED
@@ -1,28 +1,49 @@
1
- import { n as DuplicateServiceError, o as ServiceNotFoundError } from "./errors-DlHCwICc.mjs";
1
+ import { a as ServiceTagCollisionError, o as ServiceNotFoundError, t as DuplicateServiceError } from "./errors-GR3K_nRu.mjs";
2
+ import { t as assertServiceCompatibility } from "./internal-identity-BnZC3Au-.mjs";
2
3
  //#region src/testing/memory-layer-backend.ts
4
+ /**
5
+ * In-memory Layer backend for tests and small local programs.
6
+ *
7
+ * Providers are lazy, instances are cached by Service tag, and all cached
8
+ * state is cleared by `disposeAll()`.
9
+ */
3
10
  var MemoryLayerBackend = class {
4
11
  providers = /* @__PURE__ */ new Map();
5
12
  instances = /* @__PURE__ */ new Map();
6
13
  pending = /* @__PURE__ */ new Map();
7
- register(provider) {
8
- if (this.providers.has(provider.service)) throw new DuplicateServiceError(provider.service);
9
- this.providers.set(provider.service, provider);
14
+ /** Register a provider, rejecting duplicate or colliding Service tags. */
15
+ register(registration) {
16
+ const tag = registration.service.serviceTag;
17
+ const existing = this.providers.get(tag);
18
+ if (existing) {
19
+ if (existing.service !== registration.service) throw new ServiceTagCollisionError(existing.service, registration.service);
20
+ throw new DuplicateServiceError(registration.service);
21
+ }
22
+ this.providers.set(tag, registration);
10
23
  }
24
+ /** Resolve and cache a provider instance by Service tag. */
11
25
  async resolve(token) {
12
- if (this.instances.has(token)) return this.instances.get(token);
13
- const pending = this.pending.get(token);
14
- if (pending) return await pending;
15
- const provider = this.providers.get(token);
26
+ const tag = token.serviceTag;
27
+ const provider = this.providers.get(tag);
16
28
  if (!provider) throw new ServiceNotFoundError(token);
29
+ const validate = (instance) => {
30
+ assertServiceCompatibility(token, provider.service, instance);
31
+ return instance;
32
+ };
33
+ if (this.instances.has(tag)) return validate(this.instances.get(tag));
34
+ const pending = this.pending.get(tag);
35
+ if (pending) return validate(await pending);
17
36
  const acquisition = Promise.resolve(provider.acquire()).then((instance) => {
18
- this.instances.set(token, instance);
37
+ validate(instance);
38
+ this.instances.set(tag, instance);
19
39
  return instance;
20
40
  }).finally(() => {
21
- this.pending.delete(token);
41
+ this.pending.delete(tag);
22
42
  });
23
- this.pending.set(token, acquisition);
24
- return await acquisition;
43
+ this.pending.set(tag, acquisition);
44
+ return validate(await acquisition);
25
45
  }
46
+ /** Clear pending acquisitions, cached instances, and provider registrations. */
26
47
  async disposeAll() {
27
48
  if (this.pending.size > 0) await Promise.allSettled(this.pending.values());
28
49
  this.instances.clear();
@@ -1 +1 @@
1
- {"version":3,"file":"testing.mjs","names":[],"sources":["../src/testing/memory-layer-backend.ts"],"sourcesContent":["import { DuplicateServiceError, type LayerBackend, type LayerProvider } from '../layer'\n\nimport { ServiceNotFoundError, type AnyServiceToken } from '../service'\n\nexport class MemoryLayerBackend implements LayerBackend {\n private readonly providers = new Map<AnyServiceToken, LayerProvider>()\n\n private readonly instances = new Map<AnyServiceToken, unknown>()\n\n private readonly pending = new Map<AnyServiceToken, Promise<unknown>>()\n\n register(provider: LayerProvider): void {\n if (this.providers.has(provider.service)) {\n throw new DuplicateServiceError(provider.service)\n }\n\n this.providers.set(provider.service, provider)\n }\n\n async resolve<T extends AnyServiceToken>(token: T): Promise<InstanceType<T>> {\n if (this.instances.has(token)) {\n return this.instances.get(token) as InstanceType<T>\n }\n\n const pending = this.pending.get(token)\n\n if (pending) {\n return (await pending) as InstanceType<T>\n }\n\n const provider = this.providers.get(token)\n\n if (!provider) {\n throw new ServiceNotFoundError(token)\n }\n\n const acquisition = Promise.resolve(provider.acquire())\n .then((instance) => {\n this.instances.set(token, instance)\n\n return instance\n })\n .finally(() => {\n this.pending.delete(token)\n })\n\n this.pending.set(token, acquisition)\n\n return (await acquisition) as InstanceType<T>\n }\n\n async disposeAll(): Promise<void> {\n if (this.pending.size > 0) {\n await Promise.allSettled(this.pending.values())\n }\n\n this.instances.clear()\n this.pending.clear()\n this.providers.clear()\n }\n}\n"],"mappings":";;AAIA,IAAa,qBAAb,MAAwD;CACtD,4BAA6B,IAAI,IAAoC;CAErE,4BAA6B,IAAI,IAA8B;CAE/D,0BAA2B,IAAI,IAAuC;CAEtE,SAAS,UAA+B;EACtC,IAAI,KAAK,UAAU,IAAI,SAAS,OAAO,GACrC,MAAM,IAAI,sBAAsB,SAAS,OAAO;EAGlD,KAAK,UAAU,IAAI,SAAS,SAAS,QAAQ;CAC/C;CAEA,MAAM,QAAmC,OAAoC;EAC3E,IAAI,KAAK,UAAU,IAAI,KAAK,GAC1B,OAAO,KAAK,UAAU,IAAI,KAAK;EAGjC,MAAM,UAAU,KAAK,QAAQ,IAAI,KAAK;EAEtC,IAAI,SACF,OAAQ,MAAM;EAGhB,MAAM,WAAW,KAAK,UAAU,IAAI,KAAK;EAEzC,IAAI,CAAC,UACH,MAAM,IAAI,qBAAqB,KAAK;EAGtC,MAAM,cAAc,QAAQ,QAAQ,SAAS,QAAQ,CAAC,CAAC,CACpD,MAAM,aAAa;GAClB,KAAK,UAAU,IAAI,OAAO,QAAQ;GAElC,OAAO;EACT,CAAC,CAAC,CACD,cAAc;GACb,KAAK,QAAQ,OAAO,KAAK;EAC3B,CAAC;EAEH,KAAK,QAAQ,IAAI,OAAO,WAAW;EAEnC,OAAQ,MAAM;CAChB;CAEA,MAAM,aAA4B;EAChC,IAAI,KAAK,QAAQ,OAAO,GACtB,MAAM,QAAQ,WAAW,KAAK,QAAQ,OAAO,CAAC;EAGhD,KAAK,UAAU,MAAM;EACrB,KAAK,QAAQ,MAAM;EACnB,KAAK,UAAU,MAAM;CACvB;AACF"}
1
+ {"version":3,"file":"testing.mjs","names":[],"sources":["../src/testing/memory-layer-backend.ts"],"sourcesContent":["import {\n DuplicateServiceError,\n ServiceTagCollisionError,\n type LayerBackend,\n type LayerRegistration\n} from '../layer'\n\nimport { ServiceNotFoundError, type AnyServiceToken } from '../service'\n\nimport { assertServiceCompatibility } from '../layer/internal-identity'\n\n/**\n * In-memory Layer backend for tests and small local programs.\n *\n * Providers are lazy, instances are cached by Service tag, and all cached\n * state is cleared by `disposeAll()`.\n */\nexport class MemoryLayerBackend implements LayerBackend {\n private readonly providers = new Map<string, LayerRegistration>()\n\n private readonly instances = new Map<string, unknown>()\n\n private readonly pending = new Map<string, Promise<unknown>>()\n\n /** Register a provider, rejecting duplicate or colliding Service tags. */\n register(registration: LayerRegistration): void {\n const tag = registration.service.serviceTag\n const existing = this.providers.get(tag)\n\n if (existing) {\n if (existing.service !== registration.service) {\n throw new ServiceTagCollisionError(existing.service, registration.service)\n }\n\n throw new DuplicateServiceError(registration.service)\n }\n\n this.providers.set(tag, registration)\n }\n\n /** Resolve and cache a provider instance by Service tag. */\n async resolve<T extends AnyServiceToken>(token: T): Promise<InstanceType<T>> {\n const tag = token.serviceTag\n const provider = this.providers.get(tag)\n\n if (!provider) {\n throw new ServiceNotFoundError(token)\n }\n\n const validate = (instance: unknown): InstanceType<T> => {\n assertServiceCompatibility(token, provider.service, instance)\n\n return instance as InstanceType<T>\n }\n\n if (this.instances.has(tag)) {\n return validate(this.instances.get(tag))\n }\n\n const pending = this.pending.get(tag)\n\n if (pending) {\n return validate(await pending)\n }\n\n const acquisition = Promise.resolve(provider.acquire())\n .then((instance) => {\n validate(instance)\n this.instances.set(tag, instance)\n\n return instance\n })\n .finally(() => {\n this.pending.delete(tag)\n })\n\n this.pending.set(tag, acquisition)\n\n return validate(await acquisition)\n }\n\n /** Clear pending acquisitions, cached instances, and provider registrations. */\n async disposeAll(): Promise<void> {\n if (this.pending.size > 0) {\n await Promise.allSettled(this.pending.values())\n }\n\n this.instances.clear()\n this.pending.clear()\n this.providers.clear()\n }\n}\n"],"mappings":";;;;;;;;;AAiBA,IAAa,qBAAb,MAAwD;CACtD,4BAA6B,IAAI,IAA+B;CAEhE,4BAA6B,IAAI,IAAqB;CAEtD,0BAA2B,IAAI,IAA8B;;CAG7D,SAAS,cAAuC;EAC9C,MAAM,MAAM,aAAa,QAAQ;EACjC,MAAM,WAAW,KAAK,UAAU,IAAI,GAAG;EAEvC,IAAI,UAAU;GACZ,IAAI,SAAS,YAAY,aAAa,SACpC,MAAM,IAAI,yBAAyB,SAAS,SAAS,aAAa,OAAO;GAG3E,MAAM,IAAI,sBAAsB,aAAa,OAAO;EACtD;EAEA,KAAK,UAAU,IAAI,KAAK,YAAY;CACtC;;CAGA,MAAM,QAAmC,OAAoC;EAC3E,MAAM,MAAM,MAAM;EAClB,MAAM,WAAW,KAAK,UAAU,IAAI,GAAG;EAEvC,IAAI,CAAC,UACH,MAAM,IAAI,qBAAqB,KAAK;EAGtC,MAAM,YAAY,aAAuC;GACvD,2BAA2B,OAAO,SAAS,SAAS,QAAQ;GAE5D,OAAO;EACT;EAEA,IAAI,KAAK,UAAU,IAAI,GAAG,GACxB,OAAO,SAAS,KAAK,UAAU,IAAI,GAAG,CAAC;EAGzC,MAAM,UAAU,KAAK,QAAQ,IAAI,GAAG;EAEpC,IAAI,SACF,OAAO,SAAS,MAAM,OAAO;EAG/B,MAAM,cAAc,QAAQ,QAAQ,SAAS,QAAQ,CAAC,CAAC,CACpD,MAAM,aAAa;GAClB,SAAS,QAAQ;GACjB,KAAK,UAAU,IAAI,KAAK,QAAQ;GAEhC,OAAO;EACT,CAAC,CAAC,CACD,cAAc;GACb,KAAK,QAAQ,OAAO,GAAG;EACzB,CAAC;EAEH,KAAK,QAAQ,IAAI,KAAK,WAAW;EAEjC,OAAO,SAAS,MAAM,WAAW;CACnC;;CAGA,MAAM,aAA4B;EAChC,IAAI,KAAK,QAAQ,OAAO,GACtB,MAAM,QAAQ,WAAW,KAAK,QAAQ,OAAO,CAAC;EAGhD,KAAK,UAAU,MAAM;EACrB,KAAK,QAAQ,MAAM;EACnB,KAAK,UAAU,MAAM;CACvB;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-effect",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Effect-inspired application architecture for better-result with typechecked Services and environments, scoped resource lifetimes, and pluggable DI backends.",
5
5
  "keywords": [
6
6
  "better-result",
@@ -1,67 +0,0 @@
1
- //#region src/service/errors.ts
2
- var ServiceRuntimeNotConfiguredError = class extends Error {
3
- constructor() {
4
- super("No ServiceResolver is available in the current runtime context");
5
- this.name = "ServiceRuntimeNotConfiguredError";
6
- }
7
- };
8
- var ServiceNotFoundError = class extends Error {
9
- service;
10
- constructor(service) {
11
- super(`Service "${service.name}" was not provided`);
12
- this.service = service;
13
- this.name = "ServiceNotFoundError";
14
- }
15
- };
16
- //#endregion
17
- //#region src/layer/errors.ts
18
- var DuplicateServiceError = class extends Error {
19
- service;
20
- constructor(service) {
21
- super(`Duplicate service "${service.name}"`);
22
- this.service = service;
23
- this.name = "DuplicateServiceError";
24
- }
25
- };
26
- var LayerRegistrationError = class extends Error {
27
- service;
28
- registrationCause;
29
- cleanupCause;
30
- constructor(service, registrationCause, cleanupCause) {
31
- super(service ? `Failed to register service "${service.name}"` : "Failed to build Layer", { cause: registrationCause });
32
- this.service = service;
33
- this.registrationCause = registrationCause;
34
- this.cleanupCause = cleanupCause;
35
- this.name = "LayerRegistrationError";
36
- }
37
- };
38
- var LayerDisposeError = class extends Error {
39
- causes;
40
- constructor(causes) {
41
- super(`Failed to dispose Layer (${causes.length} error${causes.length === 1 ? "" : "s"})`);
42
- this.causes = causes;
43
- this.name = "LayerDisposeError";
44
- }
45
- };
46
- var LayerGeneratorYieldError = class extends Error {
47
- service;
48
- constructor(service) {
49
- super(`Layer.gen("${service.name}") yielded an unsupported value`);
50
- this.service = service;
51
- this.name = "LayerGeneratorYieldError";
52
- }
53
- };
54
- /**
55
- * @deprecated The public managed handle is `Runtime`; this error remains for
56
- * compatibility with low-level Layer integrations.
57
- */
58
- var BuiltLayerDisposedError = class extends Error {
59
- constructor() {
60
- super("Cannot run a program using a disposed Layer");
61
- this.name = "BuiltLayerDisposedError";
62
- }
63
- };
64
- //#endregion
65
- export { LayerRegistrationError as a, LayerGeneratorYieldError as i, DuplicateServiceError as n, ServiceNotFoundError as o, LayerDisposeError as r, ServiceRuntimeNotConfiguredError as s, BuiltLayerDisposedError as t };
66
-
67
- //# sourceMappingURL=errors-DlHCwICc.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors-DlHCwICc.mjs","names":[],"sources":["../src/service/errors.ts","../src/layer/errors.ts"],"sourcesContent":["import type { AnyServiceToken } from './types'\n\nexport class ServiceRuntimeNotConfiguredError extends Error {\n constructor() {\n super('No ServiceResolver is available in the current runtime context')\n\n this.name = 'ServiceRuntimeNotConfiguredError'\n }\n}\n\nexport class ServiceNotFoundError extends Error {\n constructor(readonly service: AnyServiceToken) {\n super(`Service \"${service.name}\" was not provided`)\n\n this.name = 'ServiceNotFoundError'\n }\n}\n","import type { ServiceClass } from '../service'\n\nexport class DuplicateServiceError extends Error {\n constructor(readonly service: ServiceClass<any>) {\n super(`Duplicate service \"${service.name}\"`)\n\n this.name = 'DuplicateServiceError'\n }\n}\n\nexport class LayerRegistrationError extends Error {\n constructor(\n readonly service: ServiceClass<any> | undefined,\n readonly registrationCause: unknown,\n readonly cleanupCause?: unknown\n ) {\n super(service ? `Failed to register service \"${service.name}\"` : 'Failed to build Layer', {\n cause: registrationCause\n })\n\n this.name = 'LayerRegistrationError'\n }\n}\n\nexport class LayerDisposeError extends Error {\n constructor(readonly causes: readonly unknown[]) {\n super(`Failed to dispose Layer (${causes.length} error${causes.length === 1 ? '' : 's'})`)\n\n this.name = 'LayerDisposeError'\n }\n}\n\nexport class LayerGeneratorYieldError extends Error {\n constructor(readonly service: ServiceClass<any>) {\n super(`Layer.gen(\"${service.name}\") yielded an unsupported value`)\n\n this.name = 'LayerGeneratorYieldError'\n }\n}\n\n/**\n * @deprecated The public managed handle is `Runtime`; this error remains for\n * compatibility with low-level Layer integrations.\n */\nexport class BuiltLayerDisposedError extends Error {\n constructor() {\n super('Cannot run a program using a disposed Layer')\n\n this.name = 'BuiltLayerDisposedError'\n }\n}\n"],"mappings":";AAEA,IAAa,mCAAb,cAAsD,MAAM;CAC1D,cAAc;EACZ,MAAM,gEAAgE;EAEtE,KAAK,OAAO;CACd;AACF;AAEA,IAAa,uBAAb,cAA0C,MAAM;CACzB;CAArB,YAAY,SAAmC;EAC7C,MAAM,YAAY,QAAQ,KAAK,mBAAmB;EAD/B,KAAA,UAAA;EAGnB,KAAK,OAAO;CACd;AACF;;;ACdA,IAAa,wBAAb,cAA2C,MAAM;CAC1B;CAArB,YAAY,SAAqC;EAC/C,MAAM,sBAAsB,QAAQ,KAAK,EAAE;EADxB,KAAA,UAAA;EAGnB,KAAK,OAAO;CACd;AACF;AAEA,IAAa,yBAAb,cAA4C,MAAM;CAErC;CACA;CACA;CAHX,YACE,SACA,mBACA,cACA;EACA,MAAM,UAAU,+BAA+B,QAAQ,KAAK,KAAK,yBAAyB,EACxF,OAAO,kBACT,CAAC;EANQ,KAAA,UAAA;EACA,KAAA,oBAAA;EACA,KAAA,eAAA;EAMT,KAAK,OAAO;CACd;AACF;AAEA,IAAa,oBAAb,cAAuC,MAAM;CACtB;CAArB,YAAY,QAAqC;EAC/C,MAAM,4BAA4B,OAAO,OAAO,QAAQ,OAAO,WAAW,IAAI,KAAK,IAAI,EAAE;EADtE,KAAA,SAAA;EAGnB,KAAK,OAAO;CACd;AACF;AAEA,IAAa,2BAAb,cAA8C,MAAM;CAC7B;CAArB,YAAY,SAAqC;EAC/C,MAAM,cAAc,QAAQ,KAAK,gCAAgC;EAD9C,KAAA,UAAA;EAGnB,KAAK,OAAO;CACd;AACF;;;;;AAMA,IAAa,0BAAb,cAA6C,MAAM;CACjD,cAAc;EACZ,MAAM,6CAA6C;EAEnD,KAAK,OAAO;CACd;AACF"}