better-effect 0.2.0 → 0.4.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":[],"sources":["../src/service/runtime.ts","../src/service/service.ts","../src/layer/internal.ts","../src/layer/layer.ts","../src/layer/runtime.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 { ServiceToken } from './types'\n\nexport function Service<Self>() {\n return class {\n // oxlint-disable-next-line require-yield\n static async *[Symbol.asyncIterator](): AsyncGenerator<never, Self, unknown> {\n return await ServiceRuntime.resolve(this as unknown as ServiceToken<Self>)\n }\n }\n}\n","import { LayerGeneratorYieldError } from './errors'\n\nimport type { ServiceClass } from '../service'\n\nimport type { LayerGenerator } from './types'\n\nexport const runLayerGenerator = async <S extends ServiceClass<any>>(\n service: S,\n factory: LayerGenerator<S>\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 { ServiceClass } from '../service'\nimport type { MaybePromise } from '../utils/types'\n\nimport { DuplicateServiceError } from './errors'\n\nimport { runLayerGenerator } from './internal'\n\nimport type { LayerGenerator, LayerProvider } from './types'\n\nexport class Layer {\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 {\n return new Layer([\n {\n service,\n acquire\n }\n ])\n }\n\n static succeed<S extends ServiceClass<any>>(service: S, instance: InstanceType<S>): Layer {\n return Layer.make(service, () => instance)\n }\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 {\n return new Layer([\n {\n service,\n acquire,\n\n release: (instance) => release(instance as InstanceType<S>)\n }\n ])\n }\n\n static gen<S extends ServiceClass<any>>(service: S, factory: LayerGenerator<S>): Layer {\n return Layer.make(service, () => runLayerGenerator(service, factory))\n }\n\n static merge(...layers: readonly Layer[]): Layer {\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: Layer, ...overrides: readonly Layer[]): Layer {\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","import { ServiceRuntime } from '../service'\n\nimport { BuiltLayerDisposedError, LayerDisposeError, LayerRegistrationError } from './errors'\n\nimport type { LayerBackend } from './backend'\n\nimport type { Layer } from './layer'\n\nimport type { LayerProvider } from './types'\n\nexport interface BuiltLayer {\n readonly backend: LayerBackend\n\n run<A>(program: () => A): A\n\n dispose(): Promise<void>\n}\n\nconst normalizeDisposeCauses = (cause: unknown): readonly unknown[] => {\n if (cause instanceof AggregateError) {\n return [...cause.errors]\n }\n\n return [cause]\n}\n\nclass BuiltLayerImpl implements BuiltLayer {\n private disposePromise: Promise<void> | undefined\n\n private disposed = false\n\n constructor(readonly backend: LayerBackend) {}\n\n run<A>(program: () => A): A {\n if (this.disposed || this.disposePromise) {\n throw new BuiltLayerDisposedError()\n }\n\n return ServiceRuntime.run(this.backend, program)\n }\n\n dispose(): Promise<void> {\n if (this.disposePromise) {\n return this.disposePromise\n }\n\n this.disposePromise = this.performDispose()\n\n return this.disposePromise\n }\n\n private async performDispose(): Promise<void> {\n try {\n await this.backend.disposeAll()\n } catch (cause) {\n throw new LayerDisposeError(normalizeDisposeCauses(cause))\n } finally {\n this.disposed = true\n }\n }\n}\n\nexport const buildLayer = async (layer: Layer, backend: LayerBackend): Promise<BuiltLayer> => {\n let current: LayerProvider | undefined\n\n try {\n for (const provider of layer.providers) {\n current = provider\n\n await backend.register(provider)\n }\n } catch (registrationCause) {\n let cleanupCause: unknown\n\n try {\n await backend.disposeAll()\n } catch (cause) {\n cleanupCause = cause\n }\n\n throw new LayerRegistrationError(current?.service, registrationCause, cleanupCause)\n }\n\n return new BuiltLayerImpl(backend)\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 type {\n AsyncResult,\n DisposableResource,\n MaybePromise,\n ReleaseFailureObserver,\n ReleaseOutcome\n} from './types'\n\nexport const disposeResource = (resource: unknown): MaybePromise<void> => {\n const candidate = Object(resource) as DisposableResource\n\n const dispose = candidate[Symbol.asyncDispose] ?? candidate[Symbol.dispose]\n\n return dispose?.call(candidate)\n}\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 { 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 const used = await runResult(() => use(resource))\n const released = await runRelease(name, resource, release)\n const result = await combineUseAndRelease(used, released, onReleaseFailure)\n\n return result\n })\n\nexport const Resource = {\n acquireUseRelease\n} as const\n","import { buildLayer, type BuiltLayer, type Layer, type LayerBackend } from '../layer'\n\nexport class Runtime {\n private constructor(private readonly built: BuiltLayer) {}\n\n static async make(layer: Layer, backend: LayerBackend): Promise<Runtime> {\n const built = await buildLayer(layer, backend)\n\n return new Runtime(built)\n }\n\n static async run<A>(\n layer: Layer,\n backend: LayerBackend,\n program: () => A | PromiseLike<A>\n ): Promise<Awaited<A>> {\n const runtime = await Runtime.make(layer, backend)\n\n try {\n return await runtime.run(program)\n } finally {\n await runtime.dispose()\n }\n }\n\n run<A>(program: () => A): A {\n return this.built.run(program)\n }\n\n dispose(): Promise<void> {\n return this.built.dispose()\n }\n}\n"],"mappings":"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"}
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,10 +1,9 @@
1
- import { r as LayerProvider, s as AnyServiceToken, t as LayerBackend } from "./backend-CNAls62W.mjs";
1
+ import { V as AnyServiceToken, t as LayerBackend, v as LayerProvider } from "./index-BYQKfyeJ.mjs";
2
2
  //#region src/testing/memory-layer-backend.d.ts
3
3
  declare class MemoryLayerBackend implements LayerBackend {
4
4
  private readonly providers;
5
5
  private readonly instances;
6
6
  private readonly pending;
7
- private readonly resolutionOrder;
8
7
  register(provider: LayerProvider): void;
9
8
  resolve<T extends AnyServiceToken>(token: T): Promise<InstanceType<T>>;
10
9
  disposeAll(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.mts","names":[],"sources":["../src/testing/memory-layer-backend.ts"],"mappings":";;cAIa,8BAA8B;mBACxB;mBAEA;mBAEA;mBAEA;EAEjB,SAAS,UAAU;EAQb,QAAQ,UAAU,iBAAiB,OAAO,IAAI,QAAQ,aAAa;EAkCnE,cAAc"}
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"}
package/dist/testing.mjs CHANGED
@@ -1,10 +1,9 @@
1
- import { n as DuplicateServiceError, o as ServiceNotFoundError } from "./errors-CnvKqBpb.mjs";
1
+ import { n as DuplicateServiceError, o as ServiceNotFoundError } from "./errors-DlHCwICc.mjs";
2
2
  //#region src/testing/memory-layer-backend.ts
3
3
  var MemoryLayerBackend = class {
4
4
  providers = /* @__PURE__ */ new Map();
5
5
  instances = /* @__PURE__ */ new Map();
6
6
  pending = /* @__PURE__ */ new Map();
7
- resolutionOrder = [];
8
7
  register(provider) {
9
8
  if (this.providers.has(provider.service)) throw new DuplicateServiceError(provider.service);
10
9
  this.providers.set(provider.service, provider);
@@ -17,7 +16,6 @@ var MemoryLayerBackend = class {
17
16
  if (!provider) throw new ServiceNotFoundError(token);
18
17
  const acquisition = Promise.resolve(provider.acquire()).then((instance) => {
19
18
  this.instances.set(token, instance);
20
- this.resolutionOrder.push(token);
21
19
  return instance;
22
20
  }).finally(() => {
23
21
  this.pending.delete(token);
@@ -27,23 +25,9 @@ var MemoryLayerBackend = class {
27
25
  }
28
26
  async disposeAll() {
29
27
  if (this.pending.size > 0) await Promise.allSettled(this.pending.values());
30
- const errors = [];
31
- for (let index = this.resolutionOrder.length - 1; index >= 0; index--) {
32
- const token = this.resolutionOrder[index];
33
- if (!token) continue;
34
- const instance = this.instances.get(token);
35
- const provider = this.providers.get(token);
36
- if (instance === void 0 || !provider?.release) continue;
37
- try {
38
- await provider.release(instance);
39
- } catch (cause) {
40
- errors.push(cause);
41
- }
42
- }
43
28
  this.instances.clear();
44
29
  this.pending.clear();
45
- this.resolutionOrder.splice(0);
46
- if (errors.length > 0) throw new AggregateError(errors, "Failed to dispose one or more services");
30
+ this.providers.clear();
47
31
  }
48
32
  };
49
33
  //#endregion
@@ -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 private readonly resolutionOrder: AnyServiceToken[] = []\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 this.resolutionOrder.push(token)\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 const errors: unknown[] = []\n\n for (let index = this.resolutionOrder.length - 1; index >= 0; index--) {\n const token = this.resolutionOrder[index]\n\n if (!token) {\n continue\n }\n\n const instance = this.instances.get(token)\n\n const provider = this.providers.get(token)\n\n if (instance === undefined || !provider?.release) {\n continue\n }\n\n try {\n await provider.release(instance)\n } catch (cause) {\n errors.push(cause)\n }\n }\n\n this.instances.clear()\n this.pending.clear()\n\n this.resolutionOrder.splice(0)\n\n if (errors.length > 0) {\n throw new AggregateError(errors, 'Failed to dispose one or more services')\n }\n }\n}\n"],"mappings":";;AAIA,IAAa,qBAAb,MAAwD;CACtD,4BAA6B,IAAI,IAAoC;CAErE,4BAA6B,IAAI,IAA8B;CAE/D,0BAA2B,IAAI,IAAuC;CAEtE,kBAAsD,CAAC;CAEvD,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,KAAK,gBAAgB,KAAK,KAAK;GAE/B,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,MAAM,SAAoB,CAAC;EAE3B,KAAK,IAAI,QAAQ,KAAK,gBAAgB,SAAS,GAAG,SAAS,GAAG,SAAS;GACrE,MAAM,QAAQ,KAAK,gBAAgB;GAEnC,IAAI,CAAC,OACH;GAGF,MAAM,WAAW,KAAK,UAAU,IAAI,KAAK;GAEzC,MAAM,WAAW,KAAK,UAAU,IAAI,KAAK;GAEzC,IAAI,aAAa,KAAA,KAAa,CAAC,UAAU,SACvC;GAGF,IAAI;IACF,MAAM,SAAS,QAAQ,QAAQ;GACjC,SAAS,OAAO;IACd,OAAO,KAAK,KAAK;GACnB;EACF;EAEA,KAAK,UAAU,MAAM;EACrB,KAAK,QAAQ,MAAM;EAEnB,KAAK,gBAAgB,OAAO,CAAC;EAE7B,IAAI,OAAO,SAAS,GAClB,MAAM,IAAI,eAAe,QAAQ,wCAAwC;CAE7E;AACF"}
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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "better-effect",
3
- "version": "0.2.0",
4
- "description": "Lightweight Effect-inspired primitives for better-result",
3
+ "version": "0.4.0",
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",
7
7
  "dependency-injection",
@@ -42,10 +42,10 @@
42
42
  "test:coverage": "bun test --coverage",
43
43
  "lint": "oxlint --type-aware .",
44
44
  "lint:fix": "oxlint --type-aware --fix .",
45
- "format": "oxfmt .",
46
- "format:check": "oxfmt .",
45
+ "format": "oxfmt --write .",
46
+ "format:check": "oxfmt --check .",
47
47
  "publint": "publint",
48
- "check": "bun run typecheck && bun test && bun run lint && bun run format:check && bun run build && bun run publint",
48
+ "check": "bun run typecheck && bun test && bun run lint && bun run format && bun run build && bun run publint",
49
49
  "prepublishOnly": "bun run check",
50
50
  "release:dry": "bun publish --dry-run"
51
51
  },
@@ -62,14 +62,11 @@
62
62
  "peerDependencies": {
63
63
  "better-result": "^3.0.0",
64
64
  "iti": "^0.8.0",
65
- "typescript": "^7.0.2"
65
+ "typescript": ">=5.2.0"
66
66
  },
67
67
  "peerDependenciesMeta": {
68
68
  "iti": {
69
69
  "optional": true
70
70
  }
71
- },
72
- "optionalDependencies": {
73
- "iti": "^0.8.0"
74
71
  }
75
72
  }
@@ -1,39 +0,0 @@
1
- //#region src/service/types.d.ts
2
- type ServiceToken<A = unknown> = (abstract new (...args: any[]) => A) & {
3
- readonly name: string;
4
- };
5
- type AnyServiceToken = ServiceToken<any>;
6
- type ServiceClass<A = unknown> = (new (...args: any[]) => A) & {
7
- readonly name: string;
8
- };
9
- type ServiceInstance<T extends AnyServiceToken> = InstanceType<T>;
10
- //#endregion
11
- //#region src/service/runtime.d.ts
12
- interface ServiceResolver {
13
- resolve<T extends AnyServiceToken>(token: T): InstanceType<T> | PromiseLike<InstanceType<T>>;
14
- }
15
- declare class ServiceRuntime {
16
- static run<A>(resolver: ServiceResolver, program: () => A): A;
17
- static current(): ServiceResolver;
18
- static resolve<T extends AnyServiceToken>(token: T): Promise<InstanceType<T>>;
19
- }
20
- //#endregion
21
- //#region src/utils/types.d.ts
22
- type MaybePromise<T> = T | PromiseLike<T>;
23
- //#endregion
24
- //#region src/layer/types.d.ts
25
- interface LayerProvider {
26
- readonly service: ServiceClass<any>;
27
- readonly acquire: () => MaybePromise<unknown>;
28
- readonly release?: (instance: unknown) => MaybePromise<void>;
29
- }
30
- type LayerGenerator<S extends ServiceClass<any>> = () => AsyncGenerator<never, InstanceType<S>, unknown>;
31
- //#endregion
32
- //#region src/layer/backend.d.ts
33
- interface LayerBackend extends ServiceResolver {
34
- register(provider: LayerProvider): void | PromiseLike<void>;
35
- disposeAll(): void | PromiseLike<void>;
36
- }
37
- //#endregion
38
- export { ServiceResolver as a, ServiceClass as c, MaybePromise as i, ServiceInstance as l, LayerGenerator as n, ServiceRuntime as o, LayerProvider as r, AnyServiceToken as s, LayerBackend as t, ServiceToken as u };
39
- //# sourceMappingURL=backend-CNAls62W.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"backend-CNAls62W.d.mts","names":[],"sources":["../src/service/types.ts","../src/service/runtime.ts","../src/utils/types.ts","../src/layer/types.ts","../src/layer/backend.ts"],"mappings":";KAAY,aAAa,iCAAiC,gBAAgB;WAC/D;;KAGC,kBAAkB;KAElB,aAAa,wBAAwB,gBAAgB;WACtD;;KAGC,gBAAgB,UAAU,mBAAmB,aAAa;;;UCJrD;EACf,QAAQ,UAAU,iBAAiB,OAAO,IAAI,aAAa,KAAK,YAAY,aAAa;;cAK9E;SACJ,IAAI,GAAG,UAAU,iBAAiB,eAAe,IAAI;SAIrD,WAAW;SAUL,QAAQ,UAAU,iBAAiB,OAAO,IAAI,QAAQ,aAAa;;;;KC3BtE,aAAa,KAAK,IAAI,YAAY;;;UCG7B;WACN,SAAS;WAET,eAAe;WAEf,WAAW,sBAAsB;;KAGhC,eAAe,UAAU,2BAA2B,sBAE9D,aAAa;;;UCTE,qBAAqB;EACpC,SAAS,UAAU,uBAAuB;EAC1C,qBAAqB"}