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.
Files changed (87) hide show
  1. package/README.md +327 -7
  2. package/dist/adapters/iti.d.mts +3 -3
  3. package/dist/bun.d.mts +43 -0
  4. package/dist/bun.d.mts.map +1 -0
  5. package/dist/bun.mjs +40 -0
  6. package/dist/bun.mjs.map +1 -0
  7. package/dist/{context-BUEf1qjL.mjs → context-BphfFUMO.mjs} +4 -2
  8. package/dist/context-BphfFUMO.mjs.map +1 -0
  9. package/dist/current-request-CIU7AHhF.d.mts +22 -0
  10. package/dist/current-request-CIU7AHhF.d.mts.map +1 -0
  11. package/dist/current-request-DDKNyymv.mjs +20 -0
  12. package/dist/current-request-DDKNyymv.mjs.map +1 -0
  13. package/dist/{signal-D2UTcaaG.mjs → disposable-CP-Q2H3l.mjs} +4 -52
  14. package/dist/disposable-CP-Q2H3l.mjs.map +1 -0
  15. package/dist/{effect-CK4YZaX0.mjs → effect-CPdV7Yv8.mjs} +2 -2
  16. package/dist/{effect-CK4YZaX0.mjs.map → effect-CPdV7Yv8.mjs.map} +1 -1
  17. package/dist/hono.d.mts +7 -5
  18. package/dist/hono.d.mts.map +1 -1
  19. package/dist/hono.mjs +88 -30
  20. package/dist/hono.mjs.map +1 -1
  21. package/dist/{index-heuaRmXR.d.mts → index-AiKM71-u.d.mts} +3 -1
  22. package/dist/{index-heuaRmXR.d.mts.map → index-AiKM71-u.d.mts.map} +1 -1
  23. package/dist/{index-GYJ4qm9K.d.mts → index-BodMy6rO.d.mts} +6 -5
  24. package/dist/index-BodMy6rO.d.mts.map +1 -0
  25. package/dist/{index-CX6iAoCB.d.mts → index-CCi07kUw.d.mts} +2 -2
  26. package/dist/{index-CX6iAoCB.d.mts.map → index-CCi07kUw.d.mts.map} +1 -1
  27. package/dist/{index-BMdU_Z72.d.mts → index-DAKn0qHk.d.mts} +4 -3
  28. package/dist/index-DAKn0qHk.d.mts.map +1 -0
  29. package/dist/{index-B1nH4luq.d.mts → index-cXgyMa0v.d.mts} +6 -20
  30. package/dist/index-cXgyMa0v.d.mts.map +1 -0
  31. package/dist/index.d.mts +6 -5
  32. package/dist/index.mjs +7 -6
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/{layer-D56fRdLt.mjs → layer-D16GKxuX.mjs} +4 -4
  35. package/dist/layer-D16GKxuX.mjs.map +1 -0
  36. package/dist/next.d.mts +116 -0
  37. package/dist/next.d.mts.map +1 -0
  38. package/dist/next.mjs +68 -0
  39. package/dist/next.mjs.map +1 -0
  40. package/dist/{node-context-lggRF4bR.mjs → node-context-Ca18oNSg.mjs} +2 -2
  41. package/dist/{node-context-lggRF4bR.mjs.map → node-context-Ca18oNSg.mjs.map} +1 -1
  42. package/dist/{node-context-DWsCUBRa.d.mts → node-context-DczjAcrX.d.mts} +2 -2
  43. package/dist/{node-context-DWsCUBRa.d.mts.map → node-context-DczjAcrX.d.mts.map} +1 -1
  44. package/dist/node.d.mts +4 -4
  45. package/dist/node.mjs +4 -4
  46. package/dist/observer-9nhbL7Pr.d.mts +68 -0
  47. package/dist/observer-9nhbL7Pr.d.mts.map +1 -0
  48. package/dist/opentelemetry.d.mts +94 -0
  49. package/dist/opentelemetry.d.mts.map +1 -0
  50. package/dist/opentelemetry.mjs +453 -0
  51. package/dist/opentelemetry.mjs.map +1 -0
  52. package/dist/{outcome-CB43bnFW.d.mts → outcome-DI8LPIQ4.d.mts} +14 -69
  53. package/dist/outcome-DI8LPIQ4.d.mts.map +1 -0
  54. package/dist/{program-metadata-DhQCCirO.mjs → program-metadata-BxjGkT17.mjs} +3 -3
  55. package/dist/{program-metadata-DhQCCirO.mjs.map → program-metadata-BxjGkT17.mjs.map} +1 -1
  56. package/dist/runtime/explicit.d.mts +1 -1
  57. package/dist/runtime/explicit.mjs +1 -1
  58. package/dist/runtime/node.d.mts +2 -2
  59. package/dist/runtime/node.mjs +2 -2
  60. package/dist/{runtime-CBMrX8Wl.mjs → runtime-C_55ofnL.mjs} +42 -27
  61. package/dist/runtime-C_55ofnL.mjs.map +1 -0
  62. package/dist/signal-nfgFyNCk.mjs +52 -0
  63. package/dist/signal-nfgFyNCk.mjs.map +1 -0
  64. package/dist/{standard-services-GBZ32tll.mjs → standard-services-vnGIafkS.mjs} +3 -17
  65. package/dist/standard-services-vnGIafkS.mjs.map +1 -0
  66. package/dist/standard-services.d.mts +3 -2
  67. package/dist/standard-services.mjs +3 -2
  68. package/dist/testing.d.mts +6 -5
  69. package/dist/testing.d.mts.map +1 -1
  70. package/dist/testing.mjs +6 -6
  71. package/dist/types-oihI-ESv.d.mts +54 -0
  72. package/dist/types-oihI-ESv.d.mts.map +1 -0
  73. package/dist/web-Bq3MfMrj.mjs +147 -0
  74. package/dist/web-Bq3MfMrj.mjs.map +1 -0
  75. package/dist/web.d.mts +47 -0
  76. package/dist/web.d.mts.map +1 -0
  77. package/dist/web.mjs +2 -0
  78. package/package.json +33 -2
  79. package/dist/context-BUEf1qjL.mjs.map +0 -1
  80. package/dist/index-B1nH4luq.d.mts.map +0 -1
  81. package/dist/index-BMdU_Z72.d.mts.map +0 -1
  82. package/dist/index-GYJ4qm9K.d.mts.map +0 -1
  83. package/dist/layer-D56fRdLt.mjs.map +0 -1
  84. package/dist/outcome-CB43bnFW.d.mts.map +0 -1
  85. package/dist/runtime-CBMrX8Wl.mjs.map +0 -1
  86. package/dist/signal-D2UTcaaG.mjs.map +0 -1
  87. 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. Execution events
348
- carry one matching `executionId`, the optional Program name, copied readonly
349
- attributes, and a monotonic `durationMs` measured through execution cleanup:
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 runs one Runtime execution and
524
- Scope around each request. Handlers can yield Services directly; the adapter
525
- provides `CurrentRequest`, forwards `Request.signal`, and converts Results to
526
- Responses in one policy:
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'
@@ -1,6 +1,6 @@
1
- import { N as AnyServiceToken } from "../index-heuaRmXR.mjs";
2
- import { S as LayerRegistration, b as LayerBackendDisposeOptions, y as LayerBackend } from "../outcome-CB43bnFW.mjs";
3
- import "../index-BMdU_Z72.mjs";
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
@@ -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-BUEf1qjL.mjs.map
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, n as currentRuntimeContext } from "./context-BUEf1qjL.mjs";
2
- import { n as nodeRuntimeContextStorage } from "./node-context-lggRF4bR.mjs";
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
- //#region src/runtime/signal.ts
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=signal-D2UTcaaG.mjs.map
57
+ //# sourceMappingURL=disposable-CP-Q2H3l.mjs.map