better-effect 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +327 -7
- package/dist/adapters/iti.d.mts +3 -3
- package/dist/bun.d.mts +43 -0
- package/dist/bun.d.mts.map +1 -0
- package/dist/bun.mjs +40 -0
- package/dist/bun.mjs.map +1 -0
- package/dist/{context-BUEf1qjL.mjs → context-BphfFUMO.mjs} +4 -2
- package/dist/context-BphfFUMO.mjs.map +1 -0
- package/dist/current-request-CIU7AHhF.d.mts +22 -0
- package/dist/current-request-CIU7AHhF.d.mts.map +1 -0
- package/dist/current-request-DDKNyymv.mjs +20 -0
- package/dist/current-request-DDKNyymv.mjs.map +1 -0
- package/dist/{signal-D2UTcaaG.mjs → disposable-CP-Q2H3l.mjs} +4 -52
- package/dist/disposable-CP-Q2H3l.mjs.map +1 -0
- package/dist/{effect-CK4YZaX0.mjs → effect-CPdV7Yv8.mjs} +2 -2
- package/dist/{effect-CK4YZaX0.mjs.map → effect-CPdV7Yv8.mjs.map} +1 -1
- package/dist/hono.d.mts +7 -5
- package/dist/hono.d.mts.map +1 -1
- package/dist/hono.mjs +88 -30
- package/dist/hono.mjs.map +1 -1
- package/dist/{index-heuaRmXR.d.mts → index-AiKM71-u.d.mts} +3 -1
- package/dist/{index-heuaRmXR.d.mts.map → index-AiKM71-u.d.mts.map} +1 -1
- package/dist/{index-GYJ4qm9K.d.mts → index-BodMy6rO.d.mts} +6 -5
- package/dist/index-BodMy6rO.d.mts.map +1 -0
- package/dist/{index-CX6iAoCB.d.mts → index-CCi07kUw.d.mts} +2 -2
- package/dist/{index-CX6iAoCB.d.mts.map → index-CCi07kUw.d.mts.map} +1 -1
- package/dist/{index-BMdU_Z72.d.mts → index-DAKn0qHk.d.mts} +4 -3
- package/dist/index-DAKn0qHk.d.mts.map +1 -0
- package/dist/{index-B1nH4luq.d.mts → index-cXgyMa0v.d.mts} +6 -20
- package/dist/index-cXgyMa0v.d.mts.map +1 -0
- package/dist/index.d.mts +6 -5
- package/dist/index.mjs +7 -6
- package/dist/index.mjs.map +1 -1
- package/dist/{layer-D56fRdLt.mjs → layer-D16GKxuX.mjs} +4 -4
- package/dist/layer-D16GKxuX.mjs.map +1 -0
- package/dist/next.d.mts +116 -0
- package/dist/next.d.mts.map +1 -0
- package/dist/next.mjs +68 -0
- package/dist/next.mjs.map +1 -0
- package/dist/{node-context-lggRF4bR.mjs → node-context-Ca18oNSg.mjs} +2 -2
- package/dist/{node-context-lggRF4bR.mjs.map → node-context-Ca18oNSg.mjs.map} +1 -1
- package/dist/{node-context-DWsCUBRa.d.mts → node-context-DczjAcrX.d.mts} +2 -2
- package/dist/{node-context-DWsCUBRa.d.mts.map → node-context-DczjAcrX.d.mts.map} +1 -1
- package/dist/node.d.mts +4 -4
- package/dist/node.mjs +4 -4
- package/dist/observer-9nhbL7Pr.d.mts +68 -0
- package/dist/observer-9nhbL7Pr.d.mts.map +1 -0
- package/dist/opentelemetry.d.mts +94 -0
- package/dist/opentelemetry.d.mts.map +1 -0
- package/dist/opentelemetry.mjs +453 -0
- package/dist/opentelemetry.mjs.map +1 -0
- package/dist/{outcome-CB43bnFW.d.mts → outcome-DI8LPIQ4.d.mts} +14 -69
- package/dist/outcome-DI8LPIQ4.d.mts.map +1 -0
- package/dist/{program-metadata-DhQCCirO.mjs → program-metadata-BxjGkT17.mjs} +3 -3
- package/dist/{program-metadata-DhQCCirO.mjs.map → program-metadata-BxjGkT17.mjs.map} +1 -1
- package/dist/runtime/explicit.d.mts +1 -1
- package/dist/runtime/explicit.mjs +1 -1
- package/dist/runtime/node.d.mts +2 -2
- package/dist/runtime/node.mjs +2 -2
- package/dist/{runtime-CBMrX8Wl.mjs → runtime-C_55ofnL.mjs} +42 -27
- package/dist/runtime-C_55ofnL.mjs.map +1 -0
- package/dist/signal-nfgFyNCk.mjs +52 -0
- package/dist/signal-nfgFyNCk.mjs.map +1 -0
- package/dist/{standard-services-GBZ32tll.mjs → standard-services-vnGIafkS.mjs} +3 -17
- package/dist/standard-services-vnGIafkS.mjs.map +1 -0
- package/dist/standard-services.d.mts +3 -2
- package/dist/standard-services.mjs +3 -2
- package/dist/testing.d.mts +6 -5
- package/dist/testing.d.mts.map +1 -1
- package/dist/testing.mjs +6 -6
- package/dist/types-oihI-ESv.d.mts +54 -0
- package/dist/types-oihI-ESv.d.mts.map +1 -0
- package/dist/web-Bq3MfMrj.mjs +147 -0
- package/dist/web-Bq3MfMrj.mjs.map +1 -0
- package/dist/web.d.mts +47 -0
- package/dist/web.d.mts.map +1 -0
- package/dist/web.mjs +2 -0
- package/package.json +33 -2
- package/dist/context-BUEf1qjL.mjs.map +0 -1
- package/dist/index-B1nH4luq.d.mts.map +0 -1
- package/dist/index-BMdU_Z72.d.mts.map +0 -1
- package/dist/index-GYJ4qm9K.d.mts.map +0 -1
- package/dist/layer-D56fRdLt.mjs.map +0 -1
- package/dist/outcome-CB43bnFW.d.mts.map +0 -1
- package/dist/runtime-CBMrX8Wl.mjs.map +0 -1
- package/dist/signal-D2UTcaaG.mjs.map +0 -1
- package/dist/standard-services-GBZ32tll.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -344,9 +344,13 @@ await runtime.warmup()
|
|
|
344
344
|
Warmup failures include the Service and resolution path, release resources
|
|
345
345
|
already acquired, dispose the backend and reject the Runtime. Optional
|
|
346
346
|
observers expose Service resolution/acquisition, execution and Layer release
|
|
347
|
-
events without coupling the core to an observability SDK.
|
|
348
|
-
|
|
349
|
-
|
|
347
|
+
events without coupling the core to an observability SDK. Service events carry
|
|
348
|
+
an optional matching `executionId` only when they occur inside an active
|
|
349
|
+
execution; warmup and Runtime-root activity omit it. Execution events carry one
|
|
350
|
+
matching `executionId`, the optional Program name, copied readonly attributes,
|
|
351
|
+
and a monotonic `durationMs` measured through execution cleanup. An end event
|
|
352
|
+
keeps the primary program `outcome` and adds `cleanupFailure` when execution
|
|
353
|
+
Scope cleanup fails:
|
|
350
354
|
|
|
351
355
|
```ts
|
|
352
356
|
const runtime = await Runtime.make(AppLive, {
|
|
@@ -438,6 +442,80 @@ and its ordered `timeline`; call `clear()` to reuse it. Composition invokes
|
|
|
438
442
|
observers in declaration order and isolates thrown or rejected observer
|
|
439
443
|
failures from the Runtime result.
|
|
440
444
|
|
|
445
|
+
### Optional OpenTelemetry tracing
|
|
446
|
+
|
|
447
|
+
Install the OpenTelemetry API only when this subpath is used:
|
|
448
|
+
|
|
449
|
+
```bash
|
|
450
|
+
bun add better-effect @opentelemetry/api
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
`better-effect/opentelemetry` accepts either an existing `Tracer` or an existing
|
|
454
|
+
`TracerProvider`. Its supported `@opentelemetry/api` peer range is
|
|
455
|
+
`>=1.9.0 <1.10.0` (tested with 1.9.1). It never installs a global provider, SDK,
|
|
456
|
+
context manager or exporter. The provider form only calls `getTracer`:
|
|
457
|
+
|
|
458
|
+
```ts
|
|
459
|
+
import { trace } from '@opentelemetry/api'
|
|
460
|
+
import { OpenTelemetryRuntimeObserver } from 'better-effect/opentelemetry'
|
|
461
|
+
|
|
462
|
+
const observer = OpenTelemetryRuntimeObserver.make({
|
|
463
|
+
// An existing provider can be passed instead with `provider` and `tracerName`.
|
|
464
|
+
tracer: trace.getTracer('acme.application'),
|
|
465
|
+
serviceResolution: 'events',
|
|
466
|
+
recordFailures: true,
|
|
467
|
+
executionAttributeAllowlist: ['requestId'],
|
|
468
|
+
sanitizeFailure: (cause) =>
|
|
469
|
+
cause instanceof KnownDomainError ? { message: cause.code } : undefined
|
|
470
|
+
})
|
|
471
|
+
|
|
472
|
+
const runtime = await Runtime.make(AppLive, { observers: [observer] })
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
The adapter starts one span for each execution, keyed only by the Runtime's
|
|
476
|
+
`executionId`. The Program name is the span name, with
|
|
477
|
+
`better-effect.execution` as the stable fallback. Executions whose program and
|
|
478
|
+
execution cleanup succeed use OpenTelemetry `OK`; typed `Result.err` values,
|
|
479
|
+
thrown defects and execution cleanup failures use `ERROR`. The Runtime observer
|
|
480
|
+
keeps cleanup failure separate from the primary program outcome, so the adapter
|
|
481
|
+
can report the final execution status without turning cleanup into a program
|
|
482
|
+
defect or serializing its cause by default.
|
|
483
|
+
Span timing is supplied by OpenTelemetry's start/end clock; `durationMs` is not
|
|
484
|
+
written as a second duration source.
|
|
485
|
+
|
|
486
|
+
Service telemetry is explicit and defaults to `off`:
|
|
487
|
+
|
|
488
|
+
- `off` creates no Service telemetry.
|
|
489
|
+
- `events` adds resolution, acquisition and release events to an execution span
|
|
490
|
+
only when the Runtime event carries an explicit active execution ID. Warmup,
|
|
491
|
+
Runtime-root cleanup and other events without an owner use standalone spans.
|
|
492
|
+
- `spans` creates child Service spans only for events with an explicit active
|
|
493
|
+
execution ID. Warmup and Runtime-root cleanup are represented by standalone
|
|
494
|
+
service spans (or generic event-carrier spans in `events` mode); ambient
|
|
495
|
+
OpenTelemetry context is never used to guess ownership.
|
|
496
|
+
|
|
497
|
+
Service identity is always the logical `serviceTag`; constructor names and
|
|
498
|
+
Service instances are never used. `RuntimeObserver.compose` can combine this
|
|
499
|
+
adapter with recorded, graph and application observers, and a tracer failure is
|
|
500
|
+
isolated from every Runtime result. Call `observer.dispose()` when an observer
|
|
501
|
+
may outlive its Runtime to end state left by malformed or missing end events;
|
|
502
|
+
normal execution spans are ended exactly once by their matching `executionId`.
|
|
503
|
+
|
|
504
|
+
Telemetry is privacy-preserving by default. The adapter records only bounded
|
|
505
|
+
library, execution ID, Program/outcome, Service-tag and resolution-path data.
|
|
506
|
+
It does not record causes, stacks, requests, arbitrary execution attributes or
|
|
507
|
+
Service instances, and it never stringifies unknown values. Add attributes only
|
|
508
|
+
through `executionAttributeAllowlist` or the explicit
|
|
509
|
+
`sanitizeExecutionAttributes` callback; add failure details only through
|
|
510
|
+
`sanitizeFailure` together with `recordFailures: true`. Unsupported values are
|
|
511
|
+
dropped, strings are bounded, and default limits are 256 characters, 32
|
|
512
|
+
attributes and 16 resolution-path tags (caller limits remain capped). Sanitizer
|
|
513
|
+
callbacks should return only intentional scalar OpenTelemetry attributes.
|
|
514
|
+
|
|
515
|
+
For distributed tracing, establish the caller's OpenTelemetry context before
|
|
516
|
+
calling `runtime.run`; the adapter does not propagate context or instrument
|
|
517
|
+
HTTP/database libraries automatically.
|
|
518
|
+
|
|
441
519
|
For a startup view of the graph actually observed by a Runtime, compose the
|
|
442
520
|
small graph observer and warm the Layer before accepting work:
|
|
443
521
|
|
|
@@ -518,12 +596,254 @@ with the execution Scope and never change the shared Runtime environment. Its
|
|
|
518
596
|
external requirements must be provided by the Runtime, and the Hono failure
|
|
519
597
|
handler/request-Layer types are checked at the adapter boundary.
|
|
520
598
|
|
|
599
|
+
### Framework-neutral Web request boundaries
|
|
600
|
+
|
|
601
|
+
The `better-effect/web` entrypoint provides a small Request-to-Response
|
|
602
|
+
boundary without depending on Hono or another framework. Use it anywhere a
|
|
603
|
+
framework gives you standard Web `Request` and `Response` values:
|
|
604
|
+
|
|
605
|
+
```ts
|
|
606
|
+
import { Result } from 'better-result'
|
|
607
|
+
import { CurrentAbortSignal, Effect } from 'better-effect'
|
|
608
|
+
import { CurrentRequest } from 'better-effect/standard-services'
|
|
609
|
+
import { WebEffect } from 'better-effect/web'
|
|
610
|
+
|
|
611
|
+
const handleRequest = (request: Request) =>
|
|
612
|
+
WebEffect.handle(
|
|
613
|
+
runtime,
|
|
614
|
+
request,
|
|
615
|
+
Effect.fn(async function* () {
|
|
616
|
+
const currentRequest = yield* CurrentRequest
|
|
617
|
+
const signal = yield* CurrentAbortSignal
|
|
618
|
+
const user = yield* UserService
|
|
619
|
+
const result = yield* Result.await(user.find())
|
|
620
|
+
|
|
621
|
+
return Result.ok({
|
|
622
|
+
result,
|
|
623
|
+
url: (currentRequest.request as Request).url,
|
|
624
|
+
aborted: signal.aborted
|
|
625
|
+
})
|
|
626
|
+
})
|
|
627
|
+
)
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
`WebEffect.handle` supplies `CurrentRequest`, forwards `request.signal`, and
|
|
631
|
+
runs one lazy Program in a child Scope. Request-local resources are released
|
|
632
|
+
before the returned Promise resolves; Runtime-root resources remain owned by
|
|
633
|
+
the Runtime. A `requestLayer` option can add per-request providers or
|
|
634
|
+
intentionally override a compatible request tag.
|
|
635
|
+
|
|
636
|
+
The default success policy passes through a Web `Response`, maps top-level
|
|
637
|
+
`undefined` to 204, and wraps supported values as `{ data: value }` JSON. A
|
|
638
|
+
non-`undefined`, non-`Response` value must be an acyclic graph of `null`,
|
|
639
|
+
booleans, strings, finite numbers, dense arrays, and plain object records.
|
|
640
|
+
Arrays must have only the own string properties `length` and one property for
|
|
641
|
+
each index from `0` through `length - 1`; each index must be an enumerable data
|
|
642
|
+
property. Symbol keys, extra own properties (including non-enumerable ones),
|
|
643
|
+
sparse holes, and accessor elements are rejected. Object records must have
|
|
644
|
+
`Object.prototype` or `null` as their prototype, and every own string-keyed
|
|
645
|
+
property must be an enumerable data property. Own symbol keys,
|
|
646
|
+
non-enumerable properties, accessors, custom prototypes, and other non-plain
|
|
647
|
+
objects are rejected. Shared references in separate branches are serialized as
|
|
648
|
+
repeated values. Nested `undefined`, `bigint`, functions, symbols, and
|
|
649
|
+
non-finite numbers (`NaN` and infinities) are rejected with
|
|
650
|
+
`WebEffectSerializationError` (a `TypeError`) instead of being silently dropped
|
|
651
|
+
or coerced. Use an explicit `onSuccess` policy for other representations. The
|
|
652
|
+
default failure policy passes through a standards-compatible `Response`
|
|
653
|
+
failure and redacts every other typed failure to `{ error: 'Internal Server Error' }`
|
|
654
|
+
with status 500. Custom
|
|
655
|
+
`onSuccess`/`onFailure` policies may be asynchronous but must return a
|
|
656
|
+
standards-compatible `Response`. The boundary checks that protocol structurally:
|
|
657
|
+
`status` is an integer in `0` or `200` through `599`, `ok` matches the 2xx
|
|
658
|
+
status range, `redirected` and `bodyUsed` are booleans, `statusText` and `url`
|
|
659
|
+
are strings, `type` is a standard Response type, and
|
|
660
|
+
`arrayBuffer()`, `blob()`, `bytes()`, `clone()`, `formData()`, `json()`, and
|
|
661
|
+
`text()` are callable. `headers` must provide callable `append()`, `delete()`,
|
|
662
|
+
`get()`, `getSetCookie()`, `has()`, `set()`, and `forEach()` operations. `body`
|
|
663
|
+
must be `null` (including legitimate null-body Responses such as `204`) or a
|
|
664
|
+
ReadableStream-compatible object with a boolean `locked` property and callable
|
|
665
|
+
`cancel()`, `getReader()`, `pipeThrough()`, `pipeTo()`, and `tee()` methods.
|
|
666
|
+
Native cross-realm Responses and other values satisfying this protocol are
|
|
667
|
+
accepted without `instanceof Response`; missing capabilities and forged
|
|
668
|
+
`Response.prototype` values fail with `TypeError`. Thrown defects remain
|
|
669
|
+
rejected. The Program's Service and failure channels, request-Layer
|
|
670
|
+
requirements, and override compatibility are checked at the TypeScript
|
|
671
|
+
boundary.
|
|
672
|
+
|
|
673
|
+
### Next.js App Router request boundaries
|
|
674
|
+
|
|
675
|
+
The optional `better-effect/next` entrypoint adapts an application-owned
|
|
676
|
+
Runtime to native Next.js App Router Route Handlers without importing Next.js
|
|
677
|
+
from the core or main entrypoint:
|
|
678
|
+
|
|
679
|
+
```ts
|
|
680
|
+
import { Result } from 'better-result'
|
|
681
|
+
import { Effect, Layer, Runtime, Service } from 'better-effect'
|
|
682
|
+
import { NextEffect } from 'better-effect/next'
|
|
683
|
+
|
|
684
|
+
class UserService extends Service<UserService>()('UserService') {
|
|
685
|
+
find(id: string) {
|
|
686
|
+
return { id, name: 'Ada' }
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
const runtime = await Runtime.make(Layer.make(UserService))
|
|
691
|
+
const http = NextEffect.make(runtime)
|
|
692
|
+
|
|
693
|
+
export const GET = http.gen(async function* (_request, context: RouteContext<'/api/users/[id]'>) {
|
|
694
|
+
const { id } = await context.params
|
|
695
|
+
const users = yield* UserService
|
|
696
|
+
|
|
697
|
+
return Result.ok(users.find(id))
|
|
698
|
+
})
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
`NextEffect.gen` and `NextEffect.handler` return the native
|
|
702
|
+
`(request, context) => Promise<Response>` shape expected by App Router route
|
|
703
|
+
files. The context is typed with Next's asynchronous `params`; `handler` is
|
|
704
|
+
useful when the complete `Effect.fn` Program already exists.
|
|
705
|
+
|
|
706
|
+
For a long-lived App Router application, keep the Runtime in an
|
|
707
|
+
application-owned module and expose explicit disposal for the host lifecycle:
|
|
708
|
+
|
|
709
|
+
```ts
|
|
710
|
+
// app/runtime.ts
|
|
711
|
+
export const appRuntime = await Runtime.make(AppLive)
|
|
712
|
+
|
|
713
|
+
// Call this from the actual host/server shutdown hook.
|
|
714
|
+
export const disposeAppRuntime = (): Promise<void> => appRuntime.dispose()
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
Route modules import that Runtime and bind it to the adapter:
|
|
718
|
+
|
|
719
|
+
```ts
|
|
720
|
+
// app/api/users/[id]/route.ts
|
|
721
|
+
import { appRuntime } from '@/app/runtime'
|
|
722
|
+
|
|
723
|
+
const http = NextEffect.make(appRuntime)
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
Do not put this long-lived Runtime in an `await using` scope that ends during
|
|
727
|
+
module initialization; that would dispose it before exported handlers serve
|
|
728
|
+
requests. `NextEffect.make` stores only the Runtime supplied by the caller: it
|
|
729
|
+
does not create a process-global singleton or mutate hidden adapter state.
|
|
730
|
+
Sharing `appRuntime` is an application ownership choice. If a deployment
|
|
731
|
+
requires per-invocation ownership instead, use the existing `Runtime.use`
|
|
732
|
+
helper explicitly; the adapter never creates a Runtime per request by default:
|
|
733
|
+
|
|
734
|
+
```ts
|
|
735
|
+
export const GET = (request, context) =>
|
|
736
|
+
Runtime.use(AppLive, (runtime) =>
|
|
737
|
+
NextEffect.make(runtime).handler(() => getUser(context))(request, context)
|
|
738
|
+
)
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
Each request creates one WebEffect execution and child Scope, installs
|
|
742
|
+
`CurrentRequest` and `CurrentAbortSignal`, and releases request-local Layers
|
|
743
|
+
before the handler Promise resolves. The request's
|
|
744
|
+
`AbortSignal` is linked into the execution signal, and concurrent requests keep
|
|
745
|
+
request Layers and context isolated.
|
|
746
|
+
|
|
747
|
+
The default success policy passes through a returned `Response`; other values
|
|
748
|
+
are encoded as `{ data: value }` JSON using the same strict serialization rules
|
|
749
|
+
as `better-effect/web`. A route may select at most one success policy:
|
|
750
|
+
`respond` handles a complete Response, `serialize` transforms a JSON-safe
|
|
751
|
+
value, and route-level `onSuccess` replaces the shared success policy. Shared
|
|
752
|
+
`onSuccess` and `onFailure` policies receive the native Request and route
|
|
753
|
+
context. Typed
|
|
754
|
+
`Result.err` failures use `onFailure` (or the redacted 500 default), while
|
|
755
|
+
thrown defects remain rejected. Policies must return a standards-compatible
|
|
756
|
+
`Response` and may be asynchronous. This adapter does not add Edge-runtime
|
|
757
|
+
support; use it only in hosts supported by the configured better-effect
|
|
758
|
+
Runtime.
|
|
759
|
+
|
|
760
|
+
Install Next.js only when this subpath is used:
|
|
761
|
+
|
|
762
|
+
```bash
|
|
763
|
+
bun add better-effect better-result next
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
`next` is an optional peer dependency, and `better-effect/next` uses only the
|
|
767
|
+
public native Route Handler shape, so the core and other entrypoints remain
|
|
768
|
+
usable without Next.js.
|
|
769
|
+
|
|
770
|
+
### Bun.serve fetch adapter
|
|
771
|
+
|
|
772
|
+
The optional `better-effect/bun` entrypoint is a small Bun-only adapter over
|
|
773
|
+
`WebEffect`. It does not create a Runtime, own a Bun server, install a router,
|
|
774
|
+
or make the Bun server an implicit Service. The route factory receives Bun's
|
|
775
|
+
`Request` and `Bun.Server` values explicitly:
|
|
776
|
+
|
|
777
|
+
```ts
|
|
778
|
+
import { Result } from 'better-result'
|
|
779
|
+
import { CurrentAbortSignal, Effect, Layer, Runtime, Service } from 'better-effect'
|
|
780
|
+
import { CurrentRequest } from 'better-effect/standard-services'
|
|
781
|
+
import { BunEffect } from 'better-effect/bun'
|
|
782
|
+
|
|
783
|
+
class AppService extends Service<AppService>()('AppService') {
|
|
784
|
+
handle(url: string) {
|
|
785
|
+
return url
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
const AppLive = Layer.make(AppService)
|
|
790
|
+
const runtime = await Runtime.make(AppLive)
|
|
791
|
+
const http = BunEffect.make(runtime, {
|
|
792
|
+
onFailure: (_error, request) =>
|
|
793
|
+
Response.json({ error: 'Request failed', url: request.url }, { status: 500 })
|
|
794
|
+
})
|
|
795
|
+
|
|
796
|
+
const server = Bun.serve({
|
|
797
|
+
port: 3000,
|
|
798
|
+
fetch: http.handler((request, server) =>
|
|
799
|
+
Effect.fn(async function* () {
|
|
800
|
+
const app = yield* AppService
|
|
801
|
+
const currentRequest = yield* CurrentRequest
|
|
802
|
+
const signal = yield* CurrentAbortSignal
|
|
803
|
+
|
|
804
|
+
return Result.ok({
|
|
805
|
+
value: app.handle(request.url),
|
|
806
|
+
currentUrl: (currentRequest.request as Request).url,
|
|
807
|
+
port: server.port,
|
|
808
|
+
aborted: signal.aborted
|
|
809
|
+
})
|
|
810
|
+
})
|
|
811
|
+
)
|
|
812
|
+
})
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
`BunEffect.handler` invokes exactly one `WebEffect` request boundary. That
|
|
816
|
+
boundary supplies `CurrentRequest`, forwards the request signal, composes
|
|
817
|
+
request-local Layers, applies the configured failure/response policies, keeps
|
|
818
|
+
thrown defects rejected, and releases request resources before the handler
|
|
819
|
+
Promise resolves. Runtime-root resources remain shared and owned by `runtime`.
|
|
820
|
+
|
|
821
|
+
The application owns both long-lived resources and must shut them down
|
|
822
|
+
explicitly. Stop accepting requests before releasing root Services, then
|
|
823
|
+
release the Runtime:
|
|
824
|
+
|
|
825
|
+
```ts
|
|
826
|
+
await server.stop()
|
|
827
|
+
await runtime.dispose()
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
`server.stop()` is the Bun server lifecycle boundary; `BunEffect` does not
|
|
831
|
+
provide a `serve` helper or dispose either resource for you. Keep a single
|
|
832
|
+
application-owned shutdown Promise if shutdown can be requested more than once.
|
|
833
|
+
This Bun-specific entrypoint makes no Node compatibility claim.
|
|
834
|
+
|
|
521
835
|
### Hono request boundaries
|
|
522
836
|
|
|
523
|
-
The optional `better-effect/hono` entrypoint
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
837
|
+
The optional `better-effect/hono` entrypoint supplies Hono's middleware,
|
|
838
|
+
validator, and Context integration around the same Web request boundary used
|
|
839
|
+
by `better-effect/web`. It adapts Hono's Context to a standard Web `Request`,
|
|
840
|
+
then delegates the single `Runtime` execution, Result/defect handling, and
|
|
841
|
+
request Scope cleanup to that shared boundary. You only need to configure one
|
|
842
|
+
Hono middleware boundary per request; the adapter prevents duplicate
|
|
843
|
+
registrations from opening another execution.
|
|
844
|
+
|
|
845
|
+
Handlers can yield Services directly; the adapter provides `CurrentRequest`,
|
|
846
|
+
forwards `Request.signal`, and converts Results to Responses in one policy:
|
|
527
847
|
|
|
528
848
|
```ts
|
|
529
849
|
import { Hono } from 'hono'
|
package/dist/adapters/iti.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { N as AnyServiceToken } from "../index-
|
|
2
|
-
import {
|
|
3
|
-
import "../index-
|
|
1
|
+
import { N as AnyServiceToken } from "../index-AiKM71-u.mjs";
|
|
2
|
+
import { d as LayerBackend, f as LayerBackendDisposeOptions, m as LayerRegistration } from "../outcome-DI8LPIQ4.mjs";
|
|
3
|
+
import "../index-DAKn0qHk.mjs";
|
|
4
4
|
//#region src/adapters/iti.d.ts
|
|
5
5
|
/**
|
|
6
6
|
* ITI-backed Layer backend.
|
package/dist/bun.d.mts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { M as AnyService } from "./index-AiKM71-u.mjs";
|
|
2
|
+
import { y as LayerInput } from "./outcome-DI8LPIQ4.mjs";
|
|
3
|
+
import { l as Runtime } from "./index-BodMy6rO.mjs";
|
|
4
|
+
import { a as WebEffectOptions, n as CompleteWebProgram, o as WebEffectProgram, r as DefaultRequestLayer, s as WebEffectSuccess, t as AnyProgram, u as WebRequestLayerChecks } from "./types-oihI-ESv.mjs";
|
|
5
|
+
//#region src/bun/types.d.ts
|
|
6
|
+
/** A Bun server passed to a Bun.serve fetch handler. */
|
|
7
|
+
type BunServer<WebSocketData = undefined> = Bun.Server<WebSocketData>;
|
|
8
|
+
/** The Promise<Response> handler shape accepted by Bun.serve. */
|
|
9
|
+
type BunFetchHandler<WebSocketData = undefined> = (request: Request, server: BunServer<WebSocketData>) => Promise<Response>;
|
|
10
|
+
/** A lazy Result-valued Program accepted by the Bun adapter. */
|
|
11
|
+
type BunEffectProgram<A = unknown, E = unknown, R extends AnyService = never> = WebEffectProgram<A, E, R>;
|
|
12
|
+
/** Options for adapting a WebEffect boundary to Bun's fetch callback. */
|
|
13
|
+
type BunEffectOptions<Failure = unknown, RequestLayer extends LayerInput = DefaultRequestLayer> = Omit<WebEffectOptions<Failure, RequestLayer>, 'onFailure' | 'onSuccess'> & {
|
|
14
|
+
/** Convert a successful Program value into a Response. */
|
|
15
|
+
readonly onSuccess?: (result: WebEffectSuccess, request: Request) => ResponseLike;
|
|
16
|
+
/** Convert a typed Program failure into a Response. */
|
|
17
|
+
readonly onFailure?: (error: Failure, request: Request) => ResponseLike;
|
|
18
|
+
};
|
|
19
|
+
/** A standard Web response or an asynchronous response. */
|
|
20
|
+
type ResponseLike = Response | PromiseLike<Response>;
|
|
21
|
+
/** @internal */
|
|
22
|
+
type BunAnyProgram = AnyProgram;
|
|
23
|
+
/** @internal */
|
|
24
|
+
type BunHandlerProgram<Provided extends AnyService, RequestLayer extends LayerInput, Program extends AnyProgram, Failure> = CompleteWebProgram<Provided, RequestLayer, Program, Failure>;
|
|
25
|
+
/** @internal */
|
|
26
|
+
type BunRequestLayerChecks<Provided extends AnyService, RequestLayer extends LayerInput> = WebRequestLayerChecks<Provided, RequestLayer>;
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/bun/index.d.ts
|
|
29
|
+
type BunHandlerFactory<Provided extends AnyService, RequestLayer extends LayerInput, Failure, WebSocketData, ProgramFactory extends (request: Request, server: Bun.Server<WebSocketData>) => BunAnyProgram> = ProgramFactory & ([ReturnType<ProgramFactory>] extends [BunHandlerProgram<Provided, RequestLayer, ReturnType<ProgramFactory>, Failure>] ? unknown : (request: Request, server: Bun.Server<WebSocketData>) => BunHandlerProgram<Provided, RequestLayer, ReturnType<ProgramFactory>, Failure>);
|
|
30
|
+
/** Bind a Runtime and WebEffect policy to a Bun.serve fetch handler. */
|
|
31
|
+
declare class BunEffect<Provided extends AnyService = never, Failure = unknown, RequestLayer extends LayerInput = DefaultRequestLayer> {
|
|
32
|
+
readonly runtime: Runtime<Provided>;
|
|
33
|
+
private readonly onSuccess;
|
|
34
|
+
private readonly onFailure;
|
|
35
|
+
private readonly requestLayer;
|
|
36
|
+
private constructor();
|
|
37
|
+
static make<Provided extends AnyService, Failure = unknown, RequestLayer extends LayerInput = DefaultRequestLayer>(runtime: Runtime<Provided>, options?: BunEffectOptions<Failure, RequestLayer> & BunRequestLayerChecks<Provided, RequestLayer>): BunEffect<Provided, Failure, RequestLayer>;
|
|
38
|
+
handler<WebSocketData = undefined, const ProgramFactory extends (request: Request, server: Bun.Server<WebSocketData>) => BunAnyProgram = (request: Request, server: Bun.Server<WebSocketData>) => BunAnyProgram>(makeProgram: BunHandlerFactory<Provided, RequestLayer, Failure, WebSocketData, ProgramFactory>): BunFetchHandler<WebSocketData>;
|
|
39
|
+
private makeWebOptions;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { BunEffect, type BunEffectOptions, type BunEffectProgram, type BunFetchHandler, type BunServer, type ResponseLike };
|
|
43
|
+
//# sourceMappingURL=bun.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bun.d.mts","names":[],"sources":["../src/bun/types.ts","../src/bun/index.ts"],"mappings":";;;;;;KAaY,UAAU,6BAA6B,IAAI,OAAO;;KAGlD,gBAAgB,8BAC1B,SAAS,SACT,QAAQ,UAAU,mBACf,QAAQ;;KAGD,iBACV,aACA,aACA,UAAU,sBACR,iBAAiB,GAAG,GAAG;;KAGf,iBACV,mBACA,qBAAqB,aAAa,uBAChC,KAAK,iBAAiB,SAAS;;WAExB,aAAa,QAAQ,kBAAkB,SAAS,YAAY;;WAE5D,aAAa,OAAO,SAAS,SAAS,YAAY;;;KAIjD,eAAe,WAAW,YAAY;;KAGtC,gBAAgB;;KAGhB,kBACV,iBAAiB,YACjB,qBAAqB,YACrB,gBAAgB,YAChB,WACE,mBAAmB,UAAU,cAAc,SAAS;;KAG5C,sBACV,iBAAiB,YACjB,qBAAqB,cACnB,sBAAsB,UAAU;;;KCjC/B,kBACH,iBAAiB,YACjB,qBAAqB,YACrB,SACA,eACA,wBAAwB,SAAS,SAAS,QAAQ,IAAI,OAAO,mBAAmB,iBAC9E,mBACA,WAAW,0BACX,kBAAkB,UAAU,cAAc,WAAW,iBAAiB,uBAIlE,SAAS,SACT,QAAQ,IAAI,OAAO,mBAChB,kBAAkB,UAAU,cAAc,WAAW,iBAAiB;;cAGpE,UACX,iBAAiB,oBACjB,mBACA,qBAAqB,aAAa;WAEzB,SAAS,QAAQ;mBAET;mBAEA;mBAEA;UAEV;SAUA,KACL,iBAAiB,YACjB,mBACA,qBAAqB,aAAa,qBAElC,SAAS,QAAQ,WACjB,UAAU,iBAAiB,SAAS,gBAClC,sBAAsB,UAAU,gBACjC,UAAU,UAAU,SAAS;EAIhC,QACE,iCACM,wBACJ,SAAS,SACT,QAAQ,IAAI,OAAO,mBAChB,iBAAiB,SAAS,SAAS,QAAQ,IAAI,OAAO,mBAAmB,eAE9E,aAAa,kBAAkB,UAAU,cAAc,SAAS,eAAe,kBAC9E,gBAAgB;UASX"}
|
package/dist/bun.mjs
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { t as Layer } from "./layer-D16GKxuX.mjs";
|
|
2
|
+
import { t as WebEffect } from "./web-Bq3MfMrj.mjs";
|
|
3
|
+
//#region src/bun/index.ts
|
|
4
|
+
const runWebEffect = (runtime, request, program, options) => {
|
|
5
|
+
return WebEffect.handle(runtime, request, program, options);
|
|
6
|
+
};
|
|
7
|
+
/** Bind a Runtime and WebEffect policy to a Bun.serve fetch handler. */
|
|
8
|
+
var BunEffect = class BunEffect {
|
|
9
|
+
runtime;
|
|
10
|
+
onSuccess;
|
|
11
|
+
onFailure;
|
|
12
|
+
requestLayer;
|
|
13
|
+
constructor(runtime, options) {
|
|
14
|
+
this.runtime = runtime;
|
|
15
|
+
this.onSuccess = options.onSuccess;
|
|
16
|
+
this.onFailure = options.onFailure;
|
|
17
|
+
this.requestLayer = options.requestLayer;
|
|
18
|
+
}
|
|
19
|
+
static make(runtime, options) {
|
|
20
|
+
return new BunEffect(runtime, options ?? {});
|
|
21
|
+
}
|
|
22
|
+
handler(makeProgram) {
|
|
23
|
+
return async (request, server) => {
|
|
24
|
+
const program = (() => makeProgram(request, server)());
|
|
25
|
+
return runWebEffect(this.runtime, request, program, this.makeWebOptions(request));
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
makeWebOptions(request) {
|
|
29
|
+
const options = { requestLayer: this.requestLayer ?? (() => Layer.empty) };
|
|
30
|
+
const onSuccess = this.onSuccess;
|
|
31
|
+
if (onSuccess !== void 0) options.onSuccess = (result) => onSuccess(result, request);
|
|
32
|
+
const onFailure = this.onFailure;
|
|
33
|
+
if (onFailure !== void 0) options.onFailure = (error) => onFailure(error, request);
|
|
34
|
+
return options;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
38
|
+
export { BunEffect };
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=bun.mjs.map
|
package/dist/bun.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bun.mjs","names":[],"sources":["../src/bun/index.ts"],"sourcesContent":["import { Layer } from '../layer'\nimport { WebEffect } from '../web'\nimport type { AnyService } from '../service'\nimport type { LayerInput } from '../layer/inference'\nimport type { Runtime } from '../runtime'\nimport type {\n BunAnyProgram,\n BunEffectOptions,\n BunFetchHandler,\n BunHandlerProgram,\n BunRequestLayerChecks\n} from './types'\nimport type { DefaultRequestLayer, WebEffectOptions } from '../web/types'\n\nconst runWebEffect = <Provided extends AnyService>(\n runtime: Runtime<Provided>,\n request: Request,\n program: BunAnyProgram,\n options: WebEffectOptions<unknown, LayerInput, unknown>\n): Promise<Response> => {\n // SAFETY: BunHandlerFactory validates the Program; WebEffect owns this erased request boundary.\n return WebEffect.handle(runtime, request, program, options as never)\n}\n\ntype BunHandlerFactory<\n Provided extends AnyService,\n RequestLayer extends LayerInput,\n Failure,\n WebSocketData,\n ProgramFactory extends (request: Request, server: Bun.Server<WebSocketData>) => BunAnyProgram\n> = ProgramFactory &\n ([ReturnType<ProgramFactory>] extends [\n BunHandlerProgram<Provided, RequestLayer, ReturnType<ProgramFactory>, Failure>\n ]\n ? unknown\n : (\n request: Request,\n server: Bun.Server<WebSocketData>\n ) => BunHandlerProgram<Provided, RequestLayer, ReturnType<ProgramFactory>, Failure>)\n\n/** Bind a Runtime and WebEffect policy to a Bun.serve fetch handler. */\nexport class BunEffect<\n Provided extends AnyService = never,\n Failure = unknown,\n RequestLayer extends LayerInput = DefaultRequestLayer\n> {\n readonly runtime: Runtime<Provided>\n\n private readonly onSuccess: BunEffectOptions<Failure, RequestLayer>['onSuccess']\n\n private readonly onFailure: BunEffectOptions<Failure, RequestLayer>['onFailure']\n\n private readonly requestLayer: BunEffectOptions<Failure, RequestLayer>['requestLayer']\n\n private constructor(\n runtime: Runtime<Provided>,\n options: BunEffectOptions<Failure, RequestLayer>\n ) {\n this.runtime = runtime\n this.onSuccess = options.onSuccess\n this.onFailure = options.onFailure\n this.requestLayer = options.requestLayer\n }\n\n static make<\n Provided extends AnyService,\n Failure = unknown,\n RequestLayer extends LayerInput = DefaultRequestLayer\n >(\n runtime: Runtime<Provided>,\n options?: BunEffectOptions<Failure, RequestLayer> &\n BunRequestLayerChecks<Provided, RequestLayer>\n ): BunEffect<Provided, Failure, RequestLayer> {\n return new BunEffect(runtime, options ?? {})\n }\n\n handler<\n WebSocketData = undefined,\n const ProgramFactory extends (\n request: Request,\n server: Bun.Server<WebSocketData>\n ) => BunAnyProgram = (request: Request, server: Bun.Server<WebSocketData>) => BunAnyProgram\n >(\n makeProgram: BunHandlerFactory<Provided, RequestLayer, Failure, WebSocketData, ProgramFactory>\n ): BunFetchHandler<WebSocketData> {\n return async (request, server) => {\n // SAFETY: the public factory check validates the returned Program before this erased wrapper.\n const program = (() => makeProgram(request, server)()) as BunAnyProgram\n\n return runWebEffect(this.runtime, request, program, this.makeWebOptions(request))\n }\n }\n\n private makeWebOptions(request: Request): WebEffectOptions<unknown, LayerInput, unknown> & {\n readonly requestLayer: (request: Request) => LayerInput\n } {\n type MutableWebOptions = {\n -readonly [Key in keyof WebEffectOptions<unknown, LayerInput, unknown>]?: WebEffectOptions<\n unknown,\n LayerInput,\n unknown\n >[Key]\n }\n const options: MutableWebOptions & {\n requestLayer: (request: Request) => LayerInput\n } = {\n requestLayer: this.requestLayer ?? (() => Layer.empty)\n }\n\n const onSuccess = this.onSuccess\n\n if (onSuccess !== undefined) {\n options.onSuccess = (result) => onSuccess(result, request)\n }\n\n const onFailure = this.onFailure\n\n if (onFailure !== undefined) {\n // SAFETY: the public handler check ties this wrapper to the configured Failure channel.\n options.onFailure = (error) => onFailure(error as Failure, request)\n }\n\n return options\n }\n}\n\nexport type {\n BunEffectOptions,\n BunEffectProgram,\n BunFetchHandler,\n BunServer,\n ResponseLike\n} from './types'\n"],"mappings":";;;AAcA,MAAM,gBACJ,SACA,SACA,SACA,YACsB;CAEtB,OAAO,UAAU,OAAO,SAAS,SAAS,SAAS,OAAgB;AACrE;;AAmBA,IAAa,YAAb,MAAa,UAIX;CACA;CAEA;CAEA;CAEA;CAEA,YACE,SACA,SACA;EACA,KAAK,UAAU;EACf,KAAK,YAAY,QAAQ;EACzB,KAAK,YAAY,QAAQ;EACzB,KAAK,eAAe,QAAQ;CAC9B;CAEA,OAAO,KAKL,SACA,SAE4C;EAC5C,OAAO,IAAI,UAAU,SAAS,WAAW,CAAC,CAAC;CAC7C;CAEA,QAOE,aACgC;EAChC,OAAO,OAAO,SAAS,WAAW;GAEhC,MAAM,iBAAiB,YAAY,SAAS,MAAM,CAAC,CAAC;GAEpD,OAAO,aAAa,KAAK,SAAS,SAAS,SAAS,KAAK,eAAe,OAAO,CAAC;EAClF;CACF;CAEA,eAAuB,SAErB;EAQA,MAAM,UAEF,EACF,cAAc,KAAK,uBAAuB,MAAM,OAClD;EAEA,MAAM,YAAY,KAAK;EAEvB,IAAI,cAAc,KAAA,GAChB,QAAQ,aAAa,WAAW,UAAU,QAAQ,OAAO;EAG3D,MAAM,YAAY,KAAK;EAEvB,IAAI,cAAc,KAAA,GAEhB,QAAQ,aAAa,UAAU,UAAU,OAAkB,OAAO;EAGpE,OAAO;CACT;AACF"}
|
|
@@ -39,11 +39,13 @@ const setRuntimeContextLineage = (context) => {
|
|
|
39
39
|
const hasPathPrefix = (parent, child) => child.length >= parent.length && parent.every((token, index) => child[index] === token);
|
|
40
40
|
/** Recognize contexts created by a nested Service, Scope, or Layer operation. */
|
|
41
41
|
const isDerivedRuntimeContext = (parent, child) => parent.resolver !== void 0 && child.resolver === parent.resolver && parent.resolutionPath.length > 0 && hasPathPrefix(parent.resolutionPath, child.resolutionPath) && (child.resolutionPath.length > parent.resolutionPath.length || child.scope !== parent.scope);
|
|
42
|
-
function makeRuntimeContext(resolver, scope, resolutionPath, signal, parent) {
|
|
42
|
+
function makeRuntimeContext(resolver, scope, resolutionPath, signal, parent, executionId) {
|
|
43
43
|
const context = { resolutionPath };
|
|
44
|
+
const ownerExecutionId = executionId ?? parent?.executionId;
|
|
44
45
|
if (resolver !== void 0) Object.assign(context, { resolver });
|
|
45
46
|
if (scope !== void 0) Object.assign(context, { scope });
|
|
46
47
|
if (signal !== void 0) Object.assign(context, { signal });
|
|
48
|
+
if (ownerExecutionId !== void 0) Object.assign(context, { executionId: ownerExecutionId });
|
|
47
49
|
if (parent !== void 0) inheritRuntimeContextLineage(context, parent);
|
|
48
50
|
return context;
|
|
49
51
|
}
|
|
@@ -149,4 +151,4 @@ const runRuntimeContext = (storage, context, program) => {
|
|
|
149
151
|
//#endregion
|
|
150
152
|
export { getRuntimeContextLineage as a, isRuntimeContextFrameCarrierInstalled as c, setDefaultRuntimeContextStorage as d, setRuntimeContextFrameCarrier as f, RuntimeContextOverlapError as g, RuntimeContextNotConfiguredError as h, getRuntimeContext as i, makeRuntimeContext as l, withActiveRuntimeContextStorage as m, currentRuntimeContext as n, inheritRuntimeContextLineage as o, setRuntimeContextLineage as p, currentRuntimeContextFrame as r, isDerivedRuntimeContext as s, activeRuntimeContextStorage as t, runRuntimeContext as u };
|
|
151
153
|
|
|
152
|
-
//# sourceMappingURL=context-
|
|
154
|
+
//# sourceMappingURL=context-BphfFUMO.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-BphfFUMO.mjs","names":[],"sources":["../src/runtime/errors.ts","../src/runtime/context.ts"],"sourcesContent":["/** Thrown when no RuntimeContext is active in the selected storage. */\nexport class RuntimeContextNotConfiguredError extends Error {\n constructor() {\n super('No RuntimeContext is available in the current execution context')\n\n this.name = 'RuntimeContextNotConfiguredError'\n }\n}\n\n/** Thrown when ExplicitRuntimeContextStorage cannot safely overlap lineages. */\nexport class RuntimeContextOverlapError extends Error {\n constructor() {\n super(\n 'ExplicitRuntimeContextStorage does not support overlapping root or derived context runs; use NodeRuntimeContextStorage for concurrent async branches'\n )\n\n this.name = 'RuntimeContextOverlapError'\n }\n}\n","import { RuntimeContextNotConfiguredError } from './errors'\n\nimport type { Scope } from '../scope/scope'\nimport type { AnyServiceToken, ServiceResolver } from '../service'\nimport { isPromiseLike } from '../utils/runtime'\n\n/** Contextual state shared by Service, Scope and Layer resolution. */\nexport interface RuntimeContext {\n readonly resolver?: ServiceResolver\n readonly scope?: Scope\n readonly signal?: AbortSignal\n readonly resolutionPath: readonly AnyServiceToken[]\n /** Runtime execution owner, omitted for warmup and Runtime-root activity. */\n readonly executionId?: string\n}\n\n/** A context with both channels required by a Runtime execution. */\nexport type CompleteRuntimeContext = RuntimeContext & {\n readonly resolver: ServiceResolver\n readonly scope: Scope\n}\n\n/** Host-specific storage for the current RuntimeContext. */\nexport interface RuntimeContextStorage {\n run<A>(context: RuntimeContext, program: () => A): A\n current(): RuntimeContext\n}\n\nconst unconfiguredRuntimeContextStorage: RuntimeContextStorage = {\n run: (_context, program) => program(),\n current: () => {\n throw new RuntimeContextNotConfiguredError()\n }\n}\n\nconst contextLineages = new WeakMap<object, RuntimeContext>()\n\n/** Associate a derived context with the root context of its execution lineage. */\nexport const inheritRuntimeContextLineage = (\n context: RuntimeContext,\n parent: RuntimeContext\n): RuntimeContext => {\n const lineage = contextLineages.get(parent) ?? parent\n contextLineages.set(context, lineage)\n return context\n}\n\n/** Return the root context associated with a contextual value, when known. */\nexport const getRuntimeContextLineage = (context: RuntimeContext): RuntimeContext | undefined =>\n contextLineages.get(context)\n\n/** Associate a newly-entered root context with itself. */\nexport const setRuntimeContextLineage = (context: RuntimeContext): RuntimeContext => {\n contextLineages.set(context, context)\n return context\n}\n\nconst hasPathPrefix = (\n parent: readonly AnyServiceToken[],\n child: readonly AnyServiceToken[]\n): boolean =>\n child.length >= parent.length && parent.every((token, index) => child[index] === token)\n\n/** Recognize contexts created by a nested Service, Scope, or Layer operation. */\nexport const isDerivedRuntimeContext = (parent: RuntimeContext, child: RuntimeContext): boolean =>\n parent.resolver !== undefined &&\n child.resolver === parent.resolver &&\n parent.resolutionPath.length > 0 &&\n hasPathPrefix(parent.resolutionPath, child.resolutionPath) &&\n (child.resolutionPath.length > parent.resolutionPath.length || child.scope !== parent.scope)\n\n/** Build a context while retaining only channels that are actually available. */\nexport function makeRuntimeContext(\n resolver: ServiceResolver,\n scope: Scope,\n resolutionPath: readonly AnyServiceToken[],\n signal: AbortSignal | undefined,\n parent?: RuntimeContext,\n executionId?: string\n): CompleteRuntimeContext\nexport function makeRuntimeContext(\n resolver: ServiceResolver | undefined,\n scope: Scope | undefined,\n resolutionPath: readonly AnyServiceToken[],\n signal: AbortSignal | undefined,\n parent?: RuntimeContext,\n executionId?: string\n): RuntimeContext\nexport function makeRuntimeContext(\n resolver: ServiceResolver | undefined,\n scope: Scope | undefined,\n resolutionPath: readonly AnyServiceToken[],\n signal: AbortSignal | undefined,\n parent?: RuntimeContext,\n executionId?: string\n): RuntimeContext {\n const context: RuntimeContext = { resolutionPath }\n const ownerExecutionId = executionId ?? parent?.executionId\n\n if (resolver !== undefined) {\n Object.assign(context, { resolver })\n }\n\n if (scope !== undefined) {\n Object.assign(context, { scope })\n }\n\n if (signal !== undefined) {\n Object.assign(context, { signal })\n }\n\n if (ownerExecutionId !== undefined) {\n Object.assign(context, { executionId: ownerExecutionId })\n }\n\n if (parent !== undefined) {\n inheritRuntimeContextLineage(context, parent)\n }\n\n return context\n}\n\n/** A context frame selected for one logical Runtime execution branch. */\nexport type ActiveRuntimeContextFrame = {\n readonly storage: RuntimeContextStorage\n readonly context: RuntimeContext\n readonly parent?: ActiveRuntimeContextFrame\n}\n\n/** Host-provided propagation for Runtime context frames. */\nexport interface RuntimeContextFrameCarrier {\n run<A>(frame: ActiveRuntimeContextFrame, program: () => A): A\n current(): ActiveRuntimeContextFrame | undefined\n}\n\nlet defaultStorage = unconfiguredRuntimeContextStorage\nlet fallbackFrame: ActiveRuntimeContextFrame | undefined\nconst fallbackFrames = new Set<ActiveRuntimeContextFrame>()\n\nconst settleWithRuntimeStorage = <A>(value: A, restore: () => void): A => {\n let promiseLike: boolean\n\n try {\n promiseLike = isPromiseLike(value)\n } catch (cause) {\n restore()\n throw cause\n }\n\n if (!promiseLike) {\n restore()\n return value\n }\n\n try {\n // SAFETY: PromiseLike values are normalized only to restore the storage after settlement; the public generic retains the callback's awaited shape.\n return Promise.resolve(value).then(\n (resolved) => {\n restore()\n return resolved\n },\n (cause) => {\n restore()\n throw cause\n }\n ) as A\n } catch (cause) {\n restore()\n throw cause\n }\n}\n\nconst restoreFallbackFrame = (frame: ActiveRuntimeContextFrame): void => {\n fallbackFrames.delete(frame)\n\n if (fallbackFrame !== frame) {\n return\n }\n\n let parent = frame.parent\n\n while (parent !== undefined && !fallbackFrames.has(parent)) {\n parent = parent.parent\n }\n\n fallbackFrame = parent\n}\n\nconst fallbackRuntimeContextFrameCarrier: RuntimeContextFrameCarrier = {\n run<A>(frame: ActiveRuntimeContextFrame, program: () => A): A {\n fallbackFrames.add(frame)\n fallbackFrame = frame\n const restore = (): void => restoreFallbackFrame(frame)\n\n try {\n return settleWithRuntimeStorage(program(), restore)\n } catch (cause) {\n restore()\n throw cause\n }\n },\n\n current: () => fallbackFrame\n}\n\nlet runtimeContextFrameCarrier: RuntimeContextFrameCarrier = fallbackRuntimeContextFrameCarrier\n\n/** Install host async-context propagation for Runtime context frames. */\nexport const setRuntimeContextFrameCarrier = (carrier: RuntimeContextFrameCarrier): void => {\n runtimeContextFrameCarrier = carrier\n}\n\n/** Return whether a host async-context carrier has been installed. */\nexport const isRuntimeContextFrameCarrierInstalled = (): boolean =>\n runtimeContextFrameCarrier !== fallbackRuntimeContextFrameCarrier\n\n/** Return the frame associated with the executing callback. */\nexport const currentRuntimeContextFrame = (): ActiveRuntimeContextFrame | undefined =>\n runtimeContextFrameCarrier.current()\n\n/** Install the host default used by the main Runtime entrypoint. */\nexport const setDefaultRuntimeContextStorage = (storage: RuntimeContextStorage): void => {\n defaultStorage = storage\n}\n\n/** Return the storage currently associated with the executing callback. */\nexport const activeRuntimeContextStorage = (): RuntimeContextStorage =>\n currentRuntimeContextFrame()?.storage ?? defaultStorage\n\n/** Return the active context, or undefined when the storage has not been entered. */\nexport const getRuntimeContext = (\n storage: RuntimeContextStorage = activeRuntimeContextStorage()\n): RuntimeContext | undefined => {\n const frame = currentRuntimeContextFrame()\n\n if (frame?.storage === storage) {\n return frame.context\n }\n\n try {\n return storage.current()\n } catch (cause) {\n if (cause instanceof RuntimeContextNotConfiguredError) {\n return undefined\n }\n\n throw cause\n }\n}\n\n/** Return the active context or throw the storage's standard missing-context error. */\nexport const currentRuntimeContext = (): RuntimeContext => {\n const frame = currentRuntimeContextFrame()\n\n return frame?.context ?? defaultStorage.current()\n}\n\n/** Keep a storage discoverable to Service and Scope compatibility bridges. */\nexport const withActiveRuntimeContextStorage = <A>(\n storage: RuntimeContextStorage,\n context: RuntimeContext,\n program: () => A\n): A => {\n const current = currentRuntimeContextFrame()\n\n if (current?.storage === storage && current.context === context) {\n return program()\n }\n\n const frame: ActiveRuntimeContextFrame =\n current === undefined ? { storage, context } : { storage, context, parent: current }\n\n return runtimeContextFrameCarrier.run(frame, program)\n}\n\n/** Run a callback in a context while keeping the selected storage discoverable to bridges. */\nexport const runRuntimeContext = <A>(\n storage: RuntimeContextStorage,\n context: RuntimeContext,\n program: () => A\n): A => {\n const current = getRuntimeContext(storage)\n const contextual =\n current !== undefined && isDerivedRuntimeContext(current, context)\n ? inheritRuntimeContextLineage(context, current)\n : context\n\n return storage.run(contextual, () =>\n withActiveRuntimeContextStorage(storage, contextual, program)\n )\n}\n"],"mappings":";;;AACA,IAAa,mCAAb,cAAsD,MAAM;CAC1D,cAAc;EACZ,MAAM,iEAAiE;EAEvE,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,6BAAb,cAAgD,MAAM;CACpD,cAAc;EACZ,MACE,sJACF;EAEA,KAAK,OAAO;CACd;AACF;;;ACUA,MAAM,oCAA2D;CAC/D,MAAM,UAAU,YAAY,QAAQ;CACpC,eAAe;EACb,MAAM,IAAI,iCAAiC;CAC7C;AACF;AAEA,MAAM,kCAAkB,IAAI,QAAgC;;AAG5D,MAAa,gCACX,SACA,WACmB;CACnB,MAAM,UAAU,gBAAgB,IAAI,MAAM,KAAK;CAC/C,gBAAgB,IAAI,SAAS,OAAO;CACpC,OAAO;AACT;;AAGA,MAAa,4BAA4B,YACvC,gBAAgB,IAAI,OAAO;;AAG7B,MAAa,4BAA4B,YAA4C;CACnF,gBAAgB,IAAI,SAAS,OAAO;CACpC,OAAO;AACT;AAEA,MAAM,iBACJ,QACA,UAEA,MAAM,UAAU,OAAO,UAAU,OAAO,OAAO,OAAO,UAAU,MAAM,WAAW,KAAK;;AAGxF,MAAa,2BAA2B,QAAwB,UAC9D,OAAO,aAAa,KAAA,KACpB,MAAM,aAAa,OAAO,YAC1B,OAAO,eAAe,SAAS,KAC/B,cAAc,OAAO,gBAAgB,MAAM,cAAc,MACxD,MAAM,eAAe,SAAS,OAAO,eAAe,UAAU,MAAM,UAAU,OAAO;AAmBxF,SAAgB,mBACd,UACA,OACA,gBACA,QACA,QACA,aACgB;CAChB,MAAM,UAA0B,EAAE,eAAe;CACjD,MAAM,mBAAmB,eAAe,QAAQ;CAEhD,IAAI,aAAa,KAAA,GACf,OAAO,OAAO,SAAS,EAAE,SAAS,CAAC;CAGrC,IAAI,UAAU,KAAA,GACZ,OAAO,OAAO,SAAS,EAAE,MAAM,CAAC;CAGlC,IAAI,WAAW,KAAA,GACb,OAAO,OAAO,SAAS,EAAE,OAAO,CAAC;CAGnC,IAAI,qBAAqB,KAAA,GACvB,OAAO,OAAO,SAAS,EAAE,aAAa,iBAAiB,CAAC;CAG1D,IAAI,WAAW,KAAA,GACb,6BAA6B,SAAS,MAAM;CAG9C,OAAO;AACT;AAeA,IAAI,iBAAiB;AACrB,IAAI;AACJ,MAAM,iCAAiB,IAAI,IAA+B;AAE1D,MAAM,4BAA+B,OAAU,YAA2B;CACxE,IAAI;CAEJ,IAAI;EACF,cAAc,cAAc,KAAK;CACnC,SAAS,OAAO;EACd,QAAQ;EACR,MAAM;CACR;CAEA,IAAI,CAAC,aAAa;EAChB,QAAQ;EACR,OAAO;CACT;CAEA,IAAI;EAEF,OAAO,QAAQ,QAAQ,KAAK,CAAC,CAAC,MAC3B,aAAa;GACZ,QAAQ;GACR,OAAO;EACT,IACC,UAAU;GACT,QAAQ;GACR,MAAM;EACR,CACF;CACF,SAAS,OAAO;EACd,QAAQ;EACR,MAAM;CACR;AACF;AAEA,MAAM,wBAAwB,UAA2C;CACvE,eAAe,OAAO,KAAK;CAE3B,IAAI,kBAAkB,OACpB;CAGF,IAAI,SAAS,MAAM;CAEnB,OAAO,WAAW,KAAA,KAAa,CAAC,eAAe,IAAI,MAAM,GACvD,SAAS,OAAO;CAGlB,gBAAgB;AAClB;AAEA,MAAM,qCAAiE;CACrE,IAAO,OAAkC,SAAqB;EAC5D,eAAe,IAAI,KAAK;EACxB,gBAAgB;EAChB,MAAM,gBAAsB,qBAAqB,KAAK;EAEtD,IAAI;GACF,OAAO,yBAAyB,QAAQ,GAAG,OAAO;EACpD,SAAS,OAAO;GACd,QAAQ;GACR,MAAM;EACR;CACF;CAEA,eAAe;AACjB;AAEA,IAAI,6BAAyD;;AAG7D,MAAa,iCAAiC,YAA8C;CAC1F,6BAA6B;AAC/B;;AAGA,MAAa,8CACX,+BAA+B;;AAGjC,MAAa,mCACX,2BAA2B,QAAQ;;AAGrC,MAAa,mCAAmC,YAAyC;CACvF,iBAAiB;AACnB;;AAGA,MAAa,oCACX,2BAA2B,CAAC,EAAE,WAAW;;AAG3C,MAAa,qBACX,UAAiC,4BAA4B,MAC9B;CAC/B,MAAM,QAAQ,2BAA2B;CAEzC,IAAI,OAAO,YAAY,SACrB,OAAO,MAAM;CAGf,IAAI;EACF,OAAO,QAAQ,QAAQ;CACzB,SAAS,OAAO;EACd,IAAI,iBAAiB,kCACnB;EAGF,MAAM;CACR;AACF;;AAGA,MAAa,8BAA8C;CAGzD,OAFc,2BAEH,CAAC,EAAE,WAAW,eAAe,QAAQ;AAClD;;AAGA,MAAa,mCACX,SACA,SACA,YACM;CACN,MAAM,UAAU,2BAA2B;CAE3C,IAAI,SAAS,YAAY,WAAW,QAAQ,YAAY,SACtD,OAAO,QAAQ;CAGjB,MAAM,QACJ,YAAY,KAAA,IAAY;EAAE;EAAS;CAAQ,IAAI;EAAE;EAAS;EAAS,QAAQ;CAAQ;CAErF,OAAO,2BAA2B,IAAI,OAAO,OAAO;AACtD;;AAGA,MAAa,qBACX,SACA,SACA,YACM;CACN,MAAM,UAAU,kBAAkB,OAAO;CACzC,MAAM,aACJ,YAAY,KAAA,KAAa,wBAAwB,SAAS,OAAO,IAC7D,6BAA6B,SAAS,OAAO,IAC7C;CAEN,OAAO,QAAQ,IAAI,kBACjB,gCAAgC,SAAS,YAAY,OAAO,CAC9D;AACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { H as ServiceToken, I as ServiceIdentity, b as Service, j as ServiceRequirement } from "./index-AiKM71-u.mjs";
|
|
2
|
+
import { A as ProviderEntry, x as LayerResult } from "./outcome-DI8LPIQ4.mjs";
|
|
3
|
+
import "./index-BodMy6rO.mjs";
|
|
4
|
+
//#region src/standard-services/current-request.d.ts
|
|
5
|
+
declare const CurrentRequest_base: (abstract new () => ServiceIdentity<"CurrentRequest">) & {
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly serviceTag: "CurrentRequest";
|
|
8
|
+
} & {
|
|
9
|
+
readonly of: Service.FactoryOf<CurrentRequest, "CurrentRequest">;
|
|
10
|
+
readonly [Symbol.asyncIterator]: (this: ServiceToken<"CurrentRequest", CurrentRequest & ServiceIdentity<"CurrentRequest">>) => AsyncGenerator<ServiceRequirement<CurrentRequest>, CurrentRequest, unknown>;
|
|
11
|
+
};
|
|
12
|
+
/** Execution-local request value carried by a normal Service provider. */
|
|
13
|
+
declare class CurrentRequest extends CurrentRequest_base {
|
|
14
|
+
readonly value: unknown;
|
|
15
|
+
readonly request: unknown;
|
|
16
|
+
constructor(value: unknown);
|
|
17
|
+
static layer(value: unknown): LayerResult<ProviderEntry<CurrentRequest, never>>;
|
|
18
|
+
}
|
|
19
|
+
declare const CurrentRequestLayer: (value: unknown) => LayerResult<ProviderEntry<CurrentRequest, never>>;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { CurrentRequestLayer as n, CurrentRequest as t };
|
|
22
|
+
//# sourceMappingURL=current-request-CIU7AHhF.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"current-request-CIU7AHhF.d.mts","names":[],"sources":["../src/standard-services/current-request.ts"],"mappings":";;;;;;;;;;;;cAIa,uBAAuB;WAIb;WAHZ;EAGY,YAAA;SAMd,MAAM,iBAAc,YAAA,cAAA;;cAMhB,sBAAuB,mBAAc,YAAA,cAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { n as Service, t as Layer } from "./layer-D16GKxuX.mjs";
|
|
2
|
+
//#region src/standard-services/current-request.ts
|
|
3
|
+
/** Execution-local request value carried by a normal Service provider. */
|
|
4
|
+
var CurrentRequest = class CurrentRequest extends Service()("CurrentRequest") {
|
|
5
|
+
value;
|
|
6
|
+
request;
|
|
7
|
+
constructor(value) {
|
|
8
|
+
super();
|
|
9
|
+
this.value = value;
|
|
10
|
+
this.request = value;
|
|
11
|
+
}
|
|
12
|
+
static layer(value) {
|
|
13
|
+
return Layer.succeed(CurrentRequest, new CurrentRequest(value));
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const CurrentRequestLayer = (value) => CurrentRequest.layer(value);
|
|
17
|
+
//#endregion
|
|
18
|
+
export { CurrentRequestLayer as n, CurrentRequest as t };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=current-request-DDKNyymv.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"current-request-DDKNyymv.mjs","names":[],"sources":["../src/standard-services/current-request.ts"],"sourcesContent":["import { Layer } from '../layer'\nimport { Service } from '../service'\n\n/** Execution-local request value carried by a normal Service provider. */\nexport class CurrentRequest extends Service<CurrentRequest>()('CurrentRequest') {\n readonly request: unknown\n\n // oxlint-disable-next-line anti-slop/no-unknown-parameters\n constructor(readonly value: unknown) {\n super()\n this.request = value\n }\n\n // oxlint-disable-next-line anti-slop/no-unknown-parameters\n static layer(value: unknown) {\n return Layer.succeed(CurrentRequest, new CurrentRequest(value))\n }\n}\n\n// oxlint-disable-next-line anti-slop/no-unknown-parameters\nexport const CurrentRequestLayer = (value: unknown) => CurrentRequest.layer(value)\n"],"mappings":";;;AAIA,IAAa,iBAAb,MAAa,uBAAuB,QAAwB,CAAC,CAAC,gBAAgB,CAAC,CAAC;CAIzD;CAHrB;CAGA,YAAY,OAAyB;EACnC,MAAM;EADa,KAAA,QAAA;EAEnB,KAAK,UAAU;CACjB;CAGA,OAAO,MAAM,OAAgB;EAC3B,OAAO,MAAM,QAAQ,gBAAgB,IAAI,eAAe,KAAK,CAAC;CAChE;AACF;AAGA,MAAa,uBAAuB,UAAmB,eAAe,MAAM,KAAK"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as setDefaultRuntimeContextStorage
|
|
2
|
-
import { n as nodeRuntimeContextStorage } from "./node-context-
|
|
1
|
+
import { d as setDefaultRuntimeContextStorage } from "./context-BphfFUMO.mjs";
|
|
2
|
+
import { n as nodeRuntimeContextStorage } from "./node-context-Ca18oNSg.mjs";
|
|
3
3
|
//#region src/runtime/default.ts
|
|
4
4
|
/** The Node/Bun storage used by the main Runtime entrypoint. */
|
|
5
5
|
const defaultRuntimeContextStorage = nodeRuntimeContextStorage;
|
|
@@ -52,54 +52,6 @@ const disposeResource = (resource) => {
|
|
|
52
52
|
return getDisposeFinalizer(resource)?.(SCOPE_SUCCESS);
|
|
53
53
|
};
|
|
54
54
|
//#endregion
|
|
55
|
-
|
|
56
|
-
const neverAbortedSignal = new AbortController().signal;
|
|
57
|
-
/** Link caller, Runtime and shutdown signals without owning the caller's controller. */
|
|
58
|
-
const linkAbortSignals = (...signals) => {
|
|
59
|
-
const active = signals.filter((signal) => signal !== void 0);
|
|
60
|
-
if (active.length === 0) return {
|
|
61
|
-
signal: neverAbortedSignal,
|
|
62
|
-
dispose: () => {}
|
|
63
|
-
};
|
|
64
|
-
if (active.length === 1) return {
|
|
65
|
-
signal: active[0],
|
|
66
|
-
dispose: () => {}
|
|
67
|
-
};
|
|
68
|
-
const controller = new AbortController();
|
|
69
|
-
const listeners = [];
|
|
70
|
-
let disposed = false;
|
|
71
|
-
const dispose = () => {
|
|
72
|
-
if (disposed) return;
|
|
73
|
-
disposed = true;
|
|
74
|
-
for (const [source, listener] of listeners) source.removeEventListener("abort", listener);
|
|
75
|
-
listeners.length = 0;
|
|
76
|
-
};
|
|
77
|
-
const abortFrom = (source) => {
|
|
78
|
-
if (controller.signal.aborted) return;
|
|
79
|
-
controller.abort(source.reason);
|
|
80
|
-
dispose();
|
|
81
|
-
};
|
|
82
|
-
for (const source of active) {
|
|
83
|
-
if (source.aborted) {
|
|
84
|
-
abortFrom(source);
|
|
85
|
-
break;
|
|
86
|
-
}
|
|
87
|
-
const listener = () => abortFrom(source);
|
|
88
|
-
listeners.push([source, listener]);
|
|
89
|
-
source.addEventListener("abort", listener, { once: true });
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
signal: controller.signal,
|
|
93
|
-
dispose
|
|
94
|
-
};
|
|
95
|
-
};
|
|
96
|
-
/** Return the current cooperative-cancellation signal. */
|
|
97
|
-
const currentAbortSignal = () => currentRuntimeContext().signal ?? neverAbortedSignal;
|
|
98
|
-
/** Yieldable access to the signal of the current Runtime execution. */
|
|
99
|
-
const CurrentAbortSignal = { *[Symbol.iterator]() {
|
|
100
|
-
return currentAbortSignal();
|
|
101
|
-
} };
|
|
102
|
-
//#endregion
|
|
103
|
-
export { ResourceNotDisposableError as a, ScopeRuntimeNotConfiguredError as c, getDisposeFinalizer as i, defaultRuntimeContextStorage as l, linkAbortSignals as n, ScopeCloseError as o, disposeResource as r, ScopeClosedError as s, CurrentAbortSignal as t };
|
|
55
|
+
export { ScopeClosedError as a, ScopeCloseError as i, getDisposeFinalizer as n, ScopeRuntimeNotConfiguredError as o, ResourceNotDisposableError as r, defaultRuntimeContextStorage as s, disposeResource as t };
|
|
104
56
|
|
|
105
|
-
//# sourceMappingURL=
|
|
57
|
+
//# sourceMappingURL=disposable-CP-Q2H3l.mjs.map
|