better-effect 0.12.0 → 0.14.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.
Files changed (101) hide show
  1. package/README.md +599 -30
  2. package/dist/adapters/iti.d.mts +2 -3
  3. package/dist/adapters/iti.d.mts.map +1 -1
  4. package/dist/adapters/iti.mjs +2 -2
  5. package/dist/bun.d.mts +95 -0
  6. package/dist/bun.d.mts.map +1 -0
  7. package/dist/bun.mjs +177 -0
  8. package/dist/bun.mjs.map +1 -0
  9. package/dist/{context-BUEf1qjL.mjs → context-DSGSqcJj.mjs} +14 -3
  10. package/dist/context-DSGSqcJj.mjs.map +1 -0
  11. package/dist/current-request-Bc1YHL0w.mjs +21 -0
  12. package/dist/current-request-Bc1YHL0w.mjs.map +1 -0
  13. package/dist/current-request-Dm-QQ3Xr.d.mts +22 -0
  14. package/dist/current-request-Dm-QQ3Xr.d.mts.map +1 -0
  15. package/dist/{effect-CK4YZaX0.mjs → effect-W0IQXY8P.mjs} +21 -2
  16. package/dist/effect-W0IQXY8P.mjs.map +1 -0
  17. package/dist/{errors-BKcsQ0ip.d.mts → errors-CpHMzPiP.d.mts} +6 -2
  18. package/dist/errors-CpHMzPiP.d.mts.map +1 -0
  19. package/dist/hono.d.mts +65 -27
  20. package/dist/hono.d.mts.map +1 -1
  21. package/dist/hono.mjs +177 -53
  22. package/dist/hono.mjs.map +1 -1
  23. package/dist/{index-CX6iAoCB.d.mts → index-3Bkl-sxS.d.mts} +7 -2
  24. package/dist/{index-CX6iAoCB.d.mts.map → index-3Bkl-sxS.d.mts.map} +1 -1
  25. package/dist/{index-B1nH4luq.d.mts → index-C2ed9Ilq.d.mts} +32 -21
  26. package/dist/index-C2ed9Ilq.d.mts.map +1 -0
  27. package/dist/{index-GYJ4qm9K.d.mts → index-ClNndn2-.d.mts} +93 -62
  28. package/dist/index-ClNndn2-.d.mts.map +1 -0
  29. package/dist/{index-BMdU_Z72.d.mts → index-Cy1VsU-u.d.mts} +2 -3
  30. package/dist/index-Cy1VsU-u.d.mts.map +1 -0
  31. package/dist/index.d.mts +6 -7
  32. package/dist/index.mjs +8 -8
  33. package/dist/{internal-identity-CbXoZIfw.mjs → internal-identity-BuHBtP0k.mjs} +2 -2
  34. package/dist/{internal-identity-CbXoZIfw.mjs.map → internal-identity-BuHBtP0k.mjs.map} +1 -1
  35. package/dist/layer-2kjHVv4N.mjs +343 -0
  36. package/dist/layer-2kjHVv4N.mjs.map +1 -0
  37. package/dist/{outcome-CB43bnFW.d.mts → layer-C2OaqTmB.d.mts} +683 -138
  38. package/dist/layer-C2OaqTmB.d.mts.map +1 -0
  39. package/dist/next.d.mts +192 -0
  40. package/dist/next.d.mts.map +1 -0
  41. package/dist/next.mjs +185 -0
  42. package/dist/next.mjs.map +1 -0
  43. package/dist/{node-context-DWsCUBRa.d.mts → node-context-1YEjrU9g.d.mts} +2 -2
  44. package/dist/{node-context-DWsCUBRa.d.mts.map → node-context-1YEjrU9g.d.mts.map} +1 -1
  45. package/dist/{node-context-lggRF4bR.mjs → node-context-g3bCcY9t.mjs} +2 -2
  46. package/dist/{node-context-lggRF4bR.mjs.map → node-context-g3bCcY9t.mjs.map} +1 -1
  47. package/dist/node.d.mts +11 -6
  48. package/dist/node.d.mts.map +1 -1
  49. package/dist/node.mjs +156 -10
  50. package/dist/node.mjs.map +1 -1
  51. package/dist/opentelemetry.d.mts +112 -0
  52. package/dist/opentelemetry.d.mts.map +1 -0
  53. package/dist/opentelemetry.mjs +871 -0
  54. package/dist/opentelemetry.mjs.map +1 -0
  55. package/dist/{registration-drnZk0SY.mjs → registration-Bwe2GbVu.mjs} +8 -2
  56. package/dist/registration-Bwe2GbVu.mjs.map +1 -0
  57. package/dist/runtime/explicit.d.mts +2 -2
  58. package/dist/runtime/explicit.mjs +1 -1
  59. package/dist/runtime/node.d.mts +3 -3
  60. package/dist/runtime/node.mjs +2 -2
  61. package/dist/runtime-qpcVwaz_.mjs +1680 -0
  62. package/dist/runtime-qpcVwaz_.mjs.map +1 -0
  63. package/dist/service-CO9VJQYa.mjs +74 -0
  64. package/dist/service-CO9VJQYa.mjs.map +1 -0
  65. package/dist/signal-5Rg9bUUe.mjs +52 -0
  66. package/dist/signal-5Rg9bUUe.mjs.map +1 -0
  67. package/dist/{standard-services-GBZ32tll.mjs → standard-services-B-iMM_W7.mjs} +39 -19
  68. package/dist/standard-services-B-iMM_W7.mjs.map +1 -0
  69. package/dist/standard-services.d.mts +4 -3
  70. package/dist/standard-services.mjs +3 -2
  71. package/dist/testing.d.mts +25 -6
  72. package/dist/testing.d.mts.map +1 -1
  73. package/dist/testing.mjs +51 -7
  74. package/dist/testing.mjs.map +1 -1
  75. package/dist/types-BFTqCCcw.d.mts +81 -0
  76. package/dist/types-BFTqCCcw.d.mts.map +1 -0
  77. package/dist/web-effect-B9hp9jIe.mjs +380 -0
  78. package/dist/web-effect-B9hp9jIe.mjs.map +1 -0
  79. package/dist/web.d.mts +56 -0
  80. package/dist/web.d.mts.map +1 -0
  81. package/dist/web.mjs +2 -0
  82. package/package.json +36 -11
  83. package/dist/context-BUEf1qjL.mjs.map +0 -1
  84. package/dist/effect-CK4YZaX0.mjs.map +0 -1
  85. package/dist/errors-BKcsQ0ip.d.mts.map +0 -1
  86. package/dist/index-B1nH4luq.d.mts.map +0 -1
  87. package/dist/index-BMdU_Z72.d.mts.map +0 -1
  88. package/dist/index-GYJ4qm9K.d.mts.map +0 -1
  89. package/dist/index-heuaRmXR.d.mts +0 -374
  90. package/dist/index-heuaRmXR.d.mts.map +0 -1
  91. package/dist/layer-D56fRdLt.mjs +0 -269
  92. package/dist/layer-D56fRdLt.mjs.map +0 -1
  93. package/dist/outcome-CB43bnFW.d.mts.map +0 -1
  94. package/dist/program-metadata-DhQCCirO.mjs +0 -260
  95. package/dist/program-metadata-DhQCCirO.mjs.map +0 -1
  96. package/dist/registration-drnZk0SY.mjs.map +0 -1
  97. package/dist/runtime-CBMrX8Wl.mjs +0 -776
  98. package/dist/runtime-CBMrX8Wl.mjs.map +0 -1
  99. package/dist/signal-D2UTcaaG.mjs +0 -105
  100. package/dist/signal-D2UTcaaG.mjs.map +0 -1
  101. package/dist/standard-services-GBZ32tll.mjs.map +0 -1
@@ -0,0 +1,343 @@
1
+ import { a as LayerGeneratorYieldError, d as ServiceRuntimeNotConfiguredError, f as captureServiceTag, r as DuplicateServiceError, s as ServiceTagCollisionError, t as captureLayerRegistrationTag } from "./registration-Bwe2GbVu.mjs";
2
+ import { d as setDefaultRuntimeContextStorage, h as RuntimeContextNotConfiguredError, i as getRuntimeContext, l as makeRuntimeContext, n as currentRuntimeContext, u as runRuntimeContext } from "./context-DSGSqcJj.mjs";
3
+ import { n as nodeRuntimeContextStorage } from "./node-context-g3bCcY9t.mjs";
4
+ import { Result } from "better-result";
5
+ //#region src/runtime/default.ts
6
+ /** The Node/Bun storage used by the main Runtime entrypoint. */
7
+ const defaultRuntimeContextStorage = nodeRuntimeContextStorage;
8
+ setDefaultRuntimeContextStorage(defaultRuntimeContextStorage);
9
+ //#endregion
10
+ //#region src/service/runtime.ts
11
+ /** Provides the resolver context used by Service tokens during execution. */
12
+ var ServiceRuntime = class ServiceRuntime {
13
+ /**
14
+ * Run a callback with a resolver available to `yield* Service` expressions.
15
+ *
16
+ * The context is scoped to the callback and is restored afterward.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const value = ServiceRuntime.run(resolver, () => {
21
+ * return ServiceRuntime.resolve(Database)
22
+ * })
23
+ * ```
24
+ */
25
+ static run(resolver, program, storage = defaultRuntimeContextStorage) {
26
+ const current = getRuntimeContext(storage);
27
+ const sameResolver = current?.resolver === resolver;
28
+ const context = makeRuntimeContext(resolver, current?.scope, sameResolver ? current.resolutionPath : [], current?.signal, current, current?.executionId);
29
+ return runRuntimeContext(storage, context, program);
30
+ }
31
+ /** Return the resolver active in the current execution context. */
32
+ static current() {
33
+ let context;
34
+ try {
35
+ context = currentRuntimeContext();
36
+ } catch (cause) {
37
+ if (cause instanceof RuntimeContextNotConfiguredError) throw new ServiceRuntimeNotConfiguredError();
38
+ throw cause;
39
+ }
40
+ if (!context.resolver) throw new ServiceRuntimeNotConfiguredError();
41
+ return context.resolver;
42
+ }
43
+ /** Resolve a Service token using the active resolver. */
44
+ static async resolve(token) {
45
+ captureServiceTag(token);
46
+ return await ServiceRuntime.current().resolve(token);
47
+ }
48
+ };
49
+ //#endregion
50
+ //#region src/scope/errors.ts
51
+ /** Thrown when Scope context is accessed outside an active Scope execution. */
52
+ var ScopeRuntimeNotConfiguredError = class extends Error {
53
+ constructor() {
54
+ super("No Scope is available in the current execution context");
55
+ this.name = "ScopeRuntimeNotConfiguredError";
56
+ }
57
+ };
58
+ /** Thrown when a resource or finalizer is added after Scope closure begins. */
59
+ var ScopeClosedError = class extends Error {
60
+ constructor() {
61
+ super("Cannot add resources or finalizers to a closed Scope");
62
+ this.name = "ScopeClosedError";
63
+ }
64
+ };
65
+ /** Aggregates finalizer failures encountered while closing a Scope. */
66
+ var ScopeCloseError = class extends Error {
67
+ causes;
68
+ constructor(causes) {
69
+ super(`Failed to close Scope (${causes.length} finalizer${causes.length === 1 ? "" : "s"} failed)`);
70
+ this.causes = causes;
71
+ this.name = "ScopeCloseError";
72
+ }
73
+ };
74
+ /** Thrown when a value has neither Symbol.dispose nor Symbol.asyncDispose. */
75
+ var ResourceNotDisposableError = class extends Error {
76
+ constructor() {
77
+ super("Resource does not implement Symbol.dispose or Symbol.asyncDispose");
78
+ this.name = "ResourceNotDisposableError";
79
+ }
80
+ };
81
+ //#endregion
82
+ //#region src/scope/disposable.ts
83
+ const SCOPE_SUCCESS = { status: "success" };
84
+ /** Return a Scope finalizer for a value's async or sync disposal protocol. */
85
+ const getDisposeFinalizer = (resource) => {
86
+ const candidate = Object(resource);
87
+ const asyncDispose = candidate[Symbol.asyncDispose];
88
+ if (asyncDispose instanceof Function) return () => asyncDispose.call(resource);
89
+ const dispose = candidate[Symbol.dispose];
90
+ if (dispose instanceof Function) return () => dispose.call(resource);
91
+ };
92
+ /** Dispose a value immediately when it implements a disposal protocol. */
93
+ const disposeResource = (resource) => {
94
+ return getDisposeFinalizer(resource)?.(SCOPE_SUCCESS);
95
+ };
96
+ //#endregion
97
+ //#region src/layer/internal.ts
98
+ const runLayerGenerator = async (service, factory) => {
99
+ const iterator = factory();
100
+ let state = await iterator.next();
101
+ while (!state.done) {
102
+ const token = serviceTokenFromYield(state.value);
103
+ if (token === void 0) try {
104
+ await iterator.return(void 0);
105
+ } finally {
106
+ throw new LayerGeneratorYieldError(service);
107
+ }
108
+ state = await iterator.next(await ServiceRuntime.resolve(token));
109
+ }
110
+ return state.value;
111
+ };
112
+ /** Run a lifecycle-only generator in the active ServiceRuntime context. */
113
+ const runLayerDiscardGenerator = async (factory) => runLayerDiscardIterator(factory());
114
+ /** Resolve Service yields from an erased lifecycle-only generator. */
115
+ const runLayerDiscardIterator = async (iterator) => {
116
+ let state = await iterator.next();
117
+ while (!state.done) {
118
+ const token = serviceTokenFromYield(state.value);
119
+ if (token === void 0) try {
120
+ await iterator.return(void 0);
121
+ } finally {
122
+ throw new TypeError("Layer.scopedDiscard generator yielded an unsupported value");
123
+ }
124
+ state = await iterator.next(await ServiceRuntime.resolve(token));
125
+ }
126
+ return state.value;
127
+ };
128
+ const serviceTokenFromYield = (value) => {
129
+ try {
130
+ captureServiceTag(value);
131
+ return value;
132
+ } catch {
133
+ return;
134
+ }
135
+ };
136
+ //#endregion
137
+ //#region src/layer/layer.ts
138
+ const layerEntries = /* @__PURE__ */ new WeakMap();
139
+ const isLifecycleEntry = (entry) => "kind" in entry && entry.kind === "lifecycle";
140
+ /** Read all entries while keeping lifecycle storage out of the public declaration. */
141
+ const getLayerEntries = (layer) => layerEntries.get(layer) ?? layer.providers;
142
+ /**
143
+ * Declarative collection of Service providers.
144
+ *
145
+ * A Layer describes how to acquire implementations; it does not execute
146
+ * providers until a `Runtime` is created. Use `merge` to compose distinct
147
+ * providers and `override` when replacing an existing provider intentionally.
148
+ *
149
+ * @example
150
+ * ```ts
151
+ * const AppLive = Layer.merge(
152
+ * Layer.succeed(Database, database),
153
+ * Layer.make(UserRepository)
154
+ * )
155
+ *
156
+ * const runtime = await Runtime.make(AppLive, backend)
157
+ * ```
158
+ */
159
+ var Layer = class Layer {
160
+ /** The Service provider registrations retained by this Layer. */
161
+ providers;
162
+ constructor(entries) {
163
+ const frozenEntries = Object.freeze(entries.map((entry) => {
164
+ if (isLifecycleEntry(entry)) return Object.freeze({ ...entry });
165
+ return Object.freeze({
166
+ ...entry,
167
+ serviceTag: captureLayerRegistrationTag(entry)
168
+ });
169
+ }));
170
+ layerEntries.set(this, frozenEntries);
171
+ this.providers = Object.freeze(frozenEntries.filter((entry) => !isLifecycleEntry(entry)));
172
+ }
173
+ static makeLifecycleLayer(acquire, release, quiesce) {
174
+ const entry = {
175
+ kind: "lifecycle",
176
+ id: Symbol("better-effect.lifecycle"),
177
+ acquire,
178
+ release
179
+ };
180
+ if (quiesce !== void 0) entry.quiesce = quiesce;
181
+ return new Layer([entry]);
182
+ }
183
+ /** A stable provider-free Layer for composition roots with no Services. */
184
+ static empty = Object.freeze(new Layer([]));
185
+ static make(service, acquire) {
186
+ const serviceTag = captureServiceTag(service);
187
+ const defaultAcquire = () => {
188
+ return new service();
189
+ };
190
+ const normalizedAcquire = normalizeAcquire(acquire ?? defaultAcquire);
191
+ return new Layer([{
192
+ service,
193
+ serviceTag,
194
+ acquire: normalizedAcquire
195
+ }]);
196
+ }
197
+ /** Create a Layer from an already-constructed Service instance. */
198
+ static succeed(service, instance) {
199
+ const serviceTag = captureServiceTag(service);
200
+ const normalizedAcquire = normalizeAcquire(() => instance);
201
+ return new Layer([{
202
+ service,
203
+ serviceTag,
204
+ acquire: normalizedAcquire
205
+ }]);
206
+ }
207
+ /** Alias a source Service under a compatible target contract. */
208
+ static alias(options) {
209
+ const { from, to } = options;
210
+ captureServiceTag(from);
211
+ return Layer.gen(to, async function* () {
212
+ return await ServiceRuntime.resolve(from);
213
+ });
214
+ }
215
+ static scoped(service, acquire, lifecycleOrRelease) {
216
+ const serviceTag = captureServiceTag(service);
217
+ const normalized = normalizeLifecycle(lifecycleOrRelease);
218
+ const provider = {
219
+ service,
220
+ serviceTag,
221
+ acquire: normalizeAcquire(acquire),
222
+ release: (instance, outcome) => {
223
+ return normalized.release(instance, outcome);
224
+ }
225
+ };
226
+ if (normalized.quiesce !== void 0) provider.quiesce = (instance, reason) => normalized.quiesce(instance, reason);
227
+ return new Layer([provider]);
228
+ }
229
+ /** Define a provider with Runtime-root cleanup through its disposal protocol. */
230
+ static scopedDisposable(service, acquire) {
231
+ const acquireWithRelease = async () => {
232
+ const instance = await acquire();
233
+ const finalizer = getDisposeFinalizer(instance);
234
+ if (!finalizer) throw new ResourceNotDisposableError();
235
+ return {
236
+ instance,
237
+ release: finalizer
238
+ };
239
+ };
240
+ const serviceTag = captureServiceTag(service);
241
+ return new Layer([{
242
+ service,
243
+ serviceTag,
244
+ acquire: async () => (await acquireWithRelease()).instance,
245
+ acquireWithRelease
246
+ }]);
247
+ }
248
+ static scopedGen(service, factory, lifecycleOrRelease) {
249
+ const serviceTag = captureServiceTag(service);
250
+ const normalized = normalizeLifecycle(lifecycleOrRelease);
251
+ const provider = {
252
+ service,
253
+ serviceTag,
254
+ acquire: () => runLayerGenerator(service, factory),
255
+ release: (instance, outcome) => {
256
+ return normalized.release(instance, outcome);
257
+ }
258
+ };
259
+ if (normalized.quiesce !== void 0) provider.quiesce = (instance, reason) => normalized.quiesce(instance, reason);
260
+ return new Layer([provider]);
261
+ }
262
+ /** Define a provider whose acquisition can yield contextual Services. */
263
+ static gen(service, factory) {
264
+ const serviceTag = captureServiceTag(service);
265
+ return new Layer([{
266
+ service,
267
+ serviceTag,
268
+ acquire: () => runLayerGenerator(service, factory)
269
+ }]);
270
+ }
271
+ static scopedDiscard(acquire, releaseOrLifecycle) {
272
+ const lifecycle = normalizeLifecycle(releaseOrLifecycle);
273
+ return Layer.makeLifecycleLayer(() => {
274
+ const acquired = acquire();
275
+ if (isIteratorLike(acquired)) return runLayerDiscardIterator(acquired);
276
+ return acquired;
277
+ }, lifecycle.release, lifecycle.quiesce);
278
+ }
279
+ static scopedDiscardGen(acquire, lifecycleOrRelease) {
280
+ const normalized = normalizeLifecycle(lifecycleOrRelease);
281
+ return Layer.makeLifecycleLayer(() => runLayerDiscardGenerator(acquire), (instance, outcome) => {
282
+ return normalized.release(instance, outcome);
283
+ }, normalized.quiesce === void 0 ? void 0 : (instance, reason) => normalized.quiesce(instance, reason));
284
+ }
285
+ /** Run a no-failure Effect Program as a lifecycle-only entry. */
286
+ static effectDiscard(program) {
287
+ return Layer.makeLifecycleLayer(async () => {
288
+ const result = await program();
289
+ if (Result.isError(result)) throw result.error;
290
+ }, async () => {});
291
+ }
292
+ /** Compose Layers without replacing providers. */
293
+ static merge(...layers) {
294
+ const entries = /* @__PURE__ */ new Map();
295
+ for (const layer of layers) for (const entry of getLayerEntries(layer)) {
296
+ if (isLifecycleEntry(entry)) {
297
+ entries.set(entry.id, entry);
298
+ continue;
299
+ }
300
+ const service = entry.service;
301
+ const serviceTag = captureLayerRegistrationTag(entry);
302
+ const existing = entries.get(serviceTag);
303
+ if (existing) {
304
+ if (isLifecycleEntry(existing)) throw new Error("Layer lifecycle entry identity collided with a Service tag");
305
+ if (existing.service !== service) throw new ServiceTagCollisionError(existing.service, service);
306
+ throw new DuplicateServiceError(service);
307
+ }
308
+ entries.set(serviceTag, entry);
309
+ }
310
+ return new Layer([...entries.values()]);
311
+ }
312
+ /** Mark a Layer composition root as complete without changing its runtime value. */
313
+ static complete(layer) {
314
+ return layer;
315
+ }
316
+ static override(base, ...overrides) {
317
+ const entries = /* @__PURE__ */ new Map();
318
+ for (const entry of getLayerEntries(base)) entries.set(isLifecycleEntry(entry) ? entry.id : captureLayerRegistrationTag(entry), entry);
319
+ for (const layer of overrides) for (const entry of getLayerEntries(layer)) entries.set(isLifecycleEntry(entry) ? entry.id : captureLayerRegistrationTag(entry), entry);
320
+ return new Layer([...entries.values()]);
321
+ }
322
+ };
323
+ Object.defineProperty(Layer, "empty", {
324
+ value: Layer.empty,
325
+ writable: false,
326
+ enumerable: true,
327
+ configurable: false
328
+ });
329
+ const normalizeAcquire = (acquire) => () => {
330
+ return acquire();
331
+ };
332
+ const normalizeLifecycle = (lifecycle) => {
333
+ if (typeof lifecycle === "function") return { release: lifecycle };
334
+ return lifecycle;
335
+ };
336
+ const isIteratorLike = (value) => {
337
+ if (!(value instanceof Object) || !("next" in value)) return false;
338
+ return value.next instanceof Function;
339
+ };
340
+ //#endregion
341
+ export { ResourceNotDisposableError as a, ScopeRuntimeNotConfiguredError as c, getDisposeFinalizer as i, ServiceRuntime as l, getLayerEntries as n, ScopeCloseError as o, disposeResource as r, ScopeClosedError as s, Layer as t, defaultRuntimeContextStorage as u };
342
+
343
+ //# sourceMappingURL=layer-2kjHVv4N.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layer-2kjHVv4N.mjs","names":["Constructor"],"sources":["../src/runtime/default.ts","../src/service/runtime.ts","../src/scope/errors.ts","../src/scope/disposable.ts","../src/layer/internal.ts","../src/layer/layer.ts"],"sourcesContent":["import { nodeRuntimeContextStorage } from './node-context'\n\nimport { setDefaultRuntimeContextStorage } from './context'\n\n/** The Node/Bun storage used by the main Runtime entrypoint. */\nexport const defaultRuntimeContextStorage = nodeRuntimeContextStorage\n\nsetDefaultRuntimeContextStorage(defaultRuntimeContextStorage)\n","import { ServiceRuntimeNotConfiguredError } from './errors'\nimport { captureServiceTag } from './tag'\n\nimport { RuntimeContextNotConfiguredError } from '../runtime/errors'\n\nimport {\n currentRuntimeContext,\n getRuntimeContext,\n makeRuntimeContext,\n runRuntimeContext\n} from '../runtime/context'\n\nimport { defaultRuntimeContextStorage } from '../runtime/default'\n\nimport type { AnyServiceToken } from './types'\n\nimport type { RuntimeContextStorage } from '../runtime/context'\n\n/** Resolves class-backed Service tokens for a runtime execution. */\nexport interface ServiceResolver {\n /** Resolve a token to its corresponding Service instance. */\n resolve<T extends AnyServiceToken>(token: T): InstanceType<T> | PromiseLike<InstanceType<T>>\n}\n\n/** Provides the resolver context used by Service tokens during execution. */\nexport class ServiceRuntime {\n /**\n * Run a callback with a resolver available to `yield* Service` expressions.\n *\n * The context is scoped to the callback and is restored afterward.\n *\n * @example\n * ```ts\n * const value = ServiceRuntime.run(resolver, () => {\n * return ServiceRuntime.resolve(Database)\n * })\n * ```\n */\n static run<A>(\n resolver: ServiceResolver,\n program: () => A,\n storage: RuntimeContextStorage = defaultRuntimeContextStorage\n ): A {\n const current = getRuntimeContext(storage)\n const sameResolver = current?.resolver === resolver\n const context = makeRuntimeContext(\n resolver,\n current?.scope,\n sameResolver ? current.resolutionPath : [],\n current?.signal,\n current,\n current?.executionId\n )\n\n return runRuntimeContext(storage, context, program)\n }\n\n /** Return the resolver active in the current execution context. */\n static current(): ServiceResolver {\n let context\n\n try {\n context = currentRuntimeContext()\n } catch (cause) {\n if (cause instanceof RuntimeContextNotConfiguredError) {\n throw new ServiceRuntimeNotConfiguredError()\n }\n\n throw cause\n }\n\n if (!context.resolver) {\n throw new ServiceRuntimeNotConfiguredError()\n }\n\n return context.resolver\n }\n\n /** Resolve a Service token using the active resolver. */\n static async resolve<T extends AnyServiceToken>(token: T): Promise<InstanceType<T>> {\n captureServiceTag(token)\n const resolver = ServiceRuntime.current()\n\n return await resolver.resolve(token)\n }\n}\n","/** Thrown when Scope context is accessed outside an active Scope execution. */\nexport class ScopeRuntimeNotConfiguredError extends Error {\n constructor() {\n super('No Scope is available in the current execution context')\n\n this.name = 'ScopeRuntimeNotConfiguredError'\n }\n}\n\n/** Thrown when a resource or finalizer is added after Scope closure begins. */\nexport class ScopeClosedError extends Error {\n constructor() {\n super('Cannot add resources or finalizers to a closed Scope')\n\n this.name = 'ScopeClosedError'\n }\n}\n\n/** Aggregates finalizer failures encountered while closing a Scope. */\nexport class ScopeCloseError extends Error {\n constructor(readonly causes: readonly unknown[]) {\n super(\n `Failed to close Scope (${causes.length} finalizer${causes.length === 1 ? '' : 's'} failed)`\n )\n\n this.name = 'ScopeCloseError'\n }\n}\n\n/** Thrown when a value has neither Symbol.dispose nor Symbol.asyncDispose. */\nexport class ResourceNotDisposableError extends Error {\n constructor() {\n super('Resource does not implement Symbol.dispose or Symbol.asyncDispose')\n\n this.name = 'ResourceNotDisposableError'\n }\n}\n","import type { ScopeFinalizer } from './types'\n\nconst SCOPE_SUCCESS = { status: 'success' } as const\n\ntype Disposer = (...args: never[]) => void | PromiseLike<void>\n\ntype DisposableCandidate = {\n [Symbol.dispose]?: Disposer\n\n [Symbol.asyncDispose]?: Disposer\n}\n\n/** Return a Scope finalizer for a value's async or sync disposal protocol. */\nexport const getDisposeFinalizer = <Resource>(resource: Resource): ScopeFinalizer | undefined => {\n // SAFETY: Object() provides a property-bearing view for protocol lookup; each method is checked for callability before invocation.\n const candidate = Object(resource) as DisposableCandidate\n const asyncDispose = candidate[Symbol.asyncDispose]\n\n if (asyncDispose instanceof Function) {\n return () => asyncDispose.call(resource)\n }\n\n const dispose = candidate[Symbol.dispose]\n\n if (dispose instanceof Function) {\n return () => dispose.call(resource)\n }\n\n return undefined\n}\n\n/** Dispose a value immediately when it implements a disposal protocol. */\nexport const disposeResource = <Resource>(resource: Resource): void | PromiseLike<void> => {\n const finalizer = getDisposeFinalizer(resource)\n\n return finalizer?.(SCOPE_SUCCESS)\n}\n","import { LayerGeneratorYieldError } from './errors'\n\nimport { ServiceRuntime } from '../service'\nimport { captureServiceTag } from '../service/tag'\n\nimport type { ServiceRequirement } from '../effect/types'\nimport type { AnyServiceToken, ServiceToken } from '../service'\n\nimport type { LayerDiscardGenerator, LayerGenerator } from './types'\n\nexport const runLayerGenerator = async <\n S extends ServiceToken<any, any>,\n Yield extends ServiceRequirement<unknown>\n>(\n service: S,\n factory: LayerGenerator<S, Yield>\n): Promise<InstanceType<S>> => {\n const iterator = factory()\n\n let state = await iterator.next()\n\n while (!state.done) {\n const token = serviceTokenFromYield(state.value)\n\n if (token === undefined) {\n try {\n // SAFETY: The iterator is closed only to discard an invalid yield; its return value is ignored.\n await iterator.return(undefined as never)\n } finally {\n // oxlint-disable-next-line no-unsafe-finally\n throw new LayerGeneratorYieldError(service)\n }\n }\n\n state = await iterator.next(await ServiceRuntime.resolve(token))\n }\n\n // SAFETY: The public generator boundary accepts only the requested Service contract.\n return state.value as InstanceType<S>\n}\n\n/** Runtime-erased iterator accepted by lifecycle-only generator constructors. */\nexport type LayerDiscardIterator<Acquired = unknown> =\n | Generator<ServiceRequirement<unknown>, Acquired, unknown>\n | AsyncGenerator<ServiceRequirement<unknown>, Acquired, unknown>\n\n/** Run a lifecycle-only generator in the active ServiceRuntime context. */\nexport const runLayerDiscardGenerator = async <Yield extends ServiceRequirement<unknown>, Acquired>(\n factory: LayerDiscardGenerator<Yield, Acquired>\n): Promise<Acquired> => runLayerDiscardIterator(factory())\n\n/** Resolve Service yields from an erased lifecycle-only generator. */\n// oxlint-disable-next-line anti-slop/no-unknown-returns -- the iterator result is restored by the typed generator caller.\nexport const runLayerDiscardIterator = async <Acquired>(\n iterator: LayerDiscardIterator<Acquired>\n): Promise<Acquired> => {\n let state = await iterator.next()\n\n while (!state.done) {\n const token = serviceTokenFromYield(state.value)\n\n if (token === undefined) {\n try {\n // SAFETY: The iterator is closed only to discard an invalid yield; its return value is ignored.\n await iterator.return(undefined as never)\n } finally {\n // oxlint-disable-next-line no-unsafe-finally\n throw new TypeError('Layer.scopedDiscard generator yielded an unsupported value')\n }\n }\n\n state = await iterator.next(await ServiceRuntime.resolve(token))\n }\n\n return state.value\n}\n\n// oxlint-disable-next-line anti-slop/no-unknown-parameters -- Sync Layer generators expose Service tokens only through a runtime-erased yield.\nconst serviceTokenFromYield = (value: unknown): AnyServiceToken | undefined => {\n try {\n captureServiceTag(value)\n\n // SAFETY: A valid Service token is the only runtime value emitted by the sync Service iterator.\n return value as AnyServiceToken\n } catch {\n return undefined\n }\n}\n","import { Result } from 'better-result'\n\nimport type {\n EffectError,\n EffectRequirements,\n EffectSuccess,\n Program,\n ServiceRequirement\n} from '../effect/types'\nimport { ServiceRuntime } from '../service'\nimport { captureServiceTag } from '../service/tag'\nimport type {\n AnyService,\n ServiceClass,\n ServiceContract,\n ServiceRequirements,\n ServiceToken\n} from '../service'\nimport { ResourceNotDisposableError } from '../scope'\nimport { getDisposeFinalizer } from '../scope/disposable'\n\nimport type { DisposableResource, ScopeFinalizer, ScopeOutcome } from '../scope'\nimport type { Covariant, Invariant } from '../internal/variance'\nimport type { MaybePromise } from '../utils/types'\n\nimport { DuplicateServiceError, ServiceTagCollisionError } from './errors'\nimport {\n runLayerDiscardGenerator,\n runLayerDiscardIterator,\n runLayerGenerator,\n type LayerDiscardIterator\n} from './internal'\nimport { captureLayerRegistrationTag } from './registration'\n\nimport type {\n LayerInput,\n CompleteInput,\n LayerResult,\n MergeResult,\n OverrideLayerResult,\n ValidateLayerInput,\n ValidateLayerTuple,\n ValidateOverrides,\n ProvidedEnvironment,\n RequiredEnvironment\n} from './inference'\nimport type { ProviderEntry } from './metadata'\nimport type {\n LayerDiscardGenerator,\n LayerDiscardRequirements,\n LayerLifecycle,\n LayerGenerator,\n LayerGeneratorRequirements,\n LayerQuiesce,\n LayerRegistration\n} from './types'\n\ndeclare const LayerTypeId: unique symbol\n\ninterface LayerVariance<in out Provided, out Required> {\n readonly _Provided: Invariant<Provided>\n readonly _Required: Covariant<Required>\n}\n\ntype CapturedLayerAcquisition = {\n readonly instance: unknown\n readonly release: ScopeFinalizer\n}\n\ninterface LayerProvider extends LayerRegistration {\n /** The tag captured before this provider can cross an asynchronous boundary. */\n readonly serviceTag: string\n\n /** Provider storage deliberately erases the concrete instance type. */\n // oxlint-disable-next-line anti-slop/no-unknown-parameters\n readonly release?: (instance: unknown, outcome: ScopeOutcome) => MaybePromise<void>\n\n readonly quiesce?: LayerQuiesce\n\n /** Capture acquisition-local cleanup without retaining the acquired instance. */\n readonly acquireWithRelease?: () => MaybePromise<CapturedLayerAcquisition>\n}\n\ntype MutableLayerProvider = Omit<LayerProvider, 'quiesce'> & {\n quiesce?: LayerQuiesce\n}\n\ntype LifecycleCallback<Instance> =\n | ((instance: Instance, outcome: ScopeOutcome) => MaybePromise<void>)\n | LayerLifecycle<Instance>\n\n/** Internal lifecycle entry that deliberately has no Service identity. */\nexport interface LayerLifecycleEntry {\n readonly kind: 'lifecycle'\n readonly id: symbol\n readonly acquire: () => MaybePromise<unknown>\n // oxlint-disable-next-line anti-slop/no-unknown-parameters -- Lifecycle resources are intentionally opaque to the Layer runtime.\n readonly release: (instance: unknown, outcome: ScopeOutcome) => MaybePromise<void>\n readonly quiesce?: LayerQuiesce\n}\n\ntype MutableLayerLifecycleEntry = Omit<LayerLifecycleEntry, 'quiesce'> & {\n quiesce?: LayerQuiesce\n}\n\ntype LayerEntry = LayerProvider | LayerLifecycleEntry\n\nconst layerEntries = new WeakMap<object, readonly LayerEntry[]>()\n\nconst isLifecycleEntry = (entry: LayerEntry): entry is LayerLifecycleEntry =>\n 'kind' in entry && entry.kind === 'lifecycle'\n\n/** Read all entries while keeping lifecycle storage out of the public declaration. */\nexport const getLayerEntries = (layer: LayerInput): readonly LayerEntry[] =>\n layerEntries.get(layer) ?? layer.providers\n\ntype AnyProgram = Program<any, any, AnyService>\n\ntype EffectDiscardValidation<P extends AnyProgram> = [EffectSuccess<P>] extends [void]\n ? [EffectError<P>] extends [never]\n ? unknown\n : {\n readonly __betterEffectDiscardTypedFailure: unique symbol\n }\n : {\n readonly __betterEffectDiscardSuccessMustBeVoid: unique symbol\n }\n\n/** A Service class whose constructor can be called without arguments. */\ntype DefaultConstructibleServiceClass<\n Tag extends string = string,\n Instance extends AnyService = AnyService\n> = ServiceClass<Tag, Instance> & (new () => Instance)\n\ntype IsUnion<Type, Candidate = Type> = Type extends unknown\n ? [Candidate] extends [Type]\n ? false\n : true\n : never\n\ntype InvalidUnionAliasToken = {\n readonly __betterEffectUnionLayerAliasToken: unique symbol\n}\n\ntype RejectUnionAliasToken<Token> = IsUnion<Token> extends true ? InvalidUnionAliasToken : unknown\n\ntype LayerAliasOptions<From extends ServiceToken<any, any>, To extends ServiceToken<any, any>> = {\n readonly from: From\n readonly to: To\n} & RejectUnionAliasToken<From> &\n RejectUnionAliasToken<To> &\n ([ServiceContract<InstanceType<From>>] extends [ServiceContract<InstanceType<To>>]\n ? unknown\n : {\n readonly __betterEffectIncompatibleLayerAlias: unique symbol\n })\n\n/**\n * Declarative collection of Service providers.\n *\n * A Layer describes how to acquire implementations; it does not execute\n * providers until a `Runtime` is created. Use `merge` to compose distinct\n * providers and `override` when replacing an existing provider intentionally.\n *\n * @example\n * ```ts\n * const AppLive = Layer.merge(\n * Layer.succeed(Database, database),\n * Layer.make(UserRepository)\n * )\n *\n * const runtime = await Runtime.make(AppLive, backend)\n * ```\n */\nexport class Layer<\n in out Provided extends AnyService = AnyService,\n out Required extends AnyService = AnyService\n> {\n declare readonly [LayerTypeId]: LayerVariance<Provided, Required>\n\n /** The Service provider registrations retained by this Layer. */\n readonly providers: readonly LayerProvider[]\n\n private constructor(entries: readonly LayerEntry[]) {\n const frozenEntries = Object.freeze(\n entries.map((entry) => {\n if (isLifecycleEntry(entry)) {\n return Object.freeze({ ...entry })\n }\n\n return Object.freeze({\n ...entry,\n serviceTag: captureLayerRegistrationTag(entry)\n })\n })\n )\n\n layerEntries.set(this, frozenEntries)\n this.providers = Object.freeze(\n frozenEntries.filter((entry): entry is LayerProvider => !isLifecycleEntry(entry))\n )\n }\n\n private static makeLifecycleLayer<RawRequired extends AnyService>(\n acquire: () => MaybePromise<unknown>,\n // oxlint-disable-next-line anti-slop/no-unknown-parameters -- Lifecycle resources are intentionally opaque to the Layer runtime.\n release: (instance: unknown, outcome: ScopeOutcome) => MaybePromise<void>,\n quiesce?: LayerQuiesce\n ): LayerResult<ProviderEntry<never, RawRequired>> {\n // SAFETY: Lifecycle entries have no public Service environment; the typed requirements are declaration-only provenance.\n const entry: MutableLayerLifecycleEntry = {\n kind: 'lifecycle',\n id: Symbol('better-effect.lifecycle'),\n acquire,\n release\n }\n\n if (quiesce !== undefined) {\n entry.quiesce = quiesce\n }\n\n // SAFETY: Lifecycle entries carry only declaration-level requirements, erased by the Layer storage boundary.\n return new Layer([entry]) as LayerResult<ProviderEntry<never, RawRequired>>\n }\n\n /** A stable provider-free Layer for composition roots with no Services. */\n static readonly empty: Layer<never, never> = Object.freeze(new Layer<never, never>([]))\n\n /** Create a Layer that lazily acquires a Service instance. */\n static make<S extends DefaultConstructibleServiceClass<any, any>>(\n service: S\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>>\n\n static make<S extends ServiceToken<any, any>>(\n service: S,\n acquire: () => MaybePromise<ServiceContract<InstanceType<S>>>\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>>\n\n static make<S extends ServiceToken<any, any>>(\n service: S,\n acquire?: () => MaybePromise<ServiceContract<InstanceType<S>>>\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>> {\n const serviceTag = captureServiceTag(service)\n const defaultAcquire = (): InstanceType<S> => {\n // SAFETY: The no-argument overload constrains `service` to a default constructible class.\n // oxlint-disable-next-line anti-slop/no-chained-type-assertions -- the overload supplies the erased constructor guarantee.\n const Constructor = service as unknown as new () => InstanceType<S>\n\n return new Constructor()\n }\n\n const normalizedAcquire = normalizeAcquire<S>(acquire ?? defaultAcquire)\n\n // SAFETY: Runtime storage erases only the concrete provider metadata; the public constructor result restores its typed provenance.\n return new Layer([\n {\n service,\n serviceTag,\n acquire: normalizedAcquire\n }\n ]) as LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>>\n }\n\n /** Create a Layer from an already-constructed Service instance. */\n static succeed<S extends ServiceToken<any, any>>(\n service: S,\n instance: ServiceContract<InstanceType<S>>\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>> {\n const serviceTag = captureServiceTag(service)\n const normalizedAcquire = normalizeAcquire<S>(() => instance)\n\n // SAFETY: The structural instance has been checked against the requested Service contract.\n return new Layer([\n {\n service,\n serviceTag,\n acquire: normalizedAcquire\n }\n ]) as LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>>\n }\n\n /** Alias a source Service under a compatible target contract. */\n static alias<From extends ServiceToken<any, any>, To extends ServiceToken<any, any>>(\n options: LayerAliasOptions<From, To>\n ): LayerResult<\n ProviderEntry<InstanceType<To>, InstanceType<From> | ServiceRequirements<InstanceType<To>>>\n > {\n const { from, to } = options\n void captureServiceTag(from)\n\n // Keep alias acquisition in the normal Layer generator path so Runtime supplies the active resolver and resolution diagnostics.\n // oxlint-disable-next-line require-yield\n const alias = Layer.gen(to, async function* () {\n const source = await ServiceRuntime.resolve(from)\n\n // SAFETY: LayerAliasOptions checks that the source implementation satisfies the target contract.\n return source as ServiceContract<InstanceType<To>>\n })\n\n // SAFETY: The alias factory resolves the declared source token before returning the target contract.\n return alias as LayerResult<\n ProviderEntry<InstanceType<To>, InstanceType<From> | ServiceRequirements<InstanceType<To>>>\n >\n }\n\n /** Define a provider with Runtime-root cleanup. */\n static scoped<S extends ServiceToken<any, any>>(\n service: S,\n acquire: () => MaybePromise<ServiceContract<InstanceType<S>>>,\n release: (instance: InstanceType<S>, outcome: ScopeOutcome) => MaybePromise<void>\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>>\n\n static scoped<S extends ServiceToken<any, any>>(\n service: S,\n acquire: () => MaybePromise<ServiceContract<InstanceType<S>>>,\n lifecycle: LayerLifecycle<InstanceType<S>>\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>>\n\n static scoped<S extends ServiceToken<any, any>>(\n service: S,\n acquire: () => MaybePromise<ServiceContract<InstanceType<S>>>,\n lifecycleOrRelease: LifecycleCallback<InstanceType<S>>\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>> {\n const serviceTag = captureServiceTag(service)\n const normalized = normalizeLifecycle(lifecycleOrRelease)\n\n const provider: MutableLayerProvider = {\n service,\n serviceTag,\n acquire: normalizeAcquire<S>(acquire),\n release: (instance, outcome) => {\n // SAFETY: The backend invokes release with the instance acquired for this token.\n return normalized.release(instance as InstanceType<S>, outcome)\n }\n }\n\n if (normalized.quiesce !== undefined) {\n // SAFETY: The lifecycle overload constrains this erased instance to InstanceType<S>.\n provider.quiesce = (instance, reason) =>\n normalized.quiesce!(instance as InstanceType<S>, reason)\n }\n\n // SAFETY: The public callbacks constrain acquisition and release to the requested Service.\n return new Layer([provider]) as LayerResult<\n ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>\n >\n }\n\n /** Define a provider with Runtime-root cleanup through its disposal protocol. */\n static scopedDisposable<S extends ServiceToken<any, any>>(\n service: S,\n acquire: () => MaybePromise<ServiceContract<InstanceType<S>> & DisposableResource>\n ): LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>> {\n const acquireWithRelease = async (): Promise<CapturedLayerAcquisition> => {\n const instance = await acquire()\n const finalizer = getDisposeFinalizer(instance)\n\n if (!finalizer) {\n throw new ResourceNotDisposableError()\n }\n\n return { instance, release: finalizer }\n }\n\n const serviceTag = captureServiceTag(service)\n\n // SAFETY: The public callback constrains the acquired value and this runtime-only carrier is erased at the Layer boundary.\n return new Layer([\n {\n service,\n serviceTag,\n acquire: async () => (await acquireWithRelease()).instance,\n acquireWithRelease\n }\n ]) as LayerResult<ProviderEntry<InstanceType<S>, ServiceRequirements<InstanceType<S>>>>\n }\n\n /** Define a provider whose acquisition can yield contextual Services. */\n static scopedGen<S extends ServiceToken<any, any>, Yield extends ServiceRequirement<unknown>>(\n service: S,\n factory: LayerGenerator<S, Yield>,\n release: (instance: InstanceType<S>, outcome: ScopeOutcome) => MaybePromise<void>\n ): LayerResult<ProviderEntry<InstanceType<S>, LayerGeneratorRequirements<S, Yield>>>\n\n static scopedGen<S extends ServiceToken<any, any>, Yield extends ServiceRequirement<unknown>>(\n service: S,\n factory: LayerGenerator<S, Yield>,\n lifecycle: LayerLifecycle<InstanceType<S>>\n ): LayerResult<ProviderEntry<InstanceType<S>, LayerGeneratorRequirements<S, Yield>>>\n\n static scopedGen<S extends ServiceToken<any, any>, Yield extends ServiceRequirement<unknown>>(\n service: S,\n factory: LayerGenerator<S, Yield>,\n lifecycleOrRelease: LifecycleCallback<InstanceType<S>>\n ): LayerResult<ProviderEntry<InstanceType<S>, LayerGeneratorRequirements<S, Yield>>> {\n const serviceTag = captureServiceTag(service)\n const normalized = normalizeLifecycle(lifecycleOrRelease)\n\n const provider: MutableLayerProvider = {\n service,\n serviceTag,\n acquire: () => runLayerGenerator(service, factory),\n release: (instance, outcome) => {\n // SAFETY: The backend invokes release with the instance acquired for this token.\n return normalized.release(instance as InstanceType<S>, outcome)\n }\n }\n\n if (normalized.quiesce !== undefined) {\n // SAFETY: The lifecycle overload constrains this erased instance to InstanceType<S>.\n provider.quiesce = (instance, reason) =>\n normalized.quiesce!(instance as InstanceType<S>, reason)\n }\n\n // SAFETY: The generator and release callback are checked against the requested Service.\n return new Layer([provider]) as LayerResult<\n ProviderEntry<InstanceType<S>, LayerGeneratorRequirements<S, Yield>>\n >\n }\n\n /** Define a provider whose acquisition can yield contextual Services. */\n static gen<S extends ServiceToken<any, any>, Yield extends ServiceRequirement<unknown>>(\n service: S,\n factory: LayerGenerator<S, Yield>\n ): LayerResult<ProviderEntry<InstanceType<S>, LayerGeneratorRequirements<S, Yield>>> {\n const serviceTag = captureServiceTag(service)\n\n // SAFETY: The generator result is normalized to the requested Service at the runtime boundary.\n return new Layer([\n {\n service,\n serviceTag,\n acquire: () => runLayerGenerator(service, factory)\n }\n ]) as LayerResult<ProviderEntry<InstanceType<S>, LayerGeneratorRequirements<S, Yield>>>\n }\n\n /** Define a lifecycle-only entry with direct acquisition and root cleanup. */\n static scopedDiscard<Yield extends ServiceRequirement<unknown>, Acquired>(\n acquire: LayerDiscardGenerator<Yield, Acquired>,\n release: (instance: Acquired, outcome: ScopeOutcome) => MaybePromise<void>\n ): LayerResult<ProviderEntry<never, LayerDiscardRequirements<Yield>>>\n\n static scopedDiscard<Yield extends ServiceRequirement<unknown>, Acquired>(\n acquire: LayerDiscardGenerator<Yield, Acquired>,\n lifecycle: LayerLifecycle<Acquired>\n ): LayerResult<ProviderEntry<never, LayerDiscardRequirements<Yield>>>\n\n static scopedDiscard<Acquired>(\n acquire: () => MaybePromise<Acquired>,\n release: (instance: Acquired, outcome: ScopeOutcome) => MaybePromise<void>\n ): LayerResult<ProviderEntry<never, never>>\n\n static scopedDiscard<Acquired>(\n acquire: () => MaybePromise<Acquired>,\n lifecycle: LayerLifecycle<Acquired>\n ): LayerResult<ProviderEntry<never, never>>\n\n static scopedDiscard(\n acquire:\n | (() => MaybePromise<unknown>)\n | LayerDiscardGenerator<ServiceRequirement<unknown>, unknown>,\n // oxlint-disable-next-line anti-slop/no-unknown-parameters -- Lifecycle resources are intentionally opaque to the Layer runtime.\n releaseOrLifecycle: LifecycleCallback<unknown>\n ): LayerResult<ProviderEntry<never, AnyService>> {\n const lifecycle = normalizeLifecycle(releaseOrLifecycle)\n\n return Layer.makeLifecycleLayer(\n () => {\n const acquired = acquire()\n\n if (isIteratorLike(acquired)) {\n return runLayerDiscardIterator(acquired)\n }\n\n return acquired\n },\n lifecycle.release,\n lifecycle.quiesce\n )\n }\n\n /** Define a lifecycle-only entry whose acquisition can yield contextual Services. */\n static scopedDiscardGen<Yield extends ServiceRequirement<unknown>, Acquired>(\n acquire: LayerDiscardGenerator<Yield, Acquired>,\n release: (instance: Acquired, outcome: ScopeOutcome) => MaybePromise<void>\n ): LayerResult<ProviderEntry<never, LayerDiscardRequirements<Yield>>>\n\n static scopedDiscardGen<Yield extends ServiceRequirement<unknown>, Acquired>(\n acquire: LayerDiscardGenerator<Yield, Acquired>,\n lifecycle: LayerLifecycle<Acquired>\n ): LayerResult<ProviderEntry<never, LayerDiscardRequirements<Yield>>>\n\n static scopedDiscardGen<Yield extends ServiceRequirement<unknown>, Acquired>(\n acquire: LayerDiscardGenerator<Yield, Acquired>,\n lifecycleOrRelease: LifecycleCallback<Acquired>\n ): LayerResult<ProviderEntry<never, LayerDiscardRequirements<Yield>>> {\n const normalized = normalizeLifecycle(lifecycleOrRelease)\n\n // SAFETY: Lifecycle generator requirements are carried only in declaration metadata; runtime storage is intentionally erased.\n return Layer.makeLifecycleLayer(\n () => runLayerDiscardGenerator(acquire),\n (instance, outcome) => {\n // SAFETY: The overload constrains this resource to Acquired before the erased Layer boundary.\n return normalized.release(instance as Acquired, outcome)\n },\n normalized.quiesce === undefined\n ? undefined\n : (instance, reason) => normalized.quiesce!(instance as Acquired, reason)\n ) as LayerResult<ProviderEntry<never, LayerDiscardRequirements<Yield>>>\n }\n\n /** Run a no-failure Effect Program as a lifecycle-only entry. */\n static effectDiscard<P extends AnyProgram>(\n program: P & EffectDiscardValidation<P>\n ): LayerResult<ProviderEntry<never, Extract<EffectRequirements<P>, AnyService>>> {\n // SAFETY: The public validation preserves the no-failure Program contract while the Layer entry erases its unit resource.\n return Layer.makeLifecycleLayer<Extract<EffectRequirements<P>, AnyService>>(\n async () => {\n const result = await program()\n\n if (Result.isError(result)) {\n throw result.error\n }\n },\n async () => {}\n ) as LayerResult<ProviderEntry<never, Extract<EffectRequirements<P>, AnyService>>>\n }\n\n /** Compose Layers without replacing providers. */\n static merge<const Layers extends readonly LayerInput[]>(\n ...layers: Layers & ValidateLayerTuple<Layers>\n ): MergeResult<Layers> {\n const entries = new Map<string | symbol, LayerEntry>()\n\n for (const layer of layers) {\n for (const entry of getLayerEntries(layer)) {\n if (isLifecycleEntry(entry)) {\n entries.set(entry.id, entry)\n continue\n }\n\n const service = entry.service\n const serviceTag = captureLayerRegistrationTag(entry)\n const existing = entries.get(serviceTag)\n\n if (existing) {\n if (isLifecycleEntry(existing)) {\n throw new Error('Layer lifecycle entry identity collided with a Service tag')\n }\n\n if (existing.service !== service) {\n throw new ServiceTagCollisionError(existing.service, service)\n }\n\n throw new DuplicateServiceError(service)\n }\n\n entries.set(serviceTag, entry)\n }\n }\n\n // SAFETY: The heterogeneous provider list is erased only at this internal storage boundary.\n return new Layer([...entries.values()]) as MergeResult<Layers>\n }\n\n /** Mark a Layer composition root as complete without changing its runtime value. */\n static complete<L extends LayerInput>(layer: L & CompleteInput<L>): L {\n return layer\n }\n\n /** Replace providers in a base Layer, using tag identity and compatible contracts. */\n static override<Base extends LayerInput>(\n base: Base & ValidateLayerInput<Base>\n ): OverrideLayerResult<Base, readonly []>\n\n static override<\n Base extends LayerInput,\n const Overrides extends readonly [LayerInput, ...LayerInput[]]\n >(\n base: Base & ValidateLayerInput<Base>,\n ...overrides: Overrides & ValidateOverrides<Base, Overrides>\n ): OverrideLayerResult<Base, Overrides>\n\n static override<Base extends LayerInput, const Overrides extends readonly LayerInput[]>(\n base: Base & ValidateLayerInput<Base>,\n ...overrides: Overrides & ValidateOverrides<Base, Overrides>\n ): OverrideLayerResult<Base, Overrides>\n\n static override(base: LayerInput, ...overrides: readonly LayerInput[]): Layer<any, any> {\n const entries = new Map<string | symbol, LayerEntry>()\n\n for (const entry of getLayerEntries(base)) {\n entries.set(isLifecycleEntry(entry) ? entry.id : captureLayerRegistrationTag(entry), entry)\n }\n\n for (const layer of overrides) {\n for (const entry of getLayerEntries(layer)) {\n entries.set(isLifecycleEntry(entry) ? entry.id : captureLayerRegistrationTag(entry), entry)\n }\n }\n\n // SAFETY: Runtime provider replacement preserves the computed override metadata.\n return new Layer([...entries.values()]) as Layer<any, any>\n }\n}\n\n// TypeScript's `readonly` does not affect the runtime property descriptor. Keep\n// the class field's enumerable behavior while locking the singleton binding.\nObject.defineProperty(Layer, 'empty', {\n value: Layer.empty,\n writable: false,\n enumerable: true,\n configurable: false\n})\n\nconst normalizeAcquire =\n <S extends ServiceToken<any, any>>(\n acquire: () => MaybePromise<ServiceContract<InstanceType<S>>>\n ): (() => MaybePromise<InstanceType<S>>) =>\n () => {\n // SAFETY: ServiceContract removes only the declaration-only identity; runtime values are unchanged.\n return acquire() as MaybePromise<InstanceType<S>>\n }\n\nconst normalizeLifecycle = <Instance>(\n lifecycle: LifecycleCallback<Instance>\n): LayerLifecycle<Instance> => {\n // oxlint-disable-next-line anti-slop/no-runtime-typeof -- lifecycle callbacks are a deliberately supported function-or-object API.\n if (typeof lifecycle === 'function') {\n return { release: lifecycle }\n }\n\n return lifecycle\n}\n\n// oxlint-disable-next-line anti-slop/no-unknown-parameters -- Lifecycle factories are runtime-erased at this boundary.\nconst isIteratorLike = (value: unknown): value is LayerDiscardIterator => {\n if (!(value instanceof Object) || !('next' in value)) {\n return false\n }\n\n return value.next instanceof Function\n}\n\n/** Type-level aliases for inspecting Layer environments and completeness. */\nexport declare namespace Layer {\n /** The widened Layer shape accepted by generic Layer infrastructure. */\n export type Any = LayerInput\n\n /** Extract the branded Service instances provided by a Layer. */\n export type Provided<L extends LayerInput> = ProvidedEnvironment<L>\n\n /** Extract the external Service requirements of a Layer. */\n export type Required<L extends LayerInput> = RequiredEnvironment<L>\n\n /** Extract the Services still missing from a Layer composition. */\n export type Missing<L extends LayerInput> = RequiredEnvironment<L>\n\n /** Validate a Layer's requirements and input shape. */\n export type Complete<L extends LayerInput> = CompleteInput<L>\n}\n"],"mappings":"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"}