better-effect 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2,13 +2,13 @@ import { a as LayerRegistrationError, i as LayerGeneratorYieldError, n as Duplic
2
2
  import { AsyncLocalStorage } from "node:async_hooks";
3
3
  import { Result, TaggedError } from "better-result";
4
4
  //#region src/service/runtime.ts
5
- const storage = new AsyncLocalStorage();
5
+ const storage$1 = new AsyncLocalStorage();
6
6
  var ServiceRuntime = class ServiceRuntime {
7
7
  static run(resolver, program) {
8
- return storage.run(resolver, program);
8
+ return storage$1.run(resolver, program);
9
9
  }
10
10
  static current() {
11
- const resolver = storage.getStore();
11
+ const resolver = storage$1.getStore();
12
12
  if (!resolver) throw new ServiceRuntimeNotConfiguredError();
13
13
  return resolver;
14
14
  }
@@ -60,6 +60,13 @@ var Layer = class Layer {
60
60
  release: (instance) => release(instance)
61
61
  }]);
62
62
  }
63
+ static scopedGen(service, factory, release) {
64
+ return new Layer([{
65
+ service,
66
+ acquire: () => runLayerGenerator(service, factory),
67
+ release: (instance, outcome) => release(instance, outcome)
68
+ }]);
69
+ }
63
70
  static gen(service, factory) {
64
71
  return Layer.make(service, () => runLayerGenerator(service, factory));
65
72
  }
@@ -80,64 +87,397 @@ var Layer = class Layer {
80
87
  }
81
88
  };
82
89
  //#endregion
90
+ //#region src/scope/errors.ts
91
+ var ScopeRuntimeNotConfiguredError = class extends Error {
92
+ constructor() {
93
+ super("No Scope is available in the current execution context");
94
+ this.name = "ScopeRuntimeNotConfiguredError";
95
+ }
96
+ };
97
+ var ScopeClosedError = class extends Error {
98
+ constructor() {
99
+ super("Cannot add resources or finalizers to a closed Scope");
100
+ this.name = "ScopeClosedError";
101
+ }
102
+ };
103
+ var ScopeCloseError = class extends Error {
104
+ causes;
105
+ constructor(causes) {
106
+ super(`Failed to close Scope (${causes.length} finalizer${causes.length === 1 ? "" : "s"} failed)`);
107
+ this.causes = causes;
108
+ this.name = "ScopeCloseError";
109
+ }
110
+ };
111
+ var ResourceNotDisposableError = class extends Error {
112
+ constructor() {
113
+ super("Resource does not implement Symbol.dispose or Symbol.asyncDispose");
114
+ this.name = "ResourceNotDisposableError";
115
+ }
116
+ };
117
+ //#endregion
118
+ //#region src/scope/disposable.ts
119
+ const SCOPE_SUCCESS$2 = { status: "success" };
120
+ const getDisposeFinalizer = (resource) => {
121
+ const candidate = Object(resource);
122
+ const asyncDispose = candidate[Symbol.asyncDispose];
123
+ if (typeof asyncDispose === "function") return () => asyncDispose.call(resource);
124
+ const dispose = candidate[Symbol.dispose];
125
+ if (typeof dispose === "function") return () => dispose.call(resource);
126
+ };
127
+ const disposeResource = (resource) => {
128
+ return getDisposeFinalizer(resource)?.(SCOPE_SUCCESS$2);
129
+ };
130
+ //#endregion
131
+ //#region src/scope/runtime.ts
132
+ const storage = new AsyncLocalStorage();
133
+ var ScopeRuntime = class {
134
+ static run(scope, program) {
135
+ return storage.run(scope, program);
136
+ }
137
+ static current() {
138
+ const scope = storage.getStore();
139
+ if (!scope) throw new ScopeRuntimeNotConfiguredError();
140
+ return scope;
141
+ }
142
+ };
143
+ //#endregion
144
+ //#region src/scope/internal.ts
145
+ const notifyCleanupFailure = async (observer, diagnostic) => {
146
+ if (!observer) return;
147
+ try {
148
+ await observer(diagnostic);
149
+ } catch {}
150
+ };
151
+ const runScoped = async (scope, program, options) => {
152
+ let value;
153
+ let programFailed = false;
154
+ let programFailure;
155
+ try {
156
+ value = await ScopeRuntime.run(scope, program);
157
+ } catch (cause) {
158
+ programFailed = true;
159
+ programFailure = cause;
160
+ }
161
+ const outcome = programFailed ? {
162
+ status: "failure",
163
+ cause: programFailure
164
+ } : options.classify(value);
165
+ let cleanupFailed = false;
166
+ let cleanupFailure;
167
+ try {
168
+ await scope.close(outcome);
169
+ } catch (cause) {
170
+ cleanupFailed = true;
171
+ cleanupFailure = cause;
172
+ }
173
+ if (cleanupFailed) {
174
+ const error = cleanupFailure instanceof ScopeCloseError ? cleanupFailure : new ScopeCloseError([cleanupFailure]);
175
+ await notifyCleanupFailure(options.onCleanupFailure, {
176
+ outcome,
177
+ error
178
+ });
179
+ cleanupFailure = error;
180
+ }
181
+ if (programFailed) throw programFailure;
182
+ if (outcome.status === "failure") return value;
183
+ if (cleanupFailed) throw cleanupFailure;
184
+ return value;
185
+ };
186
+ //#endregion
187
+ //#region src/scope/scope.ts
188
+ const SCOPE_SUCCESS$1 = Object.freeze({ status: "success" });
189
+ var ScopeImpl = class ScopeImpl {
190
+ parent;
191
+ children = /* @__PURE__ */ new Set();
192
+ finalizers = [];
193
+ closePromise;
194
+ closeOutcome;
195
+ constructor(parent) {
196
+ this.parent = parent;
197
+ }
198
+ fork() {
199
+ this.assertOpen();
200
+ const child = new ScopeImpl(this);
201
+ this.children.add(child);
202
+ return child;
203
+ }
204
+ addFinalizer(finalizer) {
205
+ this.assertOpen();
206
+ this.finalizers.push(finalizer);
207
+ }
208
+ async acquire(acquire, release) {
209
+ this.assertOpen();
210
+ const resource = await acquire();
211
+ try {
212
+ this.addFinalizer((outcome) => release(resource, outcome));
213
+ return resource;
214
+ } catch (scopeFailure) {
215
+ try {
216
+ await release(resource, this.closeOutcome ?? SCOPE_SUCCESS$1);
217
+ } catch (releaseFailure) {
218
+ throw new AggregateError([scopeFailure, releaseFailure], "Scope closed while acquiring a resource and immediate cleanup also failed");
219
+ }
220
+ throw scopeFailure;
221
+ }
222
+ }
223
+ async add(resource) {
224
+ const finalizer = getDisposeFinalizer(resource);
225
+ if (!finalizer) throw new ResourceNotDisposableError();
226
+ try {
227
+ this.addFinalizer(finalizer);
228
+ return resource;
229
+ } catch (scopeFailure) {
230
+ try {
231
+ await finalizer(this.closeOutcome ?? SCOPE_SUCCESS$1);
232
+ } catch (releaseFailure) {
233
+ throw new AggregateError([scopeFailure, releaseFailure], "Scope closed while adding a disposable resource and cleanup also failed");
234
+ }
235
+ throw scopeFailure;
236
+ }
237
+ }
238
+ close(outcome = SCOPE_SUCCESS$1) {
239
+ if (this.closePromise) return this.closePromise;
240
+ this.closeOutcome = outcome;
241
+ this.closePromise = ScopeRuntime.run(this, () => this.closeInternal(outcome));
242
+ return this.closePromise;
243
+ }
244
+ async closeInternal(outcome) {
245
+ const failures = [];
246
+ const children = [...this.children];
247
+ this.children.clear();
248
+ for (let index = children.length - 1; index >= 0; index--) {
249
+ const child = children[index];
250
+ if (!child) continue;
251
+ try {
252
+ await child.close(outcome);
253
+ } catch (cause) {
254
+ if (cause instanceof ScopeCloseError) failures.push(...cause.causes);
255
+ else failures.push(cause);
256
+ }
257
+ }
258
+ for (let index = this.finalizers.length - 1; index >= 0; index--) {
259
+ const finalizer = this.finalizers[index];
260
+ if (!finalizer) continue;
261
+ try {
262
+ await finalizer(outcome);
263
+ } catch (cause) {
264
+ failures.push(cause);
265
+ }
266
+ }
267
+ this.finalizers.length = 0;
268
+ this.detach();
269
+ if (failures.length > 0) throw new ScopeCloseError(failures);
270
+ }
271
+ detach() {
272
+ const parent = this.parent;
273
+ if (!parent) return;
274
+ parent.children.delete(this);
275
+ this.parent = void 0;
276
+ }
277
+ assertOpen() {
278
+ if (this.closePromise) throw new ScopeClosedError();
279
+ }
280
+ };
281
+ const Scope = {
282
+ make() {
283
+ return new ScopeImpl();
284
+ },
285
+ current() {
286
+ return ScopeRuntime.current();
287
+ },
288
+ provide(scope, program) {
289
+ return ScopeRuntime.run(scope, program);
290
+ },
291
+ *[Symbol.iterator]() {
292
+ return ScopeRuntime.current();
293
+ },
294
+ run(program) {
295
+ const scope = new ScopeImpl();
296
+ return runScoped(scope, () => program(scope), { classify: () => SCOPE_SUCCESS$1 });
297
+ }
298
+ };
299
+ //#endregion
300
+ //#region src/runtime/outcome.ts
301
+ const isResultLike = (value) => typeof value === "object" && value !== null && "status" in value && (value.status === "ok" || value.status === "error");
302
+ const classifyRuntimeOutcome = (value) => {
303
+ if (isResultLike(value) && Result.isError(value)) return {
304
+ status: "failure",
305
+ cause: value.error
306
+ };
307
+ return { status: "success" };
308
+ };
309
+ //#endregion
83
310
  //#region src/layer/runtime.ts
311
+ const SCOPE_SUCCESS = Object.freeze({ status: "success" });
84
312
  const normalizeDisposeCauses = (cause) => {
85
313
  if (cause instanceof AggregateError) return [...cause.errors];
86
314
  return [cause];
87
315
  };
316
+ const notifyShutdownFailure = async (observer, diagnostic) => {
317
+ if (!observer) return;
318
+ try {
319
+ await observer(diagnostic);
320
+ } catch {}
321
+ };
322
+ const bindProviderToScope = (provider, rootScope) => ({
323
+ service: provider.service,
324
+ acquire: () => ScopeRuntime.run(rootScope, async () => {
325
+ if (!provider.release) return await provider.acquire();
326
+ return await rootScope.acquire(() => provider.acquire(), (resource, outcome) => provider.release(resource, outcome));
327
+ })
328
+ });
88
329
  var BuiltLayerImpl = class {
89
330
  backend;
331
+ rootScope;
332
+ onCleanupFailure;
90
333
  disposePromise;
91
- disposed = false;
92
- constructor(backend) {
334
+ executions = /* @__PURE__ */ new Set();
335
+ state = "active";
336
+ constructor(backend, rootScope, onCleanupFailure) {
93
337
  this.backend = backend;
338
+ this.rootScope = rootScope;
339
+ this.onCleanupFailure = onCleanupFailure;
94
340
  }
95
341
  run(program) {
96
- if (this.disposed || this.disposePromise) throw new BuiltLayerDisposedError();
97
- return ServiceRuntime.run(this.backend, program);
342
+ this.assertActive();
343
+ const executionScope = this.rootScope.fork();
344
+ let resolveExecution;
345
+ let rejectExecution;
346
+ const execution = new Promise((resolve, reject) => {
347
+ resolveExecution = resolve;
348
+ rejectExecution = reject;
349
+ });
350
+ this.executions.add(execution);
351
+ execution.then(() => {
352
+ this.executions.delete(execution);
353
+ }, () => {
354
+ this.executions.delete(execution);
355
+ });
356
+ try {
357
+ this.runExecution(executionScope, program).then((value) => {
358
+ resolveExecution(value);
359
+ }, (cause) => {
360
+ rejectExecution(cause);
361
+ });
362
+ } catch (cause) {
363
+ rejectExecution(cause);
364
+ }
365
+ return execution;
98
366
  }
99
- dispose() {
367
+ runExecution(executionScope, program) {
368
+ const options = this.onCleanupFailure ? {
369
+ classify: classifyRuntimeOutcome,
370
+ onCleanupFailure: this.onCleanupFailure
371
+ } : { classify: classifyRuntimeOutcome };
372
+ return runScoped(executionScope, () => ServiceRuntime.run(this.backend, program), options);
373
+ }
374
+ dispose(outcome = SCOPE_SUCCESS) {
100
375
  if (this.disposePromise) return this.disposePromise;
101
- this.disposePromise = this.performDispose();
376
+ this.state = "disposing";
377
+ const executions = [...this.executions];
378
+ this.disposePromise = this.performDispose(executions, outcome);
102
379
  return this.disposePromise;
103
380
  }
104
- async performDispose() {
381
+ async performDispose(executions, outcome) {
382
+ const failures = [];
383
+ await Promise.allSettled(executions);
384
+ try {
385
+ await ServiceRuntime.run(this.backend, () => this.rootScope.close(outcome));
386
+ } catch (cause) {
387
+ failures.push(cause);
388
+ }
105
389
  try {
106
390
  await this.backend.disposeAll();
107
391
  } catch (cause) {
108
- throw new LayerDisposeError(normalizeDisposeCauses(cause));
109
- } finally {
110
- this.disposed = true;
392
+ failures.push(cause);
393
+ }
394
+ this.state = "disposed";
395
+ if (failures.length > 0) {
396
+ const error = new LayerDisposeError(failures.flatMap(normalizeDisposeCauses));
397
+ await notifyShutdownFailure(this.onCleanupFailure, {
398
+ outcome,
399
+ error
400
+ });
401
+ throw error;
111
402
  }
112
403
  }
404
+ assertActive() {
405
+ if (this.state !== "active") throw new BuiltLayerDisposedError();
406
+ }
113
407
  };
114
- const buildLayer = async (layer, backend) => {
408
+ const buildLayer = async (layer, backend, options = {}) => {
409
+ const rootScope = Scope.make();
115
410
  let current;
116
411
  try {
117
412
  for (const provider of layer.providers) {
118
413
  current = provider;
119
- await backend.register(provider);
414
+ await backend.register(bindProviderToScope(provider, rootScope));
120
415
  }
121
416
  } catch (registrationCause) {
122
- let cleanupCause;
417
+ const outcome = {
418
+ status: "failure",
419
+ cause: registrationCause
420
+ };
421
+ const cleanupCauses = [];
422
+ try {
423
+ await ServiceRuntime.run(backend, () => rootScope.close(outcome));
424
+ } catch (cause) {
425
+ cleanupCauses.push(cause);
426
+ }
123
427
  try {
124
428
  await backend.disposeAll();
125
429
  } catch (cause) {
126
- cleanupCause = cause;
430
+ cleanupCauses.push(cause);
431
+ }
432
+ if (cleanupCauses.length > 0) {
433
+ const shutdownError = new LayerDisposeError(cleanupCauses.flatMap(normalizeDisposeCauses));
434
+ await notifyShutdownFailure(options.onCleanupFailure, {
435
+ outcome,
436
+ error: shutdownError
437
+ });
127
438
  }
439
+ let cleanupCause;
440
+ if (cleanupCauses.length === 1) cleanupCause = cleanupCauses[0];
441
+ else if (cleanupCauses.length > 1) cleanupCause = new LayerDisposeError(cleanupCauses.flatMap(normalizeDisposeCauses));
128
442
  throw new LayerRegistrationError(current?.service, registrationCause, cleanupCause);
129
443
  }
130
- return new BuiltLayerImpl(backend);
444
+ return new BuiltLayerImpl(backend, rootScope, options.onCleanupFailure);
445
+ };
446
+ //#endregion
447
+ //#region src/effect/effect.ts
448
+ function gen(body) {
449
+ return Result.gen(body);
450
+ }
451
+ /**
452
+ * Acquire a resource in the current Scope and register its release callback.
453
+ *
454
+ * Acquisition failures are represented in the Effect Result error channel;
455
+ * release failures remain owned by Scope cleanup.
456
+ */
457
+ function acquireRelease(acquire, release) {
458
+ const scope = Scope.current();
459
+ return Result.await(Result.tryPromise(() => scope.acquire(acquire, release)));
460
+ }
461
+ /**
462
+ * Register an already-acquired disposable resource in the current Scope.
463
+ *
464
+ * Registration failures are represented in the Effect Result error channel;
465
+ * disposal failures remain owned by Scope cleanup.
466
+ */
467
+ function add(resource) {
468
+ const scope = Scope.current();
469
+ return Result.await(Result.tryPromise(() => scope.add(resource)));
470
+ }
471
+ const Effect = {
472
+ gen,
473
+ acquireRelease,
474
+ add
131
475
  };
132
476
  //#endregion
133
477
  //#region src/resource/errors.ts
134
478
  var ResourceReleaseFailure = class extends TaggedError("ResourceReleaseFailure") {};
135
479
  //#endregion
136
480
  //#region src/resource/internal.ts
137
- const disposeResource = (resource) => {
138
- const candidate = Object(resource);
139
- return (candidate[Symbol.asyncDispose] ?? candidate[Symbol.dispose])?.call(candidate);
140
- };
141
481
  const toReleaseFailure = (resource, cause) => new ResourceReleaseFailure({
142
482
  resource,
143
483
  cause,
@@ -177,8 +517,13 @@ const combineUseAndRelease = async (used, released, onReleaseFailure) => {
177
517
  //#region src/resource/resource.ts
178
518
  const acquireUseRelease = ({ name, acquire, use, release = disposeResource, onReleaseFailure }) => Result.gen(async function* () {
179
519
  const resource = yield* Result.await(runResult(acquire));
520
+ const scope = Scope.make();
521
+ let released = Result.ok();
522
+ scope.addFinalizer(async () => {
523
+ released = await runRelease(name, resource, release);
524
+ });
180
525
  const used = await runResult(() => use(resource));
181
- const released = await runRelease(name, resource, release);
526
+ await scope.close();
182
527
  return await combineUseAndRelease(used, released, onReleaseFailure);
183
528
  });
184
529
  const Resource = { acquireUseRelease };
@@ -189,26 +534,60 @@ var Runtime = class Runtime {
189
534
  constructor(built) {
190
535
  this.built = built;
191
536
  }
192
- static async make(layer, backend) {
193
- const built = await buildLayer(layer, backend);
537
+ static async make(layer, backend, options = {}) {
538
+ const built = await buildLayer(layer, backend, options);
194
539
  return new Runtime(built);
195
540
  }
196
- static async run(layer, backend, program) {
197
- const runtime = await Runtime.make(layer, backend);
541
+ static async run(layer, backend, program, options = {}) {
542
+ const runtime = await Runtime.make(layer, backend, options);
543
+ let value;
544
+ let executionFailed = false;
545
+ let executionFailure;
546
+ let programOutcome;
198
547
  try {
199
- return await runtime.run(program);
200
- } finally {
201
- await runtime.dispose();
548
+ value = await runtime.runUnchecked(async () => {
549
+ try {
550
+ const programValue = await program();
551
+ programOutcome = classifyRuntimeOutcome(programValue);
552
+ return programValue;
553
+ } catch (cause) {
554
+ programOutcome = {
555
+ status: "failure",
556
+ cause
557
+ };
558
+ throw cause;
559
+ }
560
+ });
561
+ } catch (cause) {
562
+ executionFailed = true;
563
+ executionFailure = cause;
202
564
  }
565
+ const outcome = programOutcome ?? {
566
+ status: "failure",
567
+ cause: executionFailure
568
+ };
569
+ try {
570
+ await runtime.disposeWithOutcome(outcome);
571
+ } catch (shutdownFailure) {
572
+ if (!executionFailed && outcome.status === "success") throw shutdownFailure;
573
+ }
574
+ if (executionFailed) throw executionFailure;
575
+ return value;
203
576
  }
204
577
  run(program) {
205
578
  return this.built.run(program);
206
579
  }
580
+ runUnchecked(program) {
581
+ return this.built.run(program);
582
+ }
207
583
  dispose() {
208
584
  return this.built.dispose();
209
585
  }
586
+ disposeWithOutcome(outcome) {
587
+ return this.built.dispose(outcome);
588
+ }
210
589
  };
211
590
  //#endregion
212
- export { BuiltLayerDisposedError, DuplicateServiceError, Layer, LayerDisposeError, LayerGeneratorYieldError, LayerRegistrationError, Resource, ResourceReleaseFailure, Runtime, Service, ServiceNotFoundError, ServiceRuntime, ServiceRuntimeNotConfiguredError, buildLayer };
591
+ export { BuiltLayerDisposedError, DuplicateServiceError, Effect, Layer, LayerDisposeError, LayerGeneratorYieldError, LayerRegistrationError, Resource, ResourceNotDisposableError, ResourceReleaseFailure, Runtime, Scope, ScopeCloseError, ScopeClosedError, ScopeRuntimeNotConfiguredError, Service, ServiceNotFoundError, ServiceRuntime, ServiceRuntimeNotConfiguredError, buildLayer };
213
592
 
214
593
  //# sourceMappingURL=index.mjs.map
@@ -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/effect.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 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 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 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\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\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 { 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\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} as const\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 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 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<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 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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"}