better-effect 0.13.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 (109) hide show
  1. package/README.md +337 -88
  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 +75 -23
  6. package/dist/bun.d.mts.map +1 -1
  7. package/dist/bun.mjs +170 -33
  8. package/dist/bun.mjs.map +1 -1
  9. package/dist/{context-BphfFUMO.mjs → context-DSGSqcJj.mjs} +12 -3
  10. package/dist/context-DSGSqcJj.mjs.map +1 -0
  11. package/dist/{current-request-DDKNyymv.mjs → current-request-Bc1YHL0w.mjs} +3 -2
  12. package/dist/{current-request-DDKNyymv.mjs.map → current-request-Bc1YHL0w.mjs.map} +1 -1
  13. package/dist/{current-request-CIU7AHhF.d.mts → current-request-Dm-QQ3Xr.d.mts} +4 -4
  14. package/dist/current-request-Dm-QQ3Xr.d.mts.map +1 -0
  15. package/dist/{effect-CPdV7Yv8.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 +63 -27
  20. package/dist/hono.d.mts.map +1 -1
  21. package/dist/hono.mjs +111 -45
  22. package/dist/hono.mjs.map +1 -1
  23. package/dist/{index-CCi07kUw.d.mts → index-3Bkl-sxS.d.mts} +7 -2
  24. package/dist/{index-CCi07kUw.d.mts.map → index-3Bkl-sxS.d.mts.map} +1 -1
  25. package/dist/{index-cXgyMa0v.d.mts → index-C2ed9Ilq.d.mts} +32 -7
  26. package/dist/index-C2ed9Ilq.d.mts.map +1 -0
  27. package/dist/{index-BodMy6rO.d.mts → index-ClNndn2-.d.mts} +93 -63
  28. package/dist/index-ClNndn2-.d.mts.map +1 -0
  29. package/dist/{index-DAKn0qHk.d.mts → index-Cy1VsU-u.d.mts} +2 -4
  30. package/dist/index-Cy1VsU-u.d.mts.map +1 -0
  31. package/dist/index.d.mts +6 -8
  32. package/dist/index.mjs +8 -9
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/{internal-identity-CbXoZIfw.mjs → internal-identity-BuHBtP0k.mjs} +2 -2
  35. package/dist/{internal-identity-CbXoZIfw.mjs.map → internal-identity-BuHBtP0k.mjs.map} +1 -1
  36. package/dist/layer-2kjHVv4N.mjs +343 -0
  37. package/dist/layer-2kjHVv4N.mjs.map +1 -0
  38. package/dist/layer-C2OaqTmB.d.mts +987 -0
  39. package/dist/layer-C2OaqTmB.d.mts.map +1 -0
  40. package/dist/next.d.mts +102 -26
  41. package/dist/next.d.mts.map +1 -1
  42. package/dist/next.mjs +157 -40
  43. package/dist/next.mjs.map +1 -1
  44. package/dist/{node-context-DczjAcrX.d.mts → node-context-1YEjrU9g.d.mts} +2 -2
  45. package/dist/{node-context-DczjAcrX.d.mts.map → node-context-1YEjrU9g.d.mts.map} +1 -1
  46. package/dist/{node-context-Ca18oNSg.mjs → node-context-g3bCcY9t.mjs} +2 -2
  47. package/dist/{node-context-Ca18oNSg.mjs.map → node-context-g3bCcY9t.mjs.map} +1 -1
  48. package/dist/node.d.mts +11 -6
  49. package/dist/node.d.mts.map +1 -1
  50. package/dist/node.mjs +156 -10
  51. package/dist/node.mjs.map +1 -1
  52. package/dist/opentelemetry.d.mts +20 -2
  53. package/dist/opentelemetry.d.mts.map +1 -1
  54. package/dist/opentelemetry.mjs +423 -5
  55. package/dist/opentelemetry.mjs.map +1 -1
  56. package/dist/{registration-drnZk0SY.mjs → registration-Bwe2GbVu.mjs} +8 -2
  57. package/dist/registration-Bwe2GbVu.mjs.map +1 -0
  58. package/dist/runtime/explicit.d.mts +2 -2
  59. package/dist/runtime/explicit.mjs +1 -1
  60. package/dist/runtime/node.d.mts +3 -3
  61. package/dist/runtime/node.mjs +2 -2
  62. package/dist/runtime-qpcVwaz_.mjs +1680 -0
  63. package/dist/runtime-qpcVwaz_.mjs.map +1 -0
  64. package/dist/service-CO9VJQYa.mjs +74 -0
  65. package/dist/service-CO9VJQYa.mjs.map +1 -0
  66. package/dist/{signal-nfgFyNCk.mjs → signal-5Rg9bUUe.mjs} +2 -2
  67. package/dist/{signal-nfgFyNCk.mjs.map → signal-5Rg9bUUe.mjs.map} +1 -1
  68. package/dist/{standard-services-vnGIafkS.mjs → standard-services-B-iMM_W7.mjs} +38 -4
  69. package/dist/standard-services-B-iMM_W7.mjs.map +1 -0
  70. package/dist/standard-services.d.mts +4 -4
  71. package/dist/standard-services.mjs +3 -3
  72. package/dist/testing.d.mts +25 -7
  73. package/dist/testing.d.mts.map +1 -1
  74. package/dist/testing.mjs +51 -7
  75. package/dist/testing.mjs.map +1 -1
  76. package/dist/{types-oihI-ESv.d.mts → types-BFTqCCcw.d.mts} +32 -5
  77. package/dist/types-BFTqCCcw.d.mts.map +1 -0
  78. package/dist/web-effect-B9hp9jIe.mjs +380 -0
  79. package/dist/web-effect-B9hp9jIe.mjs.map +1 -0
  80. package/dist/web.d.mts +22 -13
  81. package/dist/web.d.mts.map +1 -1
  82. package/dist/web.mjs +1 -1
  83. package/package.json +10 -16
  84. package/dist/context-BphfFUMO.mjs.map +0 -1
  85. package/dist/current-request-CIU7AHhF.d.mts.map +0 -1
  86. package/dist/disposable-CP-Q2H3l.mjs +0 -57
  87. package/dist/disposable-CP-Q2H3l.mjs.map +0 -1
  88. package/dist/effect-CPdV7Yv8.mjs.map +0 -1
  89. package/dist/errors-BKcsQ0ip.d.mts.map +0 -1
  90. package/dist/index-AiKM71-u.d.mts +0 -376
  91. package/dist/index-AiKM71-u.d.mts.map +0 -1
  92. package/dist/index-BodMy6rO.d.mts.map +0 -1
  93. package/dist/index-DAKn0qHk.d.mts.map +0 -1
  94. package/dist/index-cXgyMa0v.d.mts.map +0 -1
  95. package/dist/layer-D16GKxuX.mjs +0 -269
  96. package/dist/layer-D16GKxuX.mjs.map +0 -1
  97. package/dist/observer-9nhbL7Pr.d.mts +0 -68
  98. package/dist/observer-9nhbL7Pr.d.mts.map +0 -1
  99. package/dist/outcome-DI8LPIQ4.d.mts +0 -387
  100. package/dist/outcome-DI8LPIQ4.d.mts.map +0 -1
  101. package/dist/program-metadata-BxjGkT17.mjs +0 -260
  102. package/dist/program-metadata-BxjGkT17.mjs.map +0 -1
  103. package/dist/registration-drnZk0SY.mjs.map +0 -1
  104. package/dist/runtime-C_55ofnL.mjs +0 -791
  105. package/dist/runtime-C_55ofnL.mjs.map +0 -1
  106. package/dist/standard-services-vnGIafkS.mjs.map +0 -1
  107. package/dist/types-oihI-ESv.d.mts.map +0 -1
  108. package/dist/web-Bq3MfMrj.mjs +0 -147
  109. package/dist/web-Bq3MfMrj.mjs.map +0 -1
@@ -0,0 +1,1680 @@
1
+ import { c as CircularDependencyError, f as captureServiceTag, i as LayerDisposeError, l as ServiceAcquisitionError, n as normalizeLayerRegistration, o as LayerRegistrationError, r as DuplicateServiceError, s as ServiceTagCollisionError, t as captureLayerRegistrationTag, u as ServiceNotFoundError } from "./registration-Bwe2GbVu.mjs";
2
+ import { _ as RuntimeExecutorNotConfiguredError, h as RuntimeContextNotConfiguredError, i as getRuntimeContext, l as makeRuntimeContext, n as currentRuntimeContext, t as activeRuntimeContextStorage, u as runRuntimeContext } from "./context-DSGSqcJj.mjs";
3
+ import { a as ResourceNotDisposableError, c as ScopeRuntimeNotConfiguredError, i as getDisposeFinalizer, n as getLayerEntries, o as ScopeCloseError, s as ScopeClosedError, u as defaultRuntimeContextStorage } from "./layer-2kjHVv4N.mjs";
4
+ import { t as assertServiceCompatibility } from "./internal-identity-BuHBtP0k.mjs";
5
+ import { n as linkAbortSignals } from "./signal-5Rg9bUUe.mjs";
6
+ import { Err } from "better-result";
7
+ //#region src/scope/runtime.ts
8
+ const scopeStorages = /* @__PURE__ */ new WeakMap();
9
+ /** Bridges the current Scope through async execution context. */
10
+ var ScopeRuntime = class {
11
+ /** Supply a Scope while invoking a callback. */
12
+ static run(scope, program, storage = scopeStorages.get(scope) ?? activeRuntimeContextStorage()) {
13
+ scopeStorages.set(scope, storage);
14
+ const current = getRuntimeContext(storage);
15
+ const context = makeRuntimeContext(current?.resolver, scope, current?.resolutionPath ?? [], current?.signal, current);
16
+ return runRuntimeContext(storage, context, program);
17
+ }
18
+ /** Return the Scope active in the current execution context. */
19
+ static current() {
20
+ let context;
21
+ try {
22
+ context = currentRuntimeContext();
23
+ } catch (cause) {
24
+ if (cause instanceof RuntimeContextNotConfiguredError) throw new ScopeRuntimeNotConfiguredError();
25
+ throw cause;
26
+ }
27
+ if (!context.scope) throw new ScopeRuntimeNotConfiguredError();
28
+ return context.scope;
29
+ }
30
+ /** Associate a Runtime-owned Scope with its context storage. */
31
+ static bind(scope, storage) {
32
+ scopeStorages.set(scope, storage);
33
+ }
34
+ };
35
+ //#endregion
36
+ //#region src/scope/internal.ts
37
+ const scopeImplementations = /* @__PURE__ */ new WeakMap();
38
+ /** Register the private implementation hook used by lifecycle primitives. */
39
+ const registerScopeImplementation = (scope, implementation) => {
40
+ scopeImplementations.set(scope, implementation);
41
+ };
42
+ /** Register work that must run before attached child Scopes close. */
43
+ const addScopePreFinalizer = (scope, finalizer) => {
44
+ const implementation = scopeImplementations.get(scope);
45
+ if (!implementation) throw new TypeError("Scope does not support internal pre-finalizers");
46
+ implementation.addPreFinalizer(finalizer);
47
+ };
48
+ const notifyCleanupFailure = async (observer, diagnostic) => {
49
+ if (!observer) return;
50
+ try {
51
+ await observer(diagnostic);
52
+ } catch {}
53
+ };
54
+ const runScoped = async (scope, program, options) => {
55
+ let value;
56
+ let programFailed = false;
57
+ let programFailure;
58
+ try {
59
+ const run = () => ScopeRuntime.run(scope, program, options.contextStorage);
60
+ value = await (options.context && options.contextStorage ? runRuntimeContext(options.contextStorage, options.context, run) : run());
61
+ } catch (cause) {
62
+ programFailed = true;
63
+ programFailure = cause;
64
+ }
65
+ let outcome;
66
+ let outcomeStatus;
67
+ if (programFailed) {
68
+ outcome = {
69
+ status: "failure",
70
+ cause: programFailure
71
+ };
72
+ outcomeStatus = "failure";
73
+ } else try {
74
+ outcome = options.classify(value);
75
+ outcomeStatus = outcome.status;
76
+ } catch (cause) {
77
+ programFailed = true;
78
+ programFailure = cause;
79
+ outcome = {
80
+ status: "failure",
81
+ cause
82
+ };
83
+ outcomeStatus = "failure";
84
+ }
85
+ options.onOutcome?.(outcome);
86
+ let cleanupFailed = false;
87
+ let cleanupFailure;
88
+ try {
89
+ await scope.close(outcome);
90
+ } catch (cause) {
91
+ cleanupFailed = true;
92
+ cleanupFailure = cause;
93
+ }
94
+ if (cleanupFailed) {
95
+ const error = cleanupFailure instanceof ScopeCloseError ? cleanupFailure : new ScopeCloseError([cleanupFailure]);
96
+ await notifyCleanupFailure(options.onCleanupFailure, {
97
+ outcome,
98
+ error
99
+ });
100
+ cleanupFailure = error;
101
+ }
102
+ if (programFailed) throw programFailure;
103
+ if (outcomeStatus === "failure") return value;
104
+ if (cleanupFailed) throw cleanupFailure;
105
+ return value;
106
+ };
107
+ //#endregion
108
+ //#region src/scope/scope.ts
109
+ const SCOPE_SUCCESS$1 = Object.freeze({ status: "success" });
110
+ var ScopeImpl = class ScopeImpl {
111
+ parent;
112
+ children = /* @__PURE__ */ new Set();
113
+ finalizers = [];
114
+ preFinalizers = [];
115
+ closePromise;
116
+ closeOutcome;
117
+ constructor(parent) {
118
+ this.parent = parent;
119
+ registerScopeImplementation(this, { addPreFinalizer: (finalizer) => this.addPreFinalizer(finalizer) });
120
+ }
121
+ fork() {
122
+ this.assertOpen();
123
+ const child = new ScopeImpl(this);
124
+ this.children.add(child);
125
+ return child;
126
+ }
127
+ addFinalizer(finalizer) {
128
+ this.assertOpen();
129
+ this.finalizers.push(finalizer);
130
+ }
131
+ async acquire(acquire, release) {
132
+ this.assertOpen();
133
+ const resource = await acquire();
134
+ try {
135
+ this.addFinalizer((outcome) => release(resource, outcome));
136
+ return resource;
137
+ } catch (scopeFailure) {
138
+ try {
139
+ await release(resource, this.closeOutcome ?? SCOPE_SUCCESS$1);
140
+ } catch (releaseFailure) {
141
+ throw new AggregateError([scopeFailure, releaseFailure], "Scope closed while acquiring a resource and immediate cleanup also failed");
142
+ }
143
+ throw scopeFailure;
144
+ }
145
+ }
146
+ async add(resource) {
147
+ const finalizer = getDisposeFinalizer(resource);
148
+ if (!finalizer) throw new ResourceNotDisposableError();
149
+ try {
150
+ this.addFinalizer(finalizer);
151
+ return resource;
152
+ } catch (scopeFailure) {
153
+ try {
154
+ await finalizer(this.closeOutcome ?? SCOPE_SUCCESS$1);
155
+ } catch (releaseFailure) {
156
+ throw new AggregateError([scopeFailure, releaseFailure], "Scope closed while adding a disposable resource and cleanup also failed");
157
+ }
158
+ throw scopeFailure;
159
+ }
160
+ }
161
+ close(outcome = SCOPE_SUCCESS$1) {
162
+ if (this.closePromise) return this.closePromise;
163
+ this.closeOutcome = outcome;
164
+ this.closePromise = Promise.resolve().then(() => this.closeWithRuntime(outcome));
165
+ return this.closePromise;
166
+ }
167
+ async closeWithRuntime(outcome) {
168
+ let started = false;
169
+ try {
170
+ await ScopeRuntime.run(this, () => {
171
+ started = true;
172
+ return this.closeInternal(outcome);
173
+ });
174
+ } catch (storageFailure) {
175
+ if (started) throw storageFailure;
176
+ try {
177
+ await this.closeInternal(outcome);
178
+ } catch (cleanupFailure) {
179
+ const cleanupCauses = cleanupFailure instanceof ScopeCloseError ? cleanupFailure.causes : [cleanupFailure];
180
+ throw new ScopeCloseError([storageFailure, ...cleanupCauses]);
181
+ }
182
+ throw storageFailure;
183
+ }
184
+ }
185
+ async closeInternal(outcome) {
186
+ const failures = [];
187
+ const preFinalizers = this.preFinalizers.splice(0);
188
+ for (let index = preFinalizers.length - 1; index >= 0; index--) {
189
+ const finalizer = preFinalizers[index];
190
+ if (!finalizer) continue;
191
+ try {
192
+ await finalizer(outcome);
193
+ } catch (cause) {
194
+ failures.push(cause);
195
+ }
196
+ }
197
+ const children = [...this.children];
198
+ this.children.clear();
199
+ for (let index = children.length - 1; index >= 0; index--) {
200
+ const child = children[index];
201
+ if (!child) continue;
202
+ try {
203
+ await child.close(outcome);
204
+ } catch (cause) {
205
+ if (cause instanceof ScopeCloseError) failures.push(...cause.causes);
206
+ else failures.push(cause);
207
+ }
208
+ }
209
+ for (let index = this.finalizers.length - 1; index >= 0; index--) {
210
+ const finalizer = this.finalizers[index];
211
+ if (!finalizer) continue;
212
+ try {
213
+ await finalizer(outcome);
214
+ } catch (cause) {
215
+ failures.push(cause);
216
+ }
217
+ }
218
+ this.finalizers.length = 0;
219
+ this.detach();
220
+ if (failures.length > 0) throw new ScopeCloseError(failures);
221
+ }
222
+ detach() {
223
+ const parent = this.parent;
224
+ if (!parent) return;
225
+ parent.children.delete(this);
226
+ this.parent = void 0;
227
+ }
228
+ assertOpen() {
229
+ if (this.closePromise) throw new ScopeClosedError();
230
+ }
231
+ addPreFinalizer(finalizer) {
232
+ this.assertOpen();
233
+ this.preFinalizers.push(finalizer);
234
+ }
235
+ };
236
+ const Scope = {
237
+ /** Create an owned, initially open Scope. */
238
+ make() {
239
+ return new ScopeImpl();
240
+ },
241
+ /** Return the non-owning Scope available in the current execution context. */
242
+ current() {
243
+ return ScopeRuntime.current();
244
+ },
245
+ /** Run a callback with an existing Scope supplied as the current context. */
246
+ provide(scope, program) {
247
+ return ScopeRuntime.run(scope, program);
248
+ },
249
+ /** Resolve the current Scope through `yield* Scope` inside an Effect. */
250
+ *[Symbol.iterator]() {
251
+ return ScopeRuntime.current();
252
+ },
253
+ /**
254
+ * Run a program in a newly owned Scope.
255
+ *
256
+ * Scope is independent from `better-result`, so returned values—including
257
+ * `Result.err`—close this Scope with a successful outcome. Result-aware
258
+ * outcome classification belongs to `Runtime.run`.
259
+ *
260
+ * @example
261
+ * ```ts
262
+ * await Scope.run(async (scope) => {
263
+ * const connection = await scope.acquire(connect, (connection) => connection.close())
264
+ * return connection.query()
265
+ * })
266
+ * ```
267
+ */
268
+ run(program) {
269
+ const scope = new ScopeImpl();
270
+ return runScoped(scope, () => program(scope), { classify: () => SCOPE_SUCCESS$1 });
271
+ }
272
+ };
273
+ //#endregion
274
+ //#region src/layer/map-layer-backend.ts
275
+ /** Native map-backed Layer backend used by Runtime when no adapter is supplied. */
276
+ var MapLayerBackend = class {
277
+ providers = /* @__PURE__ */ new Map();
278
+ instances = /* @__PURE__ */ new Map();
279
+ pending = /* @__PURE__ */ new Map();
280
+ /** Register a provider, rejecting duplicate or colliding Service tags. */
281
+ register(registration) {
282
+ const normalized = normalizeLayerRegistration(registration);
283
+ const tag = captureLayerRegistrationTag(normalized);
284
+ const existing = this.providers.get(tag);
285
+ if (existing) {
286
+ if (existing.service !== normalized.service) throw new ServiceTagCollisionError(existing.service, normalized.service);
287
+ throw new DuplicateServiceError(normalized.service);
288
+ }
289
+ this.providers.set(tag, normalized);
290
+ }
291
+ /** Resolve and cache a provider instance by Service tag. */
292
+ async resolve(token) {
293
+ const tag = captureServiceTag(token);
294
+ const provider = this.providers.get(tag);
295
+ if (!provider) throw new ServiceNotFoundError(token);
296
+ const validate = (instance) => {
297
+ assertServiceCompatibility(token, provider.service, instance);
298
+ return instance;
299
+ };
300
+ const cached = this.instances.get(tag);
301
+ if (cached !== void 0) return validate(cached);
302
+ const pending = this.pending.get(tag);
303
+ if (pending) return validate(await pending);
304
+ const acquisition = Promise.resolve().then(() => provider.acquire()).then((instance) => {
305
+ validate(instance);
306
+ this.instances.set(tag, instance);
307
+ return instance;
308
+ }).finally(() => {
309
+ this.pending.delete(tag);
310
+ });
311
+ this.pending.set(tag, acquisition);
312
+ return validate(await acquisition);
313
+ }
314
+ /** Clear pending acquisitions, cached instances, and provider registrations. */
315
+ async disposeAll(options) {
316
+ const acquisitions = [...this.pending.values()];
317
+ if (acquisitions.length > 0) {
318
+ const observePending = options?.onPendingAcquisitions;
319
+ if (observePending) await observePending(acquisitions);
320
+ await Promise.allSettled(acquisitions);
321
+ }
322
+ this.instances.clear();
323
+ this.pending.clear();
324
+ this.providers.clear();
325
+ }
326
+ };
327
+ //#endregion
328
+ //#region src/effect/program-metadata.ts
329
+ const programNames = /* @__PURE__ */ new WeakMap();
330
+ /** Return the private diagnostic name attached to a callable Program. */
331
+ const getProgramName = (program) => programNames.get(program);
332
+ /** Attach a name without changing the callable Program facade. */
333
+ const setProgramName = (program, name) => {
334
+ programNames.set(program, name);
335
+ return program;
336
+ };
337
+ /** Copy a source Program's name to a lazily-created derived Program. */
338
+ const inheritProgramName = (source, derived) => {
339
+ const name = getProgramName(source);
340
+ return name === void 0 ? derived : setProgramName(derived, name);
341
+ };
342
+ //#endregion
343
+ //#region src/runtime/observer.ts
344
+ /** Compose best-effort Runtime observers into one observer. */
345
+ const RuntimeObserver = { compose: (...observers) => ({
346
+ onServiceResolve: (event) => {
347
+ notifyRuntimeObservers(observers, (observer) => observer.onServiceResolve, event);
348
+ },
349
+ onServiceAcquire: (event) => {
350
+ notifyRuntimeObservers(observers, (observer) => observer.onServiceAcquire, event);
351
+ },
352
+ onExecutionStart: (event) => {
353
+ notifyRuntimeObservers(observers, (observer) => observer.onExecutionStart, event);
354
+ },
355
+ onExecutionEnd: (event) => {
356
+ notifyRuntimeObservers(observers, (observer) => observer.onExecutionEnd, event);
357
+ },
358
+ onTaskStart: (event) => {
359
+ notifyRuntimeObservers(observers, (observer) => observer.onTaskStart, event);
360
+ },
361
+ onTaskEnd: (event) => {
362
+ notifyRuntimeObservers(observers, (observer) => observer.onTaskEnd, event);
363
+ },
364
+ onResourceRelease: (event) => {
365
+ notifyRuntimeObservers(observers, (observer) => observer.onResourceRelease, event);
366
+ },
367
+ onLifecycleStart: (event) => {
368
+ notifyRuntimeObservers(observers, (observer) => observer.onLifecycleStart, event);
369
+ },
370
+ onLifecycleEnd: (event) => {
371
+ notifyRuntimeObservers(observers, (observer) => observer.onLifecycleEnd, event);
372
+ },
373
+ onLifecycleRelease: (event) => {
374
+ notifyRuntimeObservers(observers, (observer) => observer.onLifecycleRelease, event);
375
+ },
376
+ onShutdown: (event) => {
377
+ notifyRuntimeObservers(observers, (observer) => observer.onShutdown, event);
378
+ }
379
+ }) };
380
+ const notifyRuntimeObservers = (observers, select, event) => {
381
+ for (const observer of observers) {
382
+ const callback = select(observer);
383
+ if (!callback) continue;
384
+ try {
385
+ Promise.resolve(callback(event)).catch(() => {});
386
+ } catch {}
387
+ }
388
+ };
389
+ //#endregion
390
+ //#region src/runtime/outcome.ts
391
+ /** Classify only a nominal better-result Err as a failed Runtime outcome. */
392
+ const classifyRuntimeOutcome = (value) => {
393
+ if (value instanceof Err) return {
394
+ status: "failure",
395
+ cause: value.error
396
+ };
397
+ return { status: "success" };
398
+ };
399
+ //#endregion
400
+ //#region src/runtime/task.ts
401
+ const taskSupervisors = /* @__PURE__ */ new WeakMap();
402
+ /** Associate one Runtime task supervisor with a Runtime-owned Scope. */
403
+ const bindRuntimeTaskSupervisor = (scope, supervisor) => {
404
+ taskSupervisors.set(scope, supervisor);
405
+ };
406
+ /** Return the supervisor associated with the current Runtime-owned Scope. */
407
+ const getRuntimeTaskSupervisor = (scope) => taskSupervisors.get(scope);
408
+ const defaultInterruptionReason = () => {
409
+ const reason = /* @__PURE__ */ new Error("Scoped task interrupted");
410
+ reason.name = "ScopedTaskInterruptedError";
411
+ return reason;
412
+ };
413
+ const signalReason = (signal) => signal.reason === void 0 ? defaultInterruptionReason() : signal.reason;
414
+ const taskStateFromExit = (exit) => exit.status;
415
+ const copyMetadata = (metadata) => {
416
+ const copy = {
417
+ taskId: metadata.taskId,
418
+ startedAt: metadata.startedAt
419
+ };
420
+ if (metadata.parentExecutionId !== void 0) copy.parentExecutionId = metadata.parentExecutionId;
421
+ if (metadata.name !== void 0) copy.name = metadata.name;
422
+ return Object.freeze(copy);
423
+ };
424
+ var ScopedTaskHandle = class {
425
+ controller;
426
+ handleState;
427
+ constructor(controller) {
428
+ this.controller = controller;
429
+ let resolveCompletion;
430
+ const completion = new Promise((resolve) => {
431
+ resolveCompletion = resolve;
432
+ });
433
+ this.handleState = {
434
+ completion,
435
+ resolveCompletion,
436
+ currentState: "running",
437
+ terminalResult: void 0,
438
+ interruptionReasonValue: void 0
439
+ };
440
+ Object.freeze(this);
441
+ }
442
+ get state() {
443
+ return this.handleState.currentState;
444
+ }
445
+ await() {
446
+ return this.handleState.completion.then((exit) => {
447
+ if (exit.status === "succeeded" || exit.status === "failed") return this.handleState.terminalResult;
448
+ if (exit.status === "defected") throw exit.cause;
449
+ throw exit.reason;
450
+ });
451
+ }
452
+ awaitExit() {
453
+ return this.handleState.completion;
454
+ }
455
+ interrupt(reason) {
456
+ if (this.handleState.currentState !== "running") return this.handleState.completion.then(() => void 0);
457
+ const interruption = reason === void 0 ? this.handleState.interruptionReasonValue ?? defaultInterruptionReason() : reason;
458
+ this.handleState.interruptionReasonValue = interruption;
459
+ if (!this.controller.signal.aborted) this.controller.abort(interruption);
460
+ return this.handleState.completion.then(() => void 0);
461
+ }
462
+ markInterrupted(reason) {
463
+ if (this.handleState.currentState === "running" && this.handleState.interruptionReasonValue === void 0) this.handleState.interruptionReasonValue = reason;
464
+ }
465
+ isInterrupted() {
466
+ return this.handleState.interruptionReasonValue !== void 0 || this.controller.signal.aborted;
467
+ }
468
+ interruptionReason(signal) {
469
+ return this.handleState.interruptionReasonValue ?? signalReason(signal);
470
+ }
471
+ settle(exit, result) {
472
+ if (this.handleState.currentState !== "running") return;
473
+ const terminalExit = Object.freeze(exit);
474
+ this.handleState.currentState = taskStateFromExit(terminalExit);
475
+ this.handleState.terminalResult = result;
476
+ this.handleState.resolveCompletion(terminalExit);
477
+ }
478
+ };
479
+ const withCleanupFailure = (value, cleanupFailure) => {
480
+ if (cleanupFailure === void 0) return Object.freeze({ ...value });
481
+ return Object.freeze({
482
+ ...value,
483
+ cleanupFailure
484
+ });
485
+ };
486
+ /** Runtime-owned supervisor for Scope child tasks. */
487
+ var RuntimeTaskSupervisor = class {
488
+ createTaskId;
489
+ now;
490
+ observers;
491
+ onCleanupFailure;
492
+ tasks = /* @__PURE__ */ new Map();
493
+ constructor(createTaskId, now, observers, onCleanupFailure) {
494
+ this.createTaskId = createTaskId;
495
+ this.now = now;
496
+ this.observers = observers;
497
+ this.onCleanupFailure = onCleanupFailure;
498
+ }
499
+ bindScope(scope) {
500
+ bindRuntimeTaskSupervisor(scope, this);
501
+ }
502
+ inspect() {
503
+ return Object.freeze([...this.tasks.values()].map(({ metadata }) => Object.freeze({
504
+ ...copyMetadata(metadata),
505
+ state: "running"
506
+ })));
507
+ }
508
+ forkScoped(program, context) {
509
+ if (!context.resolver || !context.scope) throw new RuntimeContextNotConfiguredError();
510
+ const parentScope = context.scope;
511
+ const childScope = parentScope.fork();
512
+ const controller = new AbortController();
513
+ const signalLink = linkAbortSignals(context.signal, controller.signal);
514
+ const handle = new ScopedTaskHandle(controller);
515
+ const metadata = this.makeMetadata(program, context);
516
+ const record = {
517
+ metadata,
518
+ childScope,
519
+ signalLink,
520
+ handle,
521
+ program,
522
+ context,
523
+ storage: activeRuntimeContextStorage()
524
+ };
525
+ const onAbort = () => handle.markInterrupted(signalReason(signalLink.signal));
526
+ try {
527
+ addScopePreFinalizer(parentScope, (outcome) => handle.interrupt(outcome.status === "failure" ? outcome.cause : void 0));
528
+ this.bindScope(childScope);
529
+ this.tasks.set(metadata.taskId, record);
530
+ signalLink.signal.addEventListener("abort", onAbort, { once: true });
531
+ if (signalLink.signal.aborted) onAbort();
532
+ this.notifyStart(metadata);
533
+ } catch (cause) {
534
+ signalLink.signal.removeEventListener("abort", onAbort);
535
+ signalLink.dispose();
536
+ childScope.close({
537
+ status: "failure",
538
+ cause
539
+ }).catch(() => {});
540
+ throw cause;
541
+ }
542
+ this.runTask(record, onAbort);
543
+ return handle;
544
+ }
545
+ makeMetadata(program, context) {
546
+ const metadata = {
547
+ taskId: this.createTaskId(),
548
+ startedAt: this.now()
549
+ };
550
+ const name = getProgramName(program);
551
+ if (name !== void 0) metadata.name = name;
552
+ if (context.executionId !== void 0) metadata.parentExecutionId = context.executionId;
553
+ return Object.freeze(metadata);
554
+ }
555
+ notifyStart(metadata) {
556
+ const event = {
557
+ ...copyMetadata(metadata),
558
+ state: "running"
559
+ };
560
+ notifyRuntimeObservers(this.observers, (observer) => observer.onTaskStart, Object.freeze(event));
561
+ }
562
+ notifyEnd(metadata, exit) {
563
+ const event = {
564
+ ...copyMetadata(metadata),
565
+ state: exit.status
566
+ };
567
+ if (exit.cleanupFailure !== void 0) event.cleanupFailure = exit.cleanupFailure;
568
+ const frozenEvent = Object.freeze(event);
569
+ notifyRuntimeObservers(this.observers, (observer) => observer.onTaskEnd, frozenEvent);
570
+ }
571
+ async runTask(record, onAbort) {
572
+ let cleanupFailure;
573
+ const onChildCleanupFailure = async (diagnostic) => {
574
+ cleanupFailure = diagnostic.error;
575
+ if (this.onCleanupFailure !== void 0) await this.onCleanupFailure(diagnostic);
576
+ };
577
+ const taskContext = makeRuntimeContext(record.context.resolver, record.childScope, [], record.signalLink.signal, record.context, record.context.executionId, record.context.executor);
578
+ const classify = (value) => record.handle.isInterrupted() ? {
579
+ status: "failure",
580
+ cause: record.handle.interruptionReason(record.signalLink.signal)
581
+ } : classifyRuntimeOutcome(value);
582
+ let exit;
583
+ let result;
584
+ try {
585
+ if (record.handle.isInterrupted()) {
586
+ await record.childScope.close({
587
+ status: "failure",
588
+ cause: record.handle.interruptionReason(record.signalLink.signal)
589
+ });
590
+ exit = withCleanupFailure({
591
+ status: "interrupted",
592
+ reason: record.handle.interruptionReason(record.signalLink.signal)
593
+ }, cleanupFailure);
594
+ } else {
595
+ const childResult = await runScoped(record.childScope, () => record.program(), {
596
+ classify,
597
+ onCleanupFailure: onChildCleanupFailure,
598
+ contextStorage: record.storage,
599
+ context: taskContext
600
+ });
601
+ result = childResult;
602
+ if (record.handle.isInterrupted()) exit = withCleanupFailure({
603
+ status: "interrupted",
604
+ reason: record.handle.interruptionReason(record.signalLink.signal)
605
+ }, cleanupFailure);
606
+ else if (childResult instanceof Err) exit = withCleanupFailure({
607
+ status: "failed",
608
+ error: childResult.error
609
+ }, cleanupFailure);
610
+ else exit = withCleanupFailure({
611
+ status: "succeeded",
612
+ value: childResult.value
613
+ }, cleanupFailure);
614
+ }
615
+ } catch (cause) {
616
+ exit = record.handle.isInterrupted() ? withCleanupFailure({
617
+ status: "interrupted",
618
+ reason: record.handle.interruptionReason(record.signalLink.signal)
619
+ }, cleanupFailure) : withCleanupFailure({
620
+ status: "defected",
621
+ cause
622
+ }, cleanupFailure);
623
+ }
624
+ record.signalLink.signal.removeEventListener("abort", onAbort);
625
+ record.signalLink.dispose();
626
+ record.handle.settle(exit, result);
627
+ this.tasks.delete(record.metadata.taskId);
628
+ this.notifyEnd(record.metadata, exit);
629
+ }
630
+ };
631
+ //#endregion
632
+ //#region src/runtime/executor.ts
633
+ const castRuntimeExecutor = (value) => {
634
+ return value;
635
+ };
636
+ const currentExecutor = () => {
637
+ let context;
638
+ try {
639
+ context = currentRuntimeContext();
640
+ } catch (cause) {
641
+ if (cause instanceof RuntimeContextNotConfiguredError) throw new RuntimeExecutorNotConfiguredError();
642
+ throw cause;
643
+ }
644
+ if (context.executor === void 0) throw new RuntimeExecutorNotConfiguredError();
645
+ return castRuntimeExecutor(context.executor);
646
+ };
647
+ /** Erase a Runtime executor's concrete environment for contextual storage. */
648
+ const eraseRuntimeExecutor = (executor) => castRuntimeExecutor(executor);
649
+ /** Create one stable executor view from an existing Runtime execution handle. */
650
+ const createRuntimeExecutor = (executor) => Object.freeze({ ...executor });
651
+ /** Build the yieldable contextual executor request used by `Runtime.executor()`. */
652
+ const makeRuntimeExecutorRequest = () => {
653
+ return {
654
+ *[Symbol.iterator]() {
655
+ return currentExecutor();
656
+ },
657
+ async *[Symbol.asyncIterator]() {
658
+ return currentExecutor();
659
+ }
660
+ };
661
+ };
662
+ //#endregion
663
+ //#region src/layer/resolution.ts
664
+ const findCycleStart = (path, tag) => path.findIndex((current) => captureServiceTag(current) === tag);
665
+ const shouldPreserve = (cause) => cause instanceof CircularDependencyError || cause instanceof ServiceAcquisitionError || cause instanceof ServiceNotFoundError || cause instanceof ServiceTagCollisionError;
666
+ /** Wrap a backend with Runtime-local resolution paths and acquisition errors. */
667
+ const createResolutionResolver = (resolver, storage = defaultRuntimeContextStorage, observers = []) => {
668
+ const wrapped = { async resolve(token) {
669
+ const tag = captureServiceTag(token);
670
+ const context = getRuntimeContext(storage);
671
+ const path = context?.resolutionPath ?? [];
672
+ const cycleStart = findCycleStart(path, tag);
673
+ const resolutionPath = [...path, token];
674
+ const notifyResolve = (outcome) => {
675
+ const event = {
676
+ service: token,
677
+ resolutionPath,
678
+ outcome
679
+ };
680
+ if (context?.executionId !== void 0) Object.assign(event, { executionId: context.executionId });
681
+ notifyRuntimeObservers(observers, (observer) => observer.onServiceResolve, event);
682
+ };
683
+ if (cycleStart >= 0) {
684
+ const error = new CircularDependencyError([...path.slice(cycleStart), token]);
685
+ notifyResolve({
686
+ status: "failure",
687
+ cause: error
688
+ });
689
+ throw error;
690
+ }
691
+ const nextContext = makeRuntimeContext(wrapped, context?.scope, resolutionPath, context?.signal, context);
692
+ return await runRuntimeContext(storage, nextContext, async () => {
693
+ try {
694
+ const instance = await resolver.resolve(token);
695
+ notifyResolve({ status: "success" });
696
+ return instance;
697
+ } catch (cause) {
698
+ if (shouldPreserve(cause)) {
699
+ notifyResolve({
700
+ status: "failure",
701
+ cause
702
+ });
703
+ throw cause;
704
+ }
705
+ const error = new ServiceAcquisitionError(token, resolutionPath, cause);
706
+ notifyResolve({
707
+ status: "failure",
708
+ cause: error
709
+ });
710
+ throw error;
711
+ }
712
+ });
713
+ } };
714
+ return wrapped;
715
+ };
716
+ //#endregion
717
+ //#region src/runtime/execution.ts
718
+ const hostMonotonicNow = () => {
719
+ if (typeof globalThis.performance?.now === "function") {
720
+ const value = globalThis.performance.now();
721
+ if (Number.isFinite(value)) return value;
722
+ }
723
+ const wallClock = Date.now();
724
+ return Number.isFinite(wallClock) ? wallClock : 0;
725
+ };
726
+ const makeMonotonicClock = () => {
727
+ let previous = 0;
728
+ return () => {
729
+ previous = Math.max(previous, hostMonotonicNow());
730
+ return previous;
731
+ };
732
+ };
733
+ let fallbackExecutionSequence = 0;
734
+ const makeExecutionIdGenerator = () => () => {
735
+ if (typeof globalThis.crypto?.randomUUID === "function") return globalThis.crypto.randomUUID();
736
+ fallbackExecutionSequence += 1;
737
+ return `execution-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}-${fallbackExecutionSequence.toString(36)}`;
738
+ };
739
+ /** Create isolated execution capabilities for one Runtime handle. */
740
+ const makeRuntimeExecutionDependencies = (overrides = {}) => ({
741
+ createExecutionId: overrides.createExecutionId ?? makeExecutionIdGenerator(),
742
+ now: overrides.now ?? makeMonotonicClock()
743
+ });
744
+ //#endregion
745
+ //#region src/layer/runtime.ts
746
+ const SCOPE_SUCCESS = Object.freeze({ status: "success" });
747
+ var RuntimeHandleDisposedError = class extends Error {
748
+ constructor() {
749
+ super("Cannot run a program using a disposed Layer");
750
+ this.name = "RuntimeHandleDisposedError";
751
+ }
752
+ };
753
+ const normalizeDisposeCauses = (cause) => {
754
+ if (cause instanceof AggregateError) return [...cause.errors];
755
+ return [cause];
756
+ };
757
+ const isScopeOutcome = (input) => input !== void 0 && "status" in input;
758
+ const validateDisposeOptions = (options) => {
759
+ const { gracePeriod, abortAfterGracePeriod } = options;
760
+ if (gracePeriod !== void 0 && (!Number.isFinite(gracePeriod) || gracePeriod < 0)) throw new RangeError("Runtime dispose gracePeriod must be a finite non-negative number");
761
+ if (abortAfterGracePeriod !== void 0 && typeof abortAfterGracePeriod !== "boolean") throw new TypeError("Runtime dispose abortAfterGracePeriod must be a boolean");
762
+ };
763
+ const copyExecutionAttributes = (attributes) => {
764
+ if (attributes === void 0) return;
765
+ if (typeof attributes !== "object" || attributes === null) throw new TypeError("Runtime execution attributes must be an object");
766
+ return Object.freeze({ ...attributes });
767
+ };
768
+ const prepareExecution = (program, options, dependencies, runtimeSignal, shutdownSignal, additionalSignal) => ({
769
+ metadata: makeExecutionMetadata(program, options?.attributes, dependencies),
770
+ signalLink: linkAbortSignals(runtimeSignal, options?.signal, additionalSignal, shutdownSignal)
771
+ });
772
+ const makeExecutionMetadata = (program, attributes, dependencies) => {
773
+ const name = getProgramName(program);
774
+ const copiedAttributes = copyExecutionAttributes(attributes);
775
+ const metadata = {
776
+ executionId: dependencies.createExecutionId(),
777
+ startedAt: dependencies.now()
778
+ };
779
+ if (name !== void 0) metadata.name = name;
780
+ if (copiedAttributes !== void 0) metadata.attributes = copiedAttributes;
781
+ return Object.freeze(metadata);
782
+ };
783
+ const executionDuration = (metadata, dependencies) => {
784
+ try {
785
+ const elapsed = dependencies.now() - metadata.startedAt;
786
+ return Number.isFinite(elapsed) ? Math.max(0, elapsed) : 0;
787
+ } catch {
788
+ return 0;
789
+ }
790
+ };
791
+ const readRuntimeTimestamp = (dependencies) => {
792
+ try {
793
+ const timestamp = dependencies.now();
794
+ return Number.isFinite(timestamp) ? timestamp : void 0;
795
+ } catch {
796
+ return;
797
+ }
798
+ };
799
+ const makeShutdownReason = (outcome) => {
800
+ if (outcome.status === "failure") return {
801
+ kind: "main-settled",
802
+ cause: outcome.cause
803
+ };
804
+ return { kind: "main-settled" };
805
+ };
806
+ const notifyShutdownFailure = async (observer, diagnostic) => {
807
+ if (!observer) return;
808
+ try {
809
+ await observer(diagnostic);
810
+ } catch {}
811
+ };
812
+ const releaseLayerResource = async (service, release, outcome, observers, executionId) => {
813
+ try {
814
+ await release(outcome);
815
+ const event = {
816
+ service,
817
+ outcome
818
+ };
819
+ if (executionId !== void 0) Object.assign(event, { executionId });
820
+ notifyRuntimeObservers(observers, (observer) => observer.onResourceRelease, event);
821
+ } catch (cause) {
822
+ const event = {
823
+ service,
824
+ outcome,
825
+ error: cause
826
+ };
827
+ if (executionId !== void 0) Object.assign(event, { executionId });
828
+ notifyRuntimeObservers(observers, (observer) => observer.onResourceRelease, event);
829
+ throw cause;
830
+ }
831
+ };
832
+ const lifecycleEventMetadata = (entry) => ({
833
+ kind: "lifecycle",
834
+ lifecycleId: entry.id
835
+ });
836
+ const releaseLifecycleResource = async (entry, resource, outcome, observers) => {
837
+ const metadata = lifecycleEventMetadata(entry);
838
+ try {
839
+ await entry.release(resource, outcome);
840
+ const event = {
841
+ ...metadata,
842
+ outcome
843
+ };
844
+ notifyRuntimeObservers(observers, (observer) => observer.onLifecycleRelease, event);
845
+ } catch (cause) {
846
+ const event = {
847
+ ...metadata,
848
+ outcome,
849
+ error: cause
850
+ };
851
+ notifyRuntimeObservers(observers, (observer) => observer.onLifecycleRelease, event);
852
+ throw cause;
853
+ }
854
+ };
855
+ const bindProviderToScope = (provider, scope, contextStorage, resolver, observers, executor, ownerExecutionId, beforeAcquire, onAcquired) => ({
856
+ service: provider.service,
857
+ serviceTag: provider.serviceTag,
858
+ acquire: () => {
859
+ beforeAcquire?.();
860
+ const current = getRuntimeContext(contextStorage);
861
+ const executionId = current?.executionId ?? ownerExecutionId;
862
+ const context = makeRuntimeContext(resolver, scope, current?.resolutionPath ?? [], current?.signal, current, void 0, executor);
863
+ return runRuntimeContext(contextStorage, context, () => ScopeRuntime.run(scope, async () => {
864
+ const resolutionPath = current?.resolutionPath ?? [provider.service];
865
+ try {
866
+ const instance = provider.acquireWithRelease ? (await scope.acquire(provider.acquireWithRelease, (acquired, outcome) => releaseLayerResource(provider.service, acquired.release, outcome, observers, ownerExecutionId))).instance : provider.release ? await scope.acquire(() => provider.acquire(), (resource, outcome) => releaseLayerResource(provider.service, (releaseOutcome) => provider.release(resource, releaseOutcome), outcome, observers, ownerExecutionId)) : await provider.acquire();
867
+ onAcquired?.(instance);
868
+ const event = {
869
+ service: provider.service,
870
+ resolutionPath,
871
+ outcome: SCOPE_SUCCESS
872
+ };
873
+ if (executionId !== void 0) Object.assign(event, { executionId });
874
+ notifyRuntimeObservers(observers, (observer) => observer.onServiceAcquire, event);
875
+ return instance;
876
+ } catch (cause) {
877
+ const event = {
878
+ service: provider.service,
879
+ resolutionPath,
880
+ outcome: {
881
+ status: "failure",
882
+ cause
883
+ }
884
+ };
885
+ if (executionId !== void 0) Object.assign(event, { executionId });
886
+ notifyRuntimeObservers(observers, (observer) => observer.onServiceAcquire, event);
887
+ throw cause;
888
+ }
889
+ }, contextStorage));
890
+ }
891
+ });
892
+ /** Resolve request-local providers first, then fall back to the Runtime root. */
893
+ var ExecutionLayerBackend = class {
894
+ local;
895
+ root;
896
+ localTags = /* @__PURE__ */ new Set();
897
+ constructor(local, root) {
898
+ this.local = local;
899
+ this.root = root;
900
+ }
901
+ register(registration) {
902
+ this.localTags.add(captureLayerRegistrationTag(registration));
903
+ this.local.register(registration);
904
+ }
905
+ async resolve(token) {
906
+ const tag = captureServiceTag(token);
907
+ if (this.localTags.has(tag)) return await this.local.resolve(token);
908
+ return await this.root.resolve(token);
909
+ }
910
+ async disposeAll() {
911
+ await this.local.disposeAll();
912
+ this.localTags.clear();
913
+ }
914
+ };
915
+ var RuntimeHandleImpl = class {
916
+ backend;
917
+ resolver;
918
+ rootScope;
919
+ onCleanupFailure;
920
+ contextStorage;
921
+ signal;
922
+ observers;
923
+ services;
924
+ executionDependencies;
925
+ executor;
926
+ lifecycleEntries;
927
+ disposePromise;
928
+ warmupPromise;
929
+ executions = /* @__PURE__ */ new Set();
930
+ rootQuiesces = [];
931
+ serviceTags;
932
+ shutdownController = new AbortController();
933
+ taskSupervisor;
934
+ state = "active";
935
+ warmupState = "idle";
936
+ constructor(backend, resolver, rootScope, onCleanupFailure, contextStorage, signal, observers, services, serviceTags, executionDependencies, executor, lifecycleEntries) {
937
+ this.backend = backend;
938
+ this.resolver = resolver;
939
+ this.rootScope = rootScope;
940
+ this.onCleanupFailure = onCleanupFailure;
941
+ this.contextStorage = contextStorage;
942
+ this.signal = signal;
943
+ this.observers = observers;
944
+ this.services = services;
945
+ this.executionDependencies = executionDependencies;
946
+ this.executor = executor;
947
+ this.lifecycleEntries = lifecycleEntries;
948
+ this.serviceTags = Object.freeze([...serviceTags]);
949
+ this.taskSupervisor = new RuntimeTaskSupervisor(() => this.executionDependencies.createExecutionId(), () => this.executionDependencies.now(), this.observers, this.onCleanupFailure);
950
+ this.taskSupervisor.bindScope(this.rootScope);
951
+ }
952
+ registerRootQuiesce(provider, instance) {
953
+ if (provider.quiesce === void 0) return;
954
+ this.rootQuiesces.push({
955
+ started: false,
956
+ quiesce: (reason) => provider.quiesce(instance, reason)
957
+ });
958
+ }
959
+ registerLifecycleQuiesce(entry, instance) {
960
+ if (entry.quiesce === void 0) return;
961
+ this.rootQuiesces.push({
962
+ started: false,
963
+ quiesce: (reason) => entry.quiesce(instance, reason)
964
+ });
965
+ }
966
+ assertRootAcquisitionAllowed() {
967
+ this.assertActive();
968
+ }
969
+ emitShutdown(event) {
970
+ notifyRuntimeObservers(this.observers, (observer) => observer.onShutdown, event);
971
+ }
972
+ async quiesceResources(reason) {
973
+ const failures = [];
974
+ for (;;) {
975
+ const registration = [...this.rootQuiesces].reverse().find((candidate) => !candidate.started);
976
+ if (registration === void 0) return failures;
977
+ registration.started = true;
978
+ try {
979
+ await registration.quiesce(reason);
980
+ } catch (cause) {
981
+ failures.push(cause);
982
+ }
983
+ }
984
+ }
985
+ inspect() {
986
+ const tasks = this.taskSupervisor.inspect();
987
+ const executions = Object.freeze([...this.executions].map(({ metadata }) => {
988
+ const inspection = {
989
+ executionId: metadata.executionId,
990
+ startedAt: metadata.startedAt
991
+ };
992
+ if (metadata.name !== void 0) inspection.name = metadata.name;
993
+ return Object.freeze(inspection);
994
+ }));
995
+ return Object.freeze({
996
+ state: this.state,
997
+ warmup: this.warmupState,
998
+ activeExecutions: executions.length,
999
+ executions,
1000
+ activeTasks: tasks.length,
1001
+ tasks,
1002
+ services: Object.freeze([...this.serviceTags]),
1003
+ shutdownSignalAborted: this.shutdownController.signal.aborted
1004
+ });
1005
+ }
1006
+ run(program, options) {
1007
+ this.assertActive();
1008
+ let prepared;
1009
+ try {
1010
+ prepared = prepareExecution(program, options, this.executionDependencies, this.signal, this.shutdownController.signal);
1011
+ } catch (cause) {
1012
+ return Promise.reject(cause);
1013
+ }
1014
+ try {
1015
+ this.assertActive();
1016
+ } catch (cause) {
1017
+ prepared.signalLink.dispose();
1018
+ throw cause;
1019
+ }
1020
+ let executionScope;
1021
+ try {
1022
+ executionScope = this.rootScope.fork();
1023
+ this.taskSupervisor.bindScope(executionScope);
1024
+ } catch (cause) {
1025
+ prepared.signalLink.dispose();
1026
+ throw cause;
1027
+ }
1028
+ return this.startExecution(prepared.signalLink, prepared.metadata, () => this.runExecution(executionScope, program, this.resolver, prepared.signalLink.signal, prepared.metadata));
1029
+ }
1030
+ runWith(layer, program, options) {
1031
+ this.assertActive();
1032
+ let prepared;
1033
+ try {
1034
+ prepared = prepareExecution(program, options, this.executionDependencies, this.signal, this.shutdownController.signal);
1035
+ } catch (cause) {
1036
+ return Promise.reject(cause);
1037
+ }
1038
+ try {
1039
+ this.assertActive();
1040
+ } catch (cause) {
1041
+ prepared.signalLink.dispose();
1042
+ throw cause;
1043
+ }
1044
+ const localBackend = new MapLayerBackend();
1045
+ const backend = new ExecutionLayerBackend(localBackend, this.backend);
1046
+ const resolver = createResolutionResolver(backend, this.contextStorage, this.observers);
1047
+ let executionScope;
1048
+ try {
1049
+ executionScope = this.rootScope.fork();
1050
+ this.taskSupervisor.bindScope(executionScope);
1051
+ } catch (cause) {
1052
+ prepared.signalLink.dispose();
1053
+ throw cause;
1054
+ }
1055
+ return this.startExecution(prepared.signalLink, prepared.metadata, async () => {
1056
+ try {
1057
+ return await this.runExecution(executionScope, async () => {
1058
+ for (const provider of layer.providers) backend.register(bindProviderToScope(provider, executionScope, this.contextStorage, resolver, this.observers, this.executor, prepared.metadata.executionId));
1059
+ return await program();
1060
+ }, resolver, prepared.signalLink.signal, prepared.metadata);
1061
+ } finally {
1062
+ await localBackend.disposeAll();
1063
+ }
1064
+ });
1065
+ }
1066
+ runWithManaged(layer, program, options) {
1067
+ this.assertActive();
1068
+ const managedController = new AbortController();
1069
+ let prepared;
1070
+ prepared = prepareExecution(program, options, this.executionDependencies, this.signal, this.shutdownController.signal, managedController.signal);
1071
+ try {
1072
+ this.assertActive();
1073
+ } catch (cause) {
1074
+ prepared.signalLink.dispose();
1075
+ throw cause;
1076
+ }
1077
+ const localBackend = new MapLayerBackend();
1078
+ const backend = new ExecutionLayerBackend(localBackend, this.backend);
1079
+ const resolver = createResolutionResolver(backend, this.contextStorage, this.observers);
1080
+ let executionScope;
1081
+ try {
1082
+ executionScope = this.rootScope.fork();
1083
+ } catch (cause) {
1084
+ prepared.signalLink.dispose();
1085
+ throw cause;
1086
+ }
1087
+ this.taskSupervisor.bindScope(executionScope);
1088
+ const executionContext = makeRuntimeContext(resolver, executionScope, [], prepared.signalLink.signal, void 0, prepared.metadata.executionId, this.executor);
1089
+ let plan;
1090
+ let pendingCancel;
1091
+ let cancelPromise;
1092
+ let executionPromise;
1093
+ let settled = false;
1094
+ let resolveReadiness;
1095
+ let rejectReadiness;
1096
+ const readiness = new Promise((resolve, reject) => {
1097
+ resolveReadiness = resolve;
1098
+ rejectReadiness = reject;
1099
+ });
1100
+ readiness.catch(() => void 0);
1101
+ const runInExecution = (operation) => {
1102
+ if (settled) return Promise.reject(new RuntimeHandleDisposedError());
1103
+ return Promise.resolve(runRuntimeContext(this.contextStorage, executionContext, () => ScopeRuntime.run(executionScope, operation, this.contextStorage)));
1104
+ };
1105
+ const cancel = (reason) => {
1106
+ if (cancelPromise !== void 0) return cancelPromise;
1107
+ cancelPromise = (async () => {
1108
+ pendingCancel = reason === void 0 ? /* @__PURE__ */ new Error("Managed execution cancelled") : reason;
1109
+ if (!managedController.signal.aborted) managedController.abort(pendingCancel);
1110
+ const currentPlan = plan;
1111
+ if (currentPlan?.cancel !== void 0) try {
1112
+ await currentPlan.cancel(pendingCancel);
1113
+ } catch {}
1114
+ if (executionPromise !== void 0) await executionPromise.catch(() => void 0);
1115
+ })();
1116
+ return cancelPromise;
1117
+ };
1118
+ const run = async () => {
1119
+ try {
1120
+ for (const provider of layer.providers) backend.register(bindProviderToScope(provider, executionScope, this.contextStorage, resolver, this.observers, this.executor, prepared.metadata.executionId));
1121
+ const next = await program();
1122
+ plan = next;
1123
+ if (pendingCancel !== void 0) {
1124
+ rejectReadiness(pendingCancel);
1125
+ await next.cancel?.(pendingCancel);
1126
+ throw pendingCancel;
1127
+ }
1128
+ try {
1129
+ resolveReadiness(await next.readiness);
1130
+ } catch (cause) {
1131
+ rejectReadiness(cause);
1132
+ await next.cancel?.(cause);
1133
+ throw cause;
1134
+ }
1135
+ return await next.completion;
1136
+ } catch (cause) {
1137
+ rejectReadiness(cause);
1138
+ throw cause;
1139
+ }
1140
+ };
1141
+ executionPromise = this.startExecution(prepared.signalLink, prepared.metadata, async () => {
1142
+ try {
1143
+ return await this.runExecution(executionScope, run, resolver, prepared.signalLink.signal, prepared.metadata, executionContext);
1144
+ } finally {
1145
+ await localBackend.disposeAll();
1146
+ }
1147
+ });
1148
+ executionPromise.then(() => {
1149
+ settled = true;
1150
+ }, () => {
1151
+ settled = true;
1152
+ });
1153
+ executionPromise.catch(() => void 0);
1154
+ const signalListener = () => {
1155
+ cancel(prepared.signalLink.signal.reason);
1156
+ };
1157
+ if (!prepared.signalLink.signal.aborted) prepared.signalLink.signal.addEventListener("abort", signalListener, { once: true });
1158
+ executionPromise.then(() => prepared.signalLink.signal.removeEventListener("abort", signalListener), () => prepared.signalLink.signal.removeEventListener("abort", signalListener));
1159
+ const completion = executionPromise.then(() => void 0);
1160
+ completion.catch(() => void 0);
1161
+ return Object.freeze({
1162
+ readiness,
1163
+ completion,
1164
+ signal: prepared.signalLink.signal,
1165
+ run: runInExecution,
1166
+ cancel
1167
+ });
1168
+ }
1169
+ warmup() {
1170
+ this.assertActive();
1171
+ if (this.warmupPromise) return this.warmupPromise;
1172
+ this.warmupState = "running";
1173
+ let warmup;
1174
+ try {
1175
+ warmup = runRuntimeContext(this.contextStorage, makeRuntimeContext(this.resolver, this.rootScope, [], this.signal, void 0, void 0, this.executor), async () => {
1176
+ for (const service of this.services) await this.resolver.resolve(service);
1177
+ });
1178
+ } catch (cause) {
1179
+ this.warmupState = "failed";
1180
+ return Promise.reject(cause);
1181
+ }
1182
+ this.warmupPromise = warmup;
1183
+ warmup.then(() => {
1184
+ if (this.warmupPromise === warmup) {
1185
+ this.warmupState = "completed";
1186
+ this.warmupPromise = void 0;
1187
+ }
1188
+ }, () => {
1189
+ if (this.warmupPromise === warmup) {
1190
+ this.warmupState = "failed";
1191
+ this.warmupPromise = void 0;
1192
+ }
1193
+ });
1194
+ return warmup;
1195
+ }
1196
+ activateLifecycle() {
1197
+ this.assertActive();
1198
+ if (this.lifecycleEntries.length === 0) return Promise.resolve();
1199
+ return runRuntimeContext(this.contextStorage, makeRuntimeContext(this.resolver, this.rootScope, [], this.signal, void 0, void 0, this.executor), () => ScopeRuntime.run(this.rootScope, async () => {
1200
+ for (const entry of this.lifecycleEntries) {
1201
+ const metadata = lifecycleEventMetadata(entry);
1202
+ const startEvent = Object.freeze({ ...metadata });
1203
+ notifyRuntimeObservers(this.observers, (observer) => observer.onLifecycleStart, startEvent);
1204
+ try {
1205
+ const resource = await this.rootScope.acquire(() => entry.acquire(), (resource, outcome) => releaseLifecycleResource(entry, resource, outcome, this.observers));
1206
+ this.registerLifecycleQuiesce(entry, resource);
1207
+ const endEvent = Object.freeze({
1208
+ ...metadata,
1209
+ outcome: SCOPE_SUCCESS
1210
+ });
1211
+ notifyRuntimeObservers(this.observers, (observer) => observer.onLifecycleEnd, endEvent);
1212
+ } catch (cause) {
1213
+ const endEvent = Object.freeze({
1214
+ ...metadata,
1215
+ outcome: {
1216
+ status: "failure",
1217
+ cause
1218
+ },
1219
+ error: cause
1220
+ });
1221
+ notifyRuntimeObservers(this.observers, (observer) => observer.onLifecycleEnd, endEvent);
1222
+ throw cause;
1223
+ }
1224
+ }
1225
+ }));
1226
+ }
1227
+ startExecution(signalLink, metadata, run) {
1228
+ let resolveExecution;
1229
+ let rejectExecution;
1230
+ const execution = new Promise((resolve, reject) => {
1231
+ resolveExecution = resolve;
1232
+ rejectExecution = reject;
1233
+ });
1234
+ const activeExecution = {
1235
+ promise: execution,
1236
+ metadata
1237
+ };
1238
+ this.executions.add(activeExecution);
1239
+ execution.then(() => {
1240
+ this.executions.delete(activeExecution);
1241
+ signalLink.dispose();
1242
+ }, () => {
1243
+ this.executions.delete(activeExecution);
1244
+ signalLink.dispose();
1245
+ });
1246
+ try {
1247
+ run(metadata).then((value) => {
1248
+ resolveExecution(value);
1249
+ }, (cause) => {
1250
+ rejectExecution(cause);
1251
+ });
1252
+ } catch (cause) {
1253
+ rejectExecution(cause);
1254
+ }
1255
+ return execution;
1256
+ }
1257
+ runExecution(executionScope, program, resolver = this.resolver, signal = this.shutdownController.signal, metadata, executionContext) {
1258
+ let outcome;
1259
+ let cleanupFailure;
1260
+ const onOutcome = (determinedOutcome) => {
1261
+ outcome = determinedOutcome;
1262
+ };
1263
+ const onExecutionCleanupFailure = async (diagnostic) => {
1264
+ cleanupFailure = diagnostic.error;
1265
+ if (this.onCleanupFailure !== void 0) await this.onCleanupFailure(diagnostic);
1266
+ };
1267
+ const runOptions = {
1268
+ classify: classifyRuntimeOutcome,
1269
+ onOutcome,
1270
+ onCleanupFailure: onExecutionCleanupFailure
1271
+ };
1272
+ const startEvent = Object.freeze({
1273
+ ...metadata,
1274
+ scope: executionScope
1275
+ });
1276
+ notifyRuntimeObservers(this.observers, (observer) => observer.onExecutionStart, startEvent);
1277
+ let ended = false;
1278
+ const notifyEnd = (finalOutcome) => {
1279
+ if (ended) return;
1280
+ ended = true;
1281
+ const endEvent = {
1282
+ ...metadata,
1283
+ scope: executionScope,
1284
+ outcome: finalOutcome,
1285
+ durationMs: executionDuration(metadata, this.executionDependencies)
1286
+ };
1287
+ if (cleanupFailure !== void 0) Object.assign(endEvent, { cleanupFailure });
1288
+ notifyRuntimeObservers(this.observers, (observer) => observer.onExecutionEnd, Object.freeze(endEvent));
1289
+ };
1290
+ let execution;
1291
+ try {
1292
+ execution = runScoped(executionScope, program, {
1293
+ ...runOptions,
1294
+ contextStorage: this.contextStorage,
1295
+ context: executionContext ?? makeRuntimeContext(resolver, executionScope, [], signal, void 0, metadata.executionId, this.executor)
1296
+ });
1297
+ } catch (cause) {
1298
+ notifyEnd({
1299
+ status: "failure",
1300
+ cause
1301
+ });
1302
+ return Promise.reject(cause);
1303
+ }
1304
+ return execution.then((value) => {
1305
+ notifyEnd(outcome ?? { status: "success" });
1306
+ return value;
1307
+ }, (cause) => {
1308
+ notifyEnd(outcome ?? {
1309
+ status: "failure",
1310
+ cause
1311
+ });
1312
+ throw cause;
1313
+ });
1314
+ }
1315
+ dispose(input) {
1316
+ if (this.disposePromise) return this.disposePromise;
1317
+ const outcome = isScopeOutcome(input) || input === void 0 ? input ?? SCOPE_SUCCESS : SCOPE_SUCCESS;
1318
+ const options = isScopeOutcome(input) || input === void 0 ? {} : input;
1319
+ validateDisposeOptions(options);
1320
+ const reason = Object.freeze(options.reason ?? (isScopeOutcome(input) ? makeShutdownReason(input) : { kind: "dispose" }));
1321
+ this.state = "quiescing";
1322
+ let resolveDispose;
1323
+ let rejectDispose;
1324
+ const disposePromise = new Promise((resolve, reject) => {
1325
+ resolveDispose = resolve;
1326
+ rejectDispose = reject;
1327
+ });
1328
+ this.disposePromise = disposePromise;
1329
+ this.emitShutdown(Object.freeze({
1330
+ phase: "shutdown-requested",
1331
+ reason,
1332
+ activeExecutions: this.executions.size
1333
+ }));
1334
+ this.performDispose(outcome, options, reason).then(resolveDispose, rejectDispose);
1335
+ return disposePromise;
1336
+ }
1337
+ async performDispose(outcome, options, reason) {
1338
+ const failures = [];
1339
+ if (this.warmupPromise !== void 0) await Promise.allSettled([this.warmupPromise]);
1340
+ const quiesceStartedAt = readRuntimeTimestamp(this.executionDependencies);
1341
+ this.emitShutdown({
1342
+ phase: "quiesce-start",
1343
+ reason
1344
+ });
1345
+ failures.push(...await this.quiesceResources(reason));
1346
+ const quiesceEnd = {
1347
+ phase: "quiesce-end",
1348
+ reason
1349
+ };
1350
+ if (quiesceStartedAt !== void 0) Object.assign(quiesceEnd, { durationMs: Math.max(0, (readRuntimeTimestamp(this.executionDependencies) ?? quiesceStartedAt) - quiesceStartedAt) });
1351
+ this.emitShutdown(quiesceEnd);
1352
+ this.state = "draining";
1353
+ const executions = [...this.executions];
1354
+ this.emitShutdown({
1355
+ phase: "drain-start",
1356
+ reason,
1357
+ activeExecutions: executions.length
1358
+ });
1359
+ await this.waitForExecutions(executions, options, reason);
1360
+ failures.push(...await this.quiesceResources(reason));
1361
+ this.emitShutdown({
1362
+ phase: "drain-end",
1363
+ reason,
1364
+ activeExecutions: this.executions.size
1365
+ });
1366
+ this.state = "releasing";
1367
+ this.emitShutdown({
1368
+ phase: "release-start",
1369
+ reason
1370
+ });
1371
+ try {
1372
+ const signalLink = linkAbortSignals(this.signal, this.shutdownController.signal);
1373
+ try {
1374
+ await runRuntimeContext(this.contextStorage, makeRuntimeContext(this.resolver, this.rootScope, [], signalLink.signal, void 0, void 0, this.executor), () => this.rootScope.close(outcome));
1375
+ } finally {
1376
+ signalLink.dispose();
1377
+ }
1378
+ } catch (cause) {
1379
+ failures.push(cause);
1380
+ }
1381
+ try {
1382
+ await this.backend.disposeAll();
1383
+ } catch (cause) {
1384
+ failures.push(cause);
1385
+ }
1386
+ this.state = "disposed";
1387
+ this.emitShutdown({
1388
+ phase: "release-end",
1389
+ reason
1390
+ });
1391
+ if (failures.length > 0) {
1392
+ const error = new LayerDisposeError(failures.flatMap(normalizeDisposeCauses));
1393
+ this.emitShutdown({
1394
+ phase: "shutdown-failure",
1395
+ reason,
1396
+ error
1397
+ });
1398
+ await notifyShutdownFailure(this.onCleanupFailure, {
1399
+ outcome,
1400
+ error
1401
+ });
1402
+ throw error;
1403
+ }
1404
+ this.emitShutdown({
1405
+ phase: "shutdown-complete",
1406
+ reason
1407
+ });
1408
+ }
1409
+ async waitForExecutions(executions, options, reason) {
1410
+ const settled = Promise.allSettled(executions.map((execution) => execution.promise));
1411
+ if (options.abortAfterGracePeriod !== true || executions.length === 0) {
1412
+ await settled;
1413
+ return;
1414
+ }
1415
+ const gracePeriod = options.gracePeriod ?? 0;
1416
+ let timer;
1417
+ const timedOut = await Promise.race([settled.then(() => false), new Promise((resolve) => {
1418
+ timer = setTimeout(() => resolve(true), gracePeriod);
1419
+ })]);
1420
+ if (timer !== void 0) clearTimeout(timer);
1421
+ if (timedOut && !this.shutdownController.signal.aborted) {
1422
+ this.state = "aborting";
1423
+ this.emitShutdown({
1424
+ phase: "abort-active",
1425
+ reason,
1426
+ activeExecutions: this.executions.size
1427
+ });
1428
+ this.shutdownController.abort(/* @__PURE__ */ new Error("Runtime shutdown grace period exceeded"));
1429
+ }
1430
+ await settled;
1431
+ }
1432
+ assertActive() {
1433
+ if (this.state !== "active") throw new RuntimeHandleDisposedError();
1434
+ }
1435
+ };
1436
+ /** Build a Runtime handle for a complete Layer and register its providers. */
1437
+ const createRuntimeHandle = async (layer, backend, options = {}, executionOverrides = {}, providedExecutor) => {
1438
+ const entries = getLayerEntries(layer);
1439
+ const providers = entries.filter((entry) => !isLifecycleEntry(entry));
1440
+ const lifecycleEntries = entries.filter(isLifecycleEntry);
1441
+ const services = providers.map((provider) => provider.service);
1442
+ const serviceTags = providers.map((provider) => captureLayerRegistrationTag(provider));
1443
+ const rootScope = Scope.make();
1444
+ const contextStorage = options.contextStorage ?? defaultRuntimeContextStorage;
1445
+ const observers = options.observers ?? [];
1446
+ const resolver = createResolutionResolver(backend, contextStorage, observers);
1447
+ const executionDependencies = makeRuntimeExecutionDependencies(executionOverrides);
1448
+ ScopeRuntime.bind(rootScope, contextStorage);
1449
+ let handle;
1450
+ const pendingRootQuiesces = [];
1451
+ const executor = providedExecutor ?? createRuntimeExecutor({
1452
+ run: (program, runOptions) => handle.run(program, runOptions),
1453
+ runWith: (request, program, runOptions) => handle.runWith(request, program, runOptions),
1454
+ runWithManaged: (request, program, runOptions) => handle.runWithManaged(request, program, runOptions)
1455
+ });
1456
+ const contextExecutor = eraseRuntimeExecutor(executor);
1457
+ let current;
1458
+ try {
1459
+ for (const provider of providers) {
1460
+ current = provider;
1461
+ await backend.register(bindProviderToScope(provider, rootScope, contextStorage, resolver, observers, contextExecutor, void 0, () => handle?.assertRootAcquisitionAllowed(), (instance) => {
1462
+ if (handle === void 0) pendingRootQuiesces.push({
1463
+ provider,
1464
+ instance
1465
+ });
1466
+ else handle.registerRootQuiesce(provider, instance);
1467
+ }));
1468
+ }
1469
+ } catch (registrationCause) {
1470
+ const outcome = {
1471
+ status: "failure",
1472
+ cause: registrationCause
1473
+ };
1474
+ const cleanupCauses = [];
1475
+ try {
1476
+ await runRuntimeContext(contextStorage, makeRuntimeContext(resolver, rootScope, [], options.signal, void 0, void 0, contextExecutor), () => rootScope.close(outcome));
1477
+ } catch (cause) {
1478
+ cleanupCauses.push(cause);
1479
+ }
1480
+ try {
1481
+ await backend.disposeAll();
1482
+ } catch (cause) {
1483
+ cleanupCauses.push(cause);
1484
+ }
1485
+ if (cleanupCauses.length > 0) {
1486
+ const shutdownError = new LayerDisposeError(cleanupCauses.flatMap(normalizeDisposeCauses));
1487
+ await notifyShutdownFailure(options.onCleanupFailure, {
1488
+ outcome,
1489
+ error: shutdownError
1490
+ });
1491
+ }
1492
+ const cleanupCause = cleanupCauses.length === 1 ? cleanupCauses[0] : cleanupCauses.length > 1 ? new LayerDisposeError(cleanupCauses.flatMap(normalizeDisposeCauses)) : void 0;
1493
+ throw new LayerRegistrationError(current?.service, registrationCause, cleanupCause);
1494
+ }
1495
+ handle = new RuntimeHandleImpl(backend, resolver, rootScope, options.onCleanupFailure, contextStorage, options.signal, observers, services, serviceTags, executionDependencies, contextExecutor, lifecycleEntries);
1496
+ for (const { provider, instance } of pendingRootQuiesces) handle.registerRootQuiesce(provider, instance);
1497
+ return handle;
1498
+ };
1499
+ const isLifecycleEntry = (entry) => "kind" in entry && entry.kind === "lifecycle";
1500
+ //#endregion
1501
+ //#region src/runtime/runtime.ts
1502
+ const isLayerBackend = (value) => value !== void 0 && "register" in value && "resolve" in value && "disposeAll" in value;
1503
+ const resolveRuntimeConfig = (backendOrOptions, legacyOptions) => {
1504
+ if (isLayerBackend(backendOrOptions)) return {
1505
+ backend: backendOrOptions,
1506
+ options: legacyOptions ?? {}
1507
+ };
1508
+ const options = backendOrOptions ?? {};
1509
+ return {
1510
+ backend: options.backend ?? new MapLayerBackend(),
1511
+ options
1512
+ };
1513
+ };
1514
+ /**
1515
+ * Long-lived execution environment backed by a complete Layer.
1516
+ *
1517
+ * A Runtime owns Layer resources until `dispose()` is called. Each `run()` is
1518
+ * isolated in a child Scope, while Layer-scoped resources remain shared.
1519
+ *
1520
+ * @example
1521
+ * ```ts
1522
+ * const runtime = await Runtime.make(AppLive)
1523
+ * const result = await runtime.run(loadUser('u1'))
1524
+ * await runtime.dispose()
1525
+ * ```
1526
+ *
1527
+ * @typeParam Provided The branded Service instances supplied by the Layer.
1528
+ */
1529
+ var Runtime = class Runtime {
1530
+ handle;
1531
+ executor;
1532
+ constructor(handle, executor) {
1533
+ this.handle = handle;
1534
+ this.executor = executor;
1535
+ }
1536
+ static async make(layer, backendOrOptions, legacyOptions) {
1537
+ const { backend, options } = resolveRuntimeConfig(backendOrOptions, legacyOptions);
1538
+ let handle;
1539
+ const executor = createRuntimeExecutor({
1540
+ run: (program, runOptions) => handle.run(program, runOptions),
1541
+ runWith: (request, program, runOptions) => handle.runWith(request, program, runOptions),
1542
+ runWithManaged: (request, program, runOptions) => handle.runWithManaged(request, program, runOptions)
1543
+ });
1544
+ handle = await createRuntimeHandle(layer, backend, options, {}, executor);
1545
+ const runtime = new Runtime(handle, executor);
1546
+ try {
1547
+ if (options.warmup) await runtime.warmup();
1548
+ await handle.activateLifecycle();
1549
+ } catch (cause) {
1550
+ try {
1551
+ await runtime.disposeWithOutcome({
1552
+ status: "failure",
1553
+ cause
1554
+ });
1555
+ } catch {}
1556
+ throw cause;
1557
+ }
1558
+ return runtime;
1559
+ }
1560
+ static async run(layer, backendOrProgramOrOptions, programOrOptions, legacyOptions) {
1561
+ let program;
1562
+ let backendOrOptions;
1563
+ let options;
1564
+ if (typeof backendOrProgramOrOptions === "function") {
1565
+ program = backendOrProgramOrOptions;
1566
+ backendOrOptions = programOrOptions;
1567
+ options = void 0;
1568
+ } else {
1569
+ backendOrOptions = backendOrProgramOrOptions;
1570
+ program = programOrOptions;
1571
+ options = legacyOptions;
1572
+ }
1573
+ const config = resolveRuntimeConfig(backendOrOptions, options);
1574
+ let programOutcome;
1575
+ const outcomeObserver = { onExecutionEnd: ({ outcome }) => {
1576
+ programOutcome = outcome;
1577
+ } };
1578
+ const runtimeOptions = {
1579
+ ...config.options,
1580
+ observers: [outcomeObserver, ...config.options.observers ?? []]
1581
+ };
1582
+ const runtime = await Runtime.make(layer, config.backend, runtimeOptions);
1583
+ let value;
1584
+ let executionFailed = false;
1585
+ let executionFailure;
1586
+ try {
1587
+ value = await runtime.runUnchecked(program, config.options);
1588
+ } catch (cause) {
1589
+ executionFailed = true;
1590
+ executionFailure = cause;
1591
+ }
1592
+ const outcome = programOutcome ?? {
1593
+ status: "failure",
1594
+ cause: executionFailure
1595
+ };
1596
+ try {
1597
+ await runtime.disposeWithOutcome(outcome);
1598
+ } catch (shutdownFailure) {
1599
+ if (!executionFailed && outcome.status === "success") throw shutdownFailure;
1600
+ }
1601
+ if (executionFailed) throw executionFailure;
1602
+ return value;
1603
+ }
1604
+ static async use(layer, use, options) {
1605
+ const runtime = await Runtime.make(layer, options);
1606
+ let value;
1607
+ let executionFailed = false;
1608
+ let executionFailure;
1609
+ let programOutcome;
1610
+ try {
1611
+ value = await use(runtime);
1612
+ programOutcome = classifyRuntimeOutcome(value);
1613
+ } catch (cause) {
1614
+ executionFailed = true;
1615
+ executionFailure = cause;
1616
+ programOutcome = {
1617
+ status: "failure",
1618
+ cause
1619
+ };
1620
+ }
1621
+ const outcome = programOutcome ?? {
1622
+ status: "failure",
1623
+ cause: executionFailure
1624
+ };
1625
+ try {
1626
+ await runtime.disposeWithOutcome(outcome);
1627
+ } catch (shutdownFailure) {
1628
+ if (!executionFailed && outcome.status === "success") throw shutdownFailure;
1629
+ }
1630
+ if (executionFailed) throw executionFailure;
1631
+ return value;
1632
+ }
1633
+ /** Request the non-owning executor view from the current Runtime context. */
1634
+ static executor() {
1635
+ return makeRuntimeExecutorRequest();
1636
+ }
1637
+ /** Resolve every Layer provider and dispose the Runtime if warmup fails. */
1638
+ async warmup() {
1639
+ try {
1640
+ await this.handle.warmup();
1641
+ } catch (cause) {
1642
+ try {
1643
+ await this.handle.dispose({
1644
+ status: "failure",
1645
+ cause
1646
+ });
1647
+ } catch {}
1648
+ throw cause;
1649
+ }
1650
+ }
1651
+ /** Return a detached diagnostic snapshot without changing Runtime state. */
1652
+ inspect() {
1653
+ return this.handle.inspect();
1654
+ }
1655
+ /** Run one execution in this Runtime's child Scope. */
1656
+ run(program, options) {
1657
+ return this.handle.run(program, options);
1658
+ }
1659
+ /** Run one execution with a Layer owned by that execution's child Scope. */
1660
+ runWith(layer, program, options) {
1661
+ return this.handle.runWith(layer, program, options);
1662
+ }
1663
+ runUnchecked(program, options) {
1664
+ return this.handle.run(program, options);
1665
+ }
1666
+ dispose(optionsOrOutcome) {
1667
+ return this.handle.dispose(optionsOrOutcome);
1668
+ }
1669
+ /** Release Runtime-owned resources through JavaScript's async disposal protocol. */
1670
+ async [Symbol.asyncDispose]() {
1671
+ await this.dispose();
1672
+ }
1673
+ disposeWithOutcome(outcome) {
1674
+ return this.handle.dispose(outcome);
1675
+ }
1676
+ };
1677
+ //#endregion
1678
+ export { RuntimeObserver as a, MapLayerBackend as c, classifyRuntimeOutcome as i, Scope as l, eraseRuntimeExecutor as n, inheritProgramName as o, getRuntimeTaskSupervisor as r, setProgramName as s, Runtime as t, ScopeRuntime as u };
1679
+
1680
+ //# sourceMappingURL=runtime-qpcVwaz_.mjs.map