getborg 0.0.119 → 0.0.124

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 (103) hide show
  1. package/dist/{FetchHttpClient-C-jciW95.mjs → FetchHttpClient-DkBX_tvM.mjs} +814 -814
  2. package/dist/{FileSystem-NX0EtGtm.mjs → FileSystem-B8SvsKCB.mjs} +87 -18
  3. package/dist/{Mime-C6O17O_3.mjs → Mime-mwjBDTG5.mjs} +945 -945
  4. package/dist/{NodeHttpIncomingMessage-CylGKvlB.mjs → NodeHttpIncomingMessage-Caou0eJc.mjs} +3 -3
  5. package/dist/{NodeHttpServer-EarHJJzn.mjs → NodeHttpServer-CiwRW4qX.mjs} +7 -7
  6. package/dist/{NodePtyAdapter-C6ioPYk6.mjs → NodePtyAdapter-DCy0YCxP.mjs} +2 -2
  7. package/dist/{NodeServices-C18DO3cx.mjs → NodeServices-KA4IGVlf.mjs} +4 -4
  8. package/dist/{NodeSqliteClient-CWkKfsSo.mjs → NodeSqliteClient-y7W-gFvl.mjs} +3 -3
  9. package/dist/{NodeStream-1N7oXzTp.mjs → NodeStream-Cwt3mZYs.mjs} +2 -2
  10. package/dist/{SqlClient-Cusaqpaw.mjs → SqlClient-D-oF89aw.mjs} +2 -2
  11. package/dist/bin.mjs +29698 -21001
  12. package/dist/{borgTelemetryNode-CHLcRFOW.mjs → borgTelemetryNode-BTLPaUwA.mjs} +5 -5
  13. package/dist/client/.vite/manifest.json +396 -320
  14. package/dist/client/assets/{ArrowRight-CgvCTAzu.js → ArrowRight-D8u8fAtz.js} +2 -2
  15. package/dist/client/assets/{ArrowSquareOut-C1CwJQ7R.js → ArrowSquareOut-B_f6YUhV.js} +2 -2
  16. package/dist/client/assets/{ArrowsClockwise-CBwAQTtQ.js → ArrowsClockwise-DQYZ1Xbo.js} +2 -2
  17. package/dist/client/assets/{CaretLeft-Bk0n02vc.js → CaretLeft-CfrkuxuJ.js} +2 -2
  18. package/dist/client/assets/ChatMarkdown-Ch9PipMk.js +249 -0
  19. package/dist/client/assets/CircleNotch-BcVOnWaH.js +2 -0
  20. package/dist/client/assets/DesignWorkspace-CrijZIpE.js +3 -0
  21. package/dist/client/assets/DiffPanel-Bbs-arXF.js +2 -0
  22. package/dist/client/assets/DiffWorkerPoolProvider-B-AH2sbL.js +10 -0
  23. package/dist/client/assets/{DocxPreview-B7-febv_.js → DocxPreview-HXde7oD1.js} +4 -4
  24. package/dist/client/assets/FilePreviewPanel-DkspqFyX.js +2237 -0
  25. package/dist/client/assets/HtmlPreview-pfh_hRgS.js +2 -0
  26. package/dist/client/assets/{PdfPreview-W5mTp32l.js → PdfPreview-VSGe6F9I.js} +3 -3
  27. package/dist/client/assets/PptxPreview-CZZ5e7rI.js +3 -0
  28. package/dist/client/assets/PreviewPanel-C_WqPJu_.js +2 -0
  29. package/dist/client/assets/PullRequestCodeTab-DLajHhi9.js +6 -0
  30. package/dist/client/assets/PullRequestReactions-BJ4eU_08.js +12 -0
  31. package/dist/client/assets/{RightPanelResizeHandle-DBci-Ee2.js → RightPanelResizeHandle-XlC9gY5e.js} +2 -2
  32. package/dist/client/assets/VirtualizedFile-qiRlyNDc.js +2 -0
  33. package/dist/client/assets/XlsxPreview-BPtt3tW-.js +3 -0
  34. package/dist/client/assets/accountData-BKyjOPQm.js +16 -0
  35. package/dist/client/assets/assetUrls-33nMWFnF.js +2 -0
  36. package/dist/client/assets/assets-1BW7ZJgz.js +2 -0
  37. package/dist/client/assets/{browserHistoryStore-DLbnuO9R.js → browserHistoryStore-CEVJXGfr.js} +3 -3
  38. package/dist/client/assets/browserRecording-BavNt16V.js +2 -0
  39. package/dist/client/assets/clientAnalytics-ChPHl8_D.js +1 -0
  40. package/dist/client/assets/clientPersistenceStorage-CeJLSpQl.js +2 -0
  41. package/dist/client/assets/combobox-CQHB5X6j.js +2 -0
  42. package/dist/client/assets/composerMentionDrag-CdTT1rUK.js +2 -0
  43. package/dist/client/assets/designCanvas.logic-DduGt5E7.js +8 -0
  44. package/dist/client/assets/{designOpenFileContext-CCL9VKvQ.js → designOpenFileContext-CMKir5dG.js} +2 -2
  45. package/dist/client/assets/{diffFileContents-CgDa-z2d.js → diffFileContents-CHRsIT6_.js} +3 -3
  46. package/dist/client/assets/{empty-CLS3rXBc.js → empty-DUUjhkFh.js} +2 -2
  47. package/dist/client/assets/entities-BtD3_L53.js +2 -0
  48. package/dist/client/assets/followUpQueuePersistence-C_pFQCnT.js +1 -0
  49. package/dist/client/assets/{index-DnoL7z0M.js → index-DrITfTBh.js} +3 -3
  50. package/dist/client/assets/{input-BbliVf4z.js → input-CyCAHFxI.js} +2 -2
  51. package/dist/client/assets/{lib-CySB76JU.js → lib-BRpsbmNP.js} +2 -2
  52. package/dist/client/assets/main-Bi6AoLeM.js +167 -0
  53. package/dist/client/assets/main-C0iNAqq8.css +2 -0
  54. package/dist/client/assets/{pdf-CdULDwXT.js → pdf-C3xMIdpt.js} +2 -2
  55. package/dist/client/assets/popover-BXSj56CI.js +2 -0
  56. package/dist/client/assets/pptxDocument-BnTLF4HV.js +3 -0
  57. package/dist/client/assets/projectFilesQueryState-Cs5skZOc.js +2 -0
  58. package/dist/client/assets/queries-BevoHPqY.js +2 -0
  59. package/dist/client/assets/{scroll-area-BW5o0Izf.js → scroll-area-DAaT-DGF.js} +36 -36
  60. package/dist/client/assets/session-Dmu9Hk5C.js +68 -0
  61. package/dist/client/assets/spinner-K3N_kbJr.js +2 -0
  62. package/dist/client/assets/textarea-BT0tVWKM.js +2 -0
  63. package/dist/client/assets/{toggle-DwBa6pBo.js → toggle-Sui8J_p3.js} +2 -2
  64. package/dist/client/assets/toggle-group-BDgfPfOF.js +2 -0
  65. package/dist/client/assets/useSettings-GEQSU1F5.js +5 -0
  66. package/dist/client/assets/{useWorkspaceMutationRefresh-DLI4brDf.js → useWorkspaceMutationRefresh-ApasU6PB.js} +2 -2
  67. package/dist/client/assets/utils-ClZ5OxbV.js +30 -0
  68. package/dist/client/assets/xlsxDocument-SRKfhPKH.js +2 -0
  69. package/dist/client/index.html +1 -1
  70. package/dist/service-launcher.mjs +1 -1
  71. package/package.json +2 -2
  72. package/dist/client/assets/ChatMarkdown-6kh9qKYW.js +0 -249
  73. package/dist/client/assets/DesignWorkspace-DPuyt5mw.js +0 -3
  74. package/dist/client/assets/DiffPanel-DzRhendL.js +0 -2
  75. package/dist/client/assets/DiffWorkerPoolProvider-BU7l1oGv.js +0 -10
  76. package/dist/client/assets/FilePreviewPanel-B3x43muL.js +0 -2231
  77. package/dist/client/assets/HtmlPreview-DY3PT2FT.js +0 -2
  78. package/dist/client/assets/PptxPreview-B02U0OAE.js +0 -3
  79. package/dist/client/assets/PreviewPanel-DhzZlEWJ.js +0 -2
  80. package/dist/client/assets/PullRequestCodeTab-CoB5ByAD.js +0 -6
  81. package/dist/client/assets/PullRequestReactions-DVg6Hz1F.js +0 -12
  82. package/dist/client/assets/VirtualizedFile-Bz5fGbNr.js +0 -2
  83. package/dist/client/assets/XlsxPreview-8ACeuCsx.js +0 -3
  84. package/dist/client/assets/accountData-C4ZvicpJ.js +0 -16
  85. package/dist/client/assets/assetUrls-CbeTQh3H.js +0 -2
  86. package/dist/client/assets/browserRecording-DpmNgRt_.js +0 -2
  87. package/dist/client/assets/clientPersistenceStorage-BlYjZvCd.js +0 -2
  88. package/dist/client/assets/combobox-CByZwSML.js +0 -2
  89. package/dist/client/assets/composerMentionDrag-1fGsNlV_.js +0 -2
  90. package/dist/client/assets/designCanvas.logic-BaQE_ItM.js +0 -8
  91. package/dist/client/assets/entities-DPi_gbtI.js +0 -2
  92. package/dist/client/assets/main-Ck7oK5At.js +0 -161
  93. package/dist/client/assets/main-YscGsfgO.css +0 -2
  94. package/dist/client/assets/popover-CFDsW-_z.js +0 -2
  95. package/dist/client/assets/pptxDocument-Dh-M0DL5.js +0 -3
  96. package/dist/client/assets/projectFilesQueryState-CmtzaSrb.js +0 -2
  97. package/dist/client/assets/queries-DRotn4pk.js +0 -2
  98. package/dist/client/assets/session-D3Szkrpk.js +0 -67
  99. package/dist/client/assets/spinner-DHhZaoFg.js +0 -2
  100. package/dist/client/assets/textarea-5SMJbr7K.js +0 -5
  101. package/dist/client/assets/toggle-group-BU7-0DcW.js +0 -2
  102. package/dist/client/assets/utils-DgzD4MA_.js +0 -30
  103. package/dist/client/assets/xlsxDocument-BMNJtufK.js +0 -2
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { B as prependUrl, St as fromInput$1, T as MaxBodySize, Tt as toString$1, Z as empty$1, _t as raw$1, at as empty$2, bt as uint8Array$1, ct as merge, dt as set, et as merge$1, ft as setAll, gt as jsonUnsafe$1, ht as jsonSchema, it as CurrentRedactedNames, l as mapRequest, lt as redact, ot as fromInput, pt as empty$3, r as HttpClient, st as fromRecordUnsafe, ut as remove, vt as stream$1, x as fromHeaders, yt as text$1 } from "./FetchHttpClient-C-jciW95.mjs";
4
- import { $r as ensuring, $s as fromReasons, $u as some, Ao as Clock, Bi as matchCauseEffect, Br as catchFilter, Ci as interrupt, Cr as acquireRelease, Cs as into, Cu as add, Di as log, Dr as andThen, Ds as makeUnsafe$1, Ei as isEffect, F as TaggedErrorClass, Fi as map$1, Fs as isFailure, Ft as optional, Ga as void_, Gd as constFalse, Gu as getOrUndefined, Hu as getOrElse, Ia as timeoutOrElse, Ii as mapEager, Io as TaggedError, Jd as constVoid, Ki as onExitPrimitive, Li as mapError, Lr as catchCause, M as String$1, Ms as failCause, Mu as merge$2, Oa as suspend, Pd as hasProperty, Po as Error$1, Qo as succeed, Rs as succeed$3, Rt as tag, Su as Service, Ta as succeed$1, Td as redact$1, Tu as get, Ua as updateContext, Uo as effectDiscard, Ur as catchTag, Va as uninterruptible, Vi as matchCauseEffectEager, Vo as effect, W as Union, Wc as makeSpanUnsafe, Ws as StackTrace, Xa as withLogSpan, Xd as dual, Xs as filterInterruptors, Xu as match, Ya as withFiber, Yd as constant, Yi as orDie, Zi as promise, Zo as provideMerge, Zr as die, Zu as none, bi as gen, c as Defect, ci as flatMapEager, cu as headUnsafe, d as ErrorClass, di as fnUntraced, dl as compose, ds as provide, ea as provideService, ei as exit, fd as PipeInspectableProto, fl as has, gs as _await, h as Int, ju as makeUnsafe$2, ka as sync, kr as annotateLogs, ku as getUnsafe, la as runFork, ln as isSchemaError, ms as TracerEnabled, nc as hasInterruptsOnly, ni as failCause$1, ou as empty$4, pc as makeDieReason, pl as toPredicate, qa as whileLoop, qc as reportCauseUnsafe, qd as constUndefined, qr as context, qu as isSome, ra as raceFirst, rs as Scope, rt as decodeUnknownEffect, si as flatMap, sl as ParentSpan, ss as closeUnsafe, ti as fail$1, ua as runForkWith, uc as isNoSuchElementError, us as makeUnsafe$3, uu as fail, v as Literals, xa as scopedWith, xd as Class, xu as Reference, ys as doneUnsafe, yu as succeed$2 } from "./Schema-CA_wFfhH.mjs";
5
- import { Z as run$1, _n as makeUnsafe$4, nt as runForEach, r as Size, t as FileSystem, vn as await_, xn as interruptAll, yn as getCurrent } from "./FileSystem-NX0EtGtm.mjs";
3
+ import { $ as fromRecordUnsafe, K as merge$1, M as prependUrl, Q as fromInput, U as empty$1, X as CurrentRedactedNames, Z as empty$2, _ as MaxBodySize, _t as toString$1, at as empty$3, ct as jsonUnsafe$1, dt as text$1, et as merge, ft as uint8Array$1, it as setAll, l as mapRequest, lt as raw$1, mt as fromInput$1, nt as remove, p as fromHeaders, r as HttpClient, rt as set, st as jsonSchema, tt as redact, ut as stream$1 } from "./FetchHttpClient-DkBX_tvM.mjs";
4
+ import { $r as ensuring, $s as fromReasons, $u as some, Ao as Clock, Bi as matchCauseEffect, Br as catchFilter, Ci as interrupt, Cr as acquireRelease, Cs as into, Cu as add, Di as log, Dr as andThen, Ds as makeUnsafe$1, Ei as isEffect, F as TaggedErrorClass, Fi as map$1, Fs as isFailure, Ft as optional, Ga as void_, Gd as constFalse, Gu as getOrUndefined, Hu as getOrElse, Ia as timeoutOrElse, Ii as mapEager, Io as TaggedError, Jd as constVoid, Ki as onExitPrimitive, Li as mapError, Lr as catchCause, M as String$1, Ms as failCause, Mu as merge$2, Oa as suspend, Pd as hasProperty, Po as Error$1, Qo as succeed$1, Rs as succeed$3, Rt as tag, Su as Service, Ta as succeed, Td as redact$1, Tu as get, Ua as updateContext, Uo as effectDiscard, Ur as catchTag, Va as uninterruptible, Vi as matchCauseEffectEager, Vo as effect, W as Union, Wc as makeSpanUnsafe, Ws as StackTrace, Xa as withLogSpan, Xd as dual, Xs as filterInterruptors, Xu as match, Ya as withFiber, Yd as constant, Yi as orDie, Zi as promise, Zo as provideMerge, Zr as die, Zu as none, bi as gen, c as Defect, ci as flatMapEager, cu as headUnsafe, d as ErrorClass, di as fnUntraced, dl as compose, ds as provide, ea as provideService, ei as exit, fd as PipeInspectableProto, fl as has, gs as _await, h as Int, ju as makeUnsafe$2, ka as sync, kr as annotateLogs, ku as getUnsafe, la as runFork, ln as isSchemaError, ms as TracerEnabled, nc as hasInterruptsOnly, ni as failCause$1, ou as empty$4, pc as makeDieReason, pl as toPredicate, qa as whileLoop, qc as reportCauseUnsafe, qd as constUndefined, qr as context, qu as isSome, ra as raceFirst, rs as Scope, rt as decodeUnknownEffect, si as flatMap, sl as ParentSpan, ss as closeUnsafe, ti as fail$1, ua as runForkWith, uc as isNoSuchElementError, us as makeUnsafe$3, uu as fail, v as Literals, xa as scopedWith, xd as Class, xu as Reference, ys as doneUnsafe, yu as succeed$2 } from "./Schema-CA_wFfhH.mjs";
5
+ import { Sn as interruptAll, Z as run$1, bn as getCurrent, nt as runForEach, r as Size, t as FileSystem, vn as makeUnsafe$4, yn as await_ } from "./FileSystem-B8SvsKCB.mjs";
6
6
  import { t as Path } from "./Path-ZDpyUmZ1.mjs";
7
7
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/UndefinedOr.js
8
8
  /**
@@ -20,102 +20,6 @@ import { t as Path } from "./Path-ZDpyUmZ1.mjs";
20
20
  */
21
21
  const map = /*#__PURE__*/ dual(2, (self, f) => self === void 0 ? void 0 : f(self));
22
22
  //#endregion
23
- //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/http/Etag.js
24
- /**
25
- * HTTP entity tag values and metadata-based generator layers.
26
- *
27
- * ETags are validators for a specific representation of a resource. Servers put
28
- * them in `ETag` response headers so clients and intermediaries can revalidate
29
- * cached content with `If-None-Match`, or protect writes with preconditions such
30
- * as `If-Match`.
31
- *
32
- * @since 4.0.0
33
- */
34
- /**
35
- * Formats an `Etag` as an HTTP header value, including quotes and the `W/` prefix for weak tags.
36
- *
37
- * @category converting
38
- * @since 4.0.0
39
- */
40
- const toString = (self) => {
41
- switch (self._tag) {
42
- case "Weak": return `W/"${self.value}"`;
43
- case "Strong": return `"${self.value}"`;
44
- }
45
- };
46
- /**
47
- * Service for generating ETags from filesystem file information or Web `File`-like metadata.
48
- *
49
- * @category services
50
- * @since 4.0.0
51
- */
52
- var Generator = class extends Service()("effect/http/Etag/Generator") {};
53
- const fromFileInfo = (info) => {
54
- const mtime = match(info.mtime, {
55
- onNone: () => "0",
56
- onSome: (mtime) => mtime.getTime().toString(16)
57
- });
58
- return `${info.size.toString(16)}-${mtime}`;
59
- };
60
- const fromFileWeb = (file) => {
61
- return `${file.size.toString(16)}-${file.lastModified.toString(16)}`;
62
- };
63
- /**
64
- * Layer that provides a `Generator` which produces strong ETags from file size
65
- * and modification time metadata.
66
- *
67
- * **When to use**
68
- *
69
- * Use when you need the `Generator` service to produce strong ETags and file
70
- * size plus modification time reliably change for every byte-level change.
71
- *
72
- * **Gotchas**
73
- *
74
- * This layer marks metadata-derived tags as strong. If the underlying storage
75
- * can update file contents without changing the recorded size or modification
76
- * time, those tags can stop representing byte-for-byte identity.
77
- *
78
- * @see {@link layerWeak} for weak metadata-derived ETags when byte-for-byte identity is not required
79
- * @see {@link Generator} for the service provided by this layer
80
- *
81
- * @category layers
82
- * @since 4.0.0
83
- */
84
- const layer = /*#__PURE__*/ succeed(Generator)({
85
- fromFileInfo(info) {
86
- return sync(() => ({
87
- _tag: "Strong",
88
- value: fromFileInfo(info)
89
- }));
90
- },
91
- fromFileWeb(file) {
92
- return sync(() => ({
93
- _tag: "Strong",
94
- value: fromFileWeb(file)
95
- }));
96
- }
97
- });
98
- /**
99
- * Layer that provides a `Generator` which produces weak ETags from file size and modification time metadata.
100
- *
101
- * @category layers
102
- * @since 4.0.0
103
- */
104
- const layerWeak = /*#__PURE__*/ succeed(Generator)({
105
- fromFileInfo(info) {
106
- return sync(() => ({
107
- _tag: "Weak",
108
- value: fromFileInfo(info)
109
- }));
110
- },
111
- fromFileWeb(file) {
112
- return sync(() => ({
113
- _tag: "Weak",
114
- value: fromFileWeb(file)
115
- }));
116
- }
117
- });
118
- //#endregion
119
23
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/ErrorReporter.js
120
24
  /**
121
25
  * Defines the runtime property key used to mark an object error as ignored by error
@@ -153,1054 +57,1150 @@ const layerWeak = /*#__PURE__*/ succeed(Generator)({
153
57
  */
154
58
  const ignore = "~effect/ErrorReporter/ignore";
155
59
  //#endregion
156
- //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/http/HttpServerResponse.js
60
+ //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/FiberSet.js
157
61
  /**
158
- * Describes immutable responses returned by Effect HTTP handlers.
62
+ * Manages many fibers together inside one scope.
159
63
  *
160
- * An `HttpServerResponse` stores the status, optional status text, headers,
161
- * cookies, and body that the server runtime later turns into a platform
162
- * response such as a Web `Response`. This module includes constructors for
163
- * common response bodies, helpers for updating response data, file response
164
- * support through `HttpPlatform`, and conversions to or from Web and Effect
165
- * HTTP client responses.
64
+ * A `FiberSet<A, E>` tracks running fibers, removes each fiber when it
65
+ * completes, and interrupts all still-running fibers when the owning scope
66
+ * closes. This module includes scoped runtime constructors plus helpers for
67
+ * adding, clearing, running, counting, joining, and waiting for managed fibers.
166
68
  *
167
- * @since 4.0.0
69
+ * @since 2.0.0
168
70
  */
169
- const TypeId$5 = "~effect/http/HttpServerResponse";
71
+ const TypeId$5 = "~effect/FiberSet";
170
72
  /**
171
- * Returns `true` when the supplied value is an `HttpServerResponse`.
73
+ * Checks whether a value is a FiberSet.
74
+ *
75
+ * **Example** (Checking if a value is a FiberSet)
76
+ *
77
+ * ```ts import.meta.vitest
78
+ * import { Effect, FiberSet } from "effect"
79
+ *
80
+ * const program = Effect.gen(function*() {
81
+ * const set = yield* FiberSet.make()
82
+ *
83
+ * return [FiberSet.isFiberSet(set), FiberSet.isFiberSet({})]
84
+ * })
85
+ *
86
+ * const actual = await Effect.runPromise(Effect.scoped(program))
87
+ * actual // => [true, false]
88
+ * ```
172
89
  *
173
90
  * @category guards
174
- * @since 4.0.0
91
+ * @since 2.0.0
175
92
  */
176
- const isHttpServerResponse = (u) => hasProperty(u, TypeId$5);
93
+ const isFiberSet = (u) => hasProperty(u, TypeId$5);
94
+ const Proto$1 = {
95
+ [TypeId$5]: TypeId$5,
96
+ [Symbol.iterator]() {
97
+ if (this.state._tag === "Closed") return empty$4();
98
+ return this.state.backing[Symbol.iterator]();
99
+ },
100
+ ...PipeInspectableProto,
101
+ toJSON() {
102
+ return {
103
+ _id: "FiberMap",
104
+ state: this.state
105
+ };
106
+ }
107
+ };
108
+ const makeUnsafe = (backing, deferred) => {
109
+ const self = Object.create(Proto$1);
110
+ self.state = {
111
+ _tag: "Open",
112
+ backing
113
+ };
114
+ self.deferred = deferred;
115
+ return self;
116
+ };
177
117
  /**
178
- * Creates an empty HTTP response.
118
+ * Creates a scoped `FiberSet` for storing fibers.
179
119
  *
180
120
  * **Details**
181
121
  *
182
- * The default status is `204`.
122
+ * When the associated Scope is closed, all fibers in the set will be
123
+ * interrupted. You can add fibers to the set using `FiberSet.add` or
124
+ * `FiberSet.run`, and the fibers will be automatically removed from the
125
+ * FiberSet when they complete.
183
126
  *
184
- * @category constructors
185
- * @since 4.0.0
186
- */
187
- const empty = (options) => makeResponse({
188
- status: options?.status ?? 204,
189
- statusText: options?.statusText,
190
- headers: options?.headers ? fromInput(options.headers) : void 0,
191
- cookies: options?.cookies
192
- });
193
- /**
194
- * Creates a redirect response with a `Location` header.
127
+ * **Example** (Creating a scoped FiberSet)
195
128
  *
196
- * **Details**
129
+ * ```ts import.meta.vitest
130
+ * import { Effect, FiberSet } from "effect"
197
131
  *
198
- * The default status is `302`; custom headers are merged with the generated
199
- * `Location` header.
132
+ * const program = Effect.gen(function*() {
133
+ * const set = yield* FiberSet.make()
200
134
  *
201
- * @category constructors
202
- * @since 4.0.0
203
- */
204
- const redirect = (location, options) => {
205
- const headers = fromRecordUnsafe({ location: location.toString() });
206
- return makeResponse({
207
- status: options?.status ?? 302,
208
- statusText: options?.statusText,
209
- headers: options?.headers ? merge(headers, fromInput(options.headers)) : headers,
210
- cookies: options?.cookies ?? empty$1
211
- });
212
- };
213
- /**
214
- * Creates an HTTP response whose body is a `Uint8Array`.
135
+ * // run some effects and add the fibers to the set
136
+ * yield* FiberSet.run(set, Effect.never)
137
+ * yield* FiberSet.run(set, Effect.never)
215
138
  *
216
- * @category constructors
217
- * @since 4.0.0
218
- */
219
- const uint8Array = (body, options) => {
220
- const headers = options?.headers ? fromInput(options.headers) : empty$2;
221
- return makeResponse({
222
- status: options?.status ?? 200,
223
- statusText: options?.statusText,
224
- headers,
225
- cookies: options?.cookies ?? empty$1,
226
- body: uint8Array$1(body, getContentType(options, headers))
227
- });
228
- };
229
- const getContentType = (options, headers) => {
230
- if (options?.contentType) return options.contentType;
231
- else if (options?.headers) return headers["content-type"];
232
- };
233
- /**
234
- * Creates an HTTP response whose body is a string.
139
+ * yield* Effect.yieldNow
140
+ * return yield* FiberSet.size(set)
141
+ * }).pipe(
142
+ * Effect.scoped // The fibers will be interrupted when the scope is closed
143
+ * )
144
+ *
145
+ * const actual = await Effect.runPromise(program)
146
+ * actual // => 2
147
+ * ```
235
148
  *
236
149
  * @category constructors
237
- * @since 4.0.0
150
+ * @since 2.0.0
238
151
  */
239
- const text = (body, options) => {
240
- const headers = options?.headers ? fromInput(options.headers) : empty$2;
241
- return makeResponse({
242
- status: options?.status ?? 200,
243
- statusText: options?.statusText,
244
- headers,
245
- cookies: options?.cookies ?? empty$1,
246
- body: text$1(body, getContentType(options, headers))
247
- });
248
- };
152
+ const make$8 = () => acquireRelease(sync(() => makeUnsafe(/* @__PURE__ */ new Set(), makeUnsafe$1())), (set) => suspend(() => {
153
+ const state = set.state;
154
+ if (state._tag === "Closed") return void_;
155
+ set.state = { _tag: "Closed" };
156
+ const fibers = state.backing;
157
+ return interruptAll(fibers).pipe(into(set.deferred));
158
+ }));
159
+ const internalFiberId = -1;
160
+ const isInternalInterruption = /*#__PURE__*/ toPredicate(/*#__PURE__*/ compose(filterInterruptors, /*#__PURE__*/ has(internalFiberId)));
249
161
  /**
250
- * Creates a JSON response constructor backed by a schema encoder.
162
+ * Adds an existing fiber to the `FiberSet` using a synchronous, unsafe
163
+ * mutation.
251
164
  *
252
- * **Details**
165
+ * **When to use**
253
166
  *
254
- * The returned function encodes the value with the supplied schema before
255
- * serializing it as JSON, and can fail with `HttpBodyError` if schema encoding or
256
- * JSON serialization fails.
167
+ * Use when an already forked fiber must be registered immediately and
168
+ * synchronous interruption on a closed set is acceptable.
257
169
  *
258
- * @category constructors
259
- * @since 4.0.0
260
- */
261
- const schemaJson = (schema, options) => {
262
- const encode = jsonSchema(schema, options);
263
- return (body, options) => {
264
- const headers = options?.headers ? fromInput(options.headers) : empty$2;
265
- return map$1(encode(body, getContentType(options, headers)), (body) => makeResponse({
266
- status: options?.status ?? 200,
267
- statusText: options?.statusText,
268
- headers,
269
- cookies: options?.cookies,
270
- body
271
- }));
272
- };
273
- };
274
- /**
275
- * Creates a JSON HTTP response synchronously.
170
+ * **Details**
276
171
  *
277
- * **When to use**
172
+ * When the fiber completes, it is removed from the set. If the set is already
173
+ * closed, the supplied fiber is interrupted immediately. Non-interruption
174
+ * failures are recorded for `FiberSet.join`.
278
175
  *
279
- * Use when the response body is known to be JSON-serializable and you need a
280
- * synchronous `HttpServerResponse`.
176
+ * **Example** (Adding a fiber unsafely)
281
177
  *
282
- * **Gotchas**
178
+ * ```ts import.meta.vitest
179
+ * import { Effect, FiberSet } from "effect"
283
180
  *
284
- * Unlike `json`, serialization errors from `JSON.stringify` are not captured in
285
- * `Effect`.
181
+ * const program = Effect.gen(function*() {
182
+ * const set = yield* FiberSet.make()
183
+ * const fiber = yield* Effect.forkChild(Effect.never)
286
184
  *
287
- * @category constructors
288
- * @since 4.0.0
289
- */
290
- const jsonUnsafe = (body, options) => {
291
- const headers = options?.headers ? fromInput(options.headers) : empty$2;
292
- return makeResponse({
293
- status: options?.status ?? 200,
294
- statusText: options?.statusText,
295
- headers,
296
- cookies: options?.cookies,
297
- body: jsonUnsafe$1(body, getContentType(options, headers))
298
- });
299
- };
300
- /**
301
- * Creates a response from URL parameters using the
302
- * `application/x-www-form-urlencoded` content type by default.
185
+ * // Unsafe add - doesn't return an Effect
186
+ * FiberSet.addUnsafe(set, fiber)
303
187
  *
304
- * @category constructors
188
+ * // The fiber is now managed by the set
189
+ * return yield* FiberSet.size(set)
190
+ * })
191
+ *
192
+ * const actual = await Effect.runPromise(Effect.scoped(program))
193
+ * actual // => 1
194
+ * ```
195
+ *
196
+ * @category combinators
305
197
  * @since 4.0.0
306
198
  */
307
- const urlParams = (body, options) => {
308
- const headers = options?.headers ? fromInput(options.headers) : empty$2;
309
- return makeResponse({
310
- status: options?.status ?? 200,
311
- statusText: options?.statusText,
312
- headers,
313
- cookies: options?.cookies,
314
- body: text$1(toString$1(fromInput$1(body)), getContentType(options, headers) ?? "application/x-www-form-urlencoded")
199
+ const addUnsafe = /*#__PURE__*/ dual((args) => isFiberSet(args[0]), (self, fiber, options) => {
200
+ if (self.state._tag === "Closed") {
201
+ fiber.interruptUnsafe(internalFiberId);
202
+ return;
203
+ } else if (self.state.backing.has(fiber)) return;
204
+ self.state.backing.add(fiber);
205
+ fiber.addObserver((exit) => {
206
+ if (self.state._tag === "Closed") return;
207
+ self.state.backing.delete(fiber);
208
+ if (isFailure(exit) && (options?.propagateInterruption === true ? !isInternalInterruption(exit.cause) : !hasInterruptsOnly(exit.cause))) doneUnsafe(self.deferred, exit);
315
209
  });
316
- };
210
+ });
211
+ const constInterruptedFiber = /*#__PURE__*/ function() {
212
+ let fiber = void 0;
213
+ return () => {
214
+ if (fiber === void 0) fiber = runFork(interrupt);
215
+ return fiber;
216
+ };
217
+ }();
317
218
  /**
318
- * Creates a response with a raw body value.
219
+ * Forks an Effect and add the forked fiber to the FiberSet.
220
+ * When the fiber completes, it will be removed from the FiberSet.
319
221
  *
320
- * **When to use**
222
+ * **Example** (Forking effects into a set)
321
223
  *
322
- * Use when you want to pass through a body value already understood by the
323
- * underlying runtime, such as a Web `Response`, `Blob`, or `ReadableStream`,
324
- * for later platform conversion.
224
+ * ```ts import.meta.vitest
225
+ * import { Effect, Fiber, FiberSet } from "effect"
325
226
  *
326
- * @category constructors
327
- * @since 4.0.0
328
- */
329
- const raw = (body, options) => makeResponse({
330
- status: options?.status ?? 200,
331
- statusText: options?.statusText,
332
- headers: options?.headers && fromInput(options.headers),
333
- cookies: options?.cookies,
334
- body: raw$1(body, {
335
- contentType: options?.contentType,
336
- contentLength: options?.contentLength
337
- })
338
- });
339
- /**
340
- * Creates a streaming response from a stream of byte chunks.
227
+ * const program = Effect.gen(function*() {
228
+ * const set = yield* FiberSet.make()
341
229
  *
342
- * **Details**
230
+ * // Fork and add to set
231
+ * const fiber1 = yield* FiberSet.run(set, Effect.succeed("hello"))
232
+ * const fiber2 = yield* FiberSet.run(set, Effect.succeed("world"))
343
233
  *
344
- * Optional response metadata can supply the status, headers, content type, and
345
- * content length.
234
+ * // Get results
235
+ * return [yield* Fiber.join(fiber1), yield* Fiber.join(fiber2)]
236
+ * })
346
237
  *
347
- * @category constructors
348
- * @since 4.0.0
238
+ * const actual = await Effect.runPromise(Effect.scoped(program))
239
+ * actual // => ["hello", "world"]
240
+ * ```
241
+ *
242
+ * @category combinators
243
+ * @since 2.0.0
349
244
  */
350
- const stream = (body, options) => {
351
- const headers = options?.headers ? fromInput(options.headers) : empty$2;
352
- return makeResponse({
353
- status: options?.status ?? 200,
354
- statusText: options?.statusText,
355
- headers,
356
- cookies: options?.cookies,
357
- body: stream$1(body, getContentType(options, headers), options?.contentLength)
358
- });
245
+ const run = function() {
246
+ const self = arguments[0];
247
+ if (!isEffect(arguments[1])) {
248
+ const options = arguments[1];
249
+ return (effect) => runImpl(self, effect, options);
250
+ }
251
+ return runImpl(self, arguments[1], arguments[2]);
359
252
  };
360
- const HttpPlatformKey = /*#__PURE__*/ Service("effect/http/HttpPlatform");
253
+ const runImpl = (self, effect, options) => withFiber((parent) => {
254
+ if (self.state._tag === "Closed") return sync(constInterruptedFiber);
255
+ const fiber = runForkWith(parent.context)(effect);
256
+ addUnsafe(self, fiber, options);
257
+ return succeed(fiber);
258
+ });
361
259
  /**
362
- * Creates a streamed file response for a file system path.
260
+ * Captures a `Runtime` and uses it to fork effects into the `FiberSet`.
363
261
  *
364
- * **Details**
262
+ * **Example** (Capturing a runtime)
365
263
  *
366
- * The effect requires `HttpPlatform`, can fail with a platform error, and supports
367
- * options for status, headers, offset, and byte range.
264
+ * ```ts import.meta.vitest
265
+ * import { Context, Effect, Fiber, FiberSet } from "effect"
368
266
  *
369
- * @category constructors
370
- * @since 4.0.0
371
- */
372
- const file = (path, options) => flatMap(HttpPlatformKey, (platform) => platform.fileResponse(path, options));
373
- /**
374
- * Returns a response with the specified header set to the supplied value.
267
+ * class Users extends Context.Service<Users, {
268
+ * readonly getAll: Effect.Effect<Array<unknown>>
269
+ * }>()("Users") {}
375
270
  *
376
- * @category combinators
377
- * @since 4.0.0
378
- */
379
- const setHeader = /*#__PURE__*/ dual(3, (self, key, value) => makeResponse({
380
- ...self,
381
- headers: set(self.headers, key, value)
382
- }));
383
- /**
384
- * Returns a response with the specified header removed.
271
+ * const program = Effect.gen(function*() {
272
+ * const set = yield* FiberSet.make()
273
+ * const run = yield* FiberSet.runtime(set)<Users>()
385
274
  *
386
- * @category combinators
387
- * @since 4.0.0
388
- */
389
- const removeHeader = /*#__PURE__*/ dual(2, (self, key) => makeResponse({
390
- ...self,
391
- headers: remove(self.headers, key)
392
- }));
393
- /**
394
- * Returns a response with all supplied headers set on the existing header map.
275
+ * // run some effects and add the fibers to the set
276
+ * const fiber = run(Effect.andThen(Users, (_) => _.getAll))
277
+ * return (yield* Fiber.join(fiber)).length
278
+ * }).pipe(
279
+ * Effect.scoped // The fibers will be interrupted when the scope is closed
280
+ * )
281
+ *
282
+ * const actual = await Effect.runPromise(Effect.provideService(program, Users, {
283
+ * getAll: Effect.succeed([])
284
+ * }))
285
+ * actual // => 0
286
+ * ```
395
287
  *
396
288
  * @category combinators
397
- * @since 4.0.0
289
+ * @since 2.0.0
398
290
  */
399
- const setHeaders = /*#__PURE__*/ dual(2, (self, input) => makeResponse({
400
- ...self,
401
- headers: setAll(self.headers, input)
402
- }));
291
+ const runtime = (self) => () => map$1(context(), (services) => {
292
+ const runFork = runForkWith(services);
293
+ return (effect, options) => {
294
+ if (self.state._tag === "Closed") return constInterruptedFiber();
295
+ const fiber = runFork(effect, options);
296
+ addUnsafe(self, fiber, options);
297
+ return fiber;
298
+ };
299
+ });
403
300
  /**
404
- * Merges additional cookies into the cookies attached to an
405
- * `HttpServerResponse`.
301
+ * Joins all fibers in the FiberSet. If any fiber in the set terminates with a failure,
302
+ * the returned Effect will terminate with the first failure that occurred.
406
303
  *
407
- * **Details**
304
+ * **Example** (Joining failing fibers)
408
305
  *
409
- * The original response is not mutated; a new response is returned with the merged
410
- * cookie collection.
306
+ * ```ts import.meta.vitest
307
+ * import { Effect, Exit, FiberSet } from "effect"
411
308
  *
412
- * @category combinators
413
- * @since 4.0.0
414
- */
415
- const mergeCookies = /*#__PURE__*/ dual(2, (self, cookies) => makeResponse({
416
- ...self,
417
- cookies: merge$1(self.cookies, cookies)
418
- }));
419
- /**
420
- * Replaces the body of an `HttpServerResponse`.
309
+ * const program = Effect.gen(function*() {
310
+ * const set = yield* FiberSet.make()
311
+ * yield* FiberSet.add(set, Effect.runFork(Effect.fail("error")))
421
312
  *
422
- * **Details**
313
+ * // parent fiber will fail with "error"
314
+ * yield* FiberSet.join(set)
315
+ * })
423
316
  *
424
- * When the body carries a content type or content length, the returned response
425
- * includes the corresponding headers.
317
+ * const actual = await Effect.runPromise(Effect.exit(Effect.scoped(program)))
318
+ * actual // => Exit.fail("error")
319
+ * ```
426
320
  *
427
321
  * @category combinators
428
- * @since 4.0.0
322
+ * @since 2.0.0
429
323
  */
430
- const setBody = /*#__PURE__*/ dual(2, (self, body) => makeResponse({
431
- ...self,
432
- body
433
- }));
324
+ const join = (self) => _await(self.deferred);
434
325
  /**
435
- * Sets the HTTP status code of an `HttpServerResponse`.
326
+ * Waits until the fiber set is empty.
436
327
  *
437
- * **Details**
328
+ * **Example** (Waiting for an empty set)
438
329
  *
439
- * When `statusText` is omitted, the existing status text is preserved.
330
+ * ```ts import.meta.vitest
331
+ * import { Effect, FiberSet } from "effect"
332
+ *
333
+ * const program = Effect.gen(function*() {
334
+ * const set = yield* FiberSet.make()
335
+ *
336
+ * yield* FiberSet.run(set, Effect.yieldNow)
337
+ * yield* FiberSet.run(set, Effect.yieldNow)
338
+ *
339
+ * // Wait for all fibers to complete
340
+ * yield* FiberSet.awaitEmpty(set)
341
+ *
342
+ * return yield* FiberSet.size(set)
343
+ * })
344
+ *
345
+ * const actual = await Effect.runPromise(Effect.scoped(program))
346
+ * actual // => 0
347
+ * ```
440
348
  *
441
349
  * @category combinators
442
- * @since 4.0.0
350
+ * @since 3.13.0
443
351
  */
444
- const setStatus = /*#__PURE__*/ dual((args) => isHttpServerResponse(args[0]), (self, status, statusText) => makeResponse({
445
- ...self,
446
- status,
447
- statusText: statusText ?? self.statusText
448
- }));
449
- const Proto$1 = {
450
- ...PipeInspectableProto,
451
- [TypeId$5]: TypeId$5,
452
- [ignore]: true,
453
- toJSON() {
454
- return {
455
- _id: "HttpServerResponse",
456
- status: this.status,
457
- statusText: this.statusText,
458
- headers: redact$1(this.headers),
459
- cookies: this.cookies.toJSON(),
460
- body: this.body.toJSON()
461
- };
462
- }
463
- };
464
- const makeResponse = (options) => {
465
- const self = Object.create(Proto$1);
466
- self.status = options.status;
467
- self.statusText = options.statusText;
468
- self.cookies = options.cookies ?? empty$1;
469
- self.body = options.body ?? empty$3;
470
- if (self.body._tag !== "Empty" && (self.body.contentType || self.body.contentLength)) {
471
- const newHeaders = fromRecordUnsafe({ ...options.headers });
472
- if (self.body.contentType) newHeaders["content-type"] = self.body.contentType;
473
- if (self.body.contentLength) newHeaders["content-length"] = self.body.contentLength.toString();
474
- self.headers = newHeaders;
475
- } else self.headers = options.headers ?? empty$2;
476
- return self;
477
- };
478
- //#endregion
479
- //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/http/internal/compression.js
480
- /** @internal */
481
- const varyAcceptEncoding = (headers) => {
482
- const vary = headers["vary"];
483
- if (vary === void 0) return "Accept-Encoding";
484
- const members = vary.split(",").map((member) => member.trim().toLowerCase());
485
- return members.includes("*") || members.includes("accept-encoding") ? void 0 : `${vary}, Accept-Encoding`;
486
- };
487
- /** @internal */
488
- const wrapCompression = (impl) => ({
489
- algorithms: impl.algorithms,
490
- compressResponse(response, algorithm, options) {
491
- return map$1(impl.compressResponse(response, algorithm, options), (compressed) => {
492
- if (compressed === response) return response;
493
- const headers = { "content-encoding": algorithm };
494
- const vary = varyAcceptEncoding(compressed.headers);
495
- if (vary !== void 0) headers["vary"] = vary;
496
- const etag = compressed.headers["etag"];
497
- if (etag !== void 0 && !etag.startsWith("W/")) headers["etag"] = `W/${etag}`;
498
- return setHeaders(compressed, headers);
499
- });
500
- }
352
+ const awaitEmpty = (self) => whileLoop({
353
+ while: () => self.state._tag === "Open" && self.state.backing.size > 0,
354
+ body: () => await_(headUnsafe(self)),
355
+ step: constVoid
501
356
  });
502
- /** @internal */
503
- const defaultCompressible = (contentType) => {
504
- const semi = contentType.indexOf(";");
505
- const type = (semi === -1 ? contentType : contentType.slice(0, semi)).trim().toLowerCase();
506
- if (type.startsWith("text/")) return true;
507
- switch (type) {
508
- case "application/json":
509
- case "application/javascript":
510
- case "application/xml":
511
- case "image/svg+xml":
512
- case "application/wasm": return true;
513
- }
514
- return type.endsWith("+json") || type.endsWith("+xml");
515
- };
516
- const acceptMember = /^([a-z0-9!#$%&'*+.^_`|~-]+)(?:;q=(0(?:\.[0-9]{0,3})?|1(?:\.0{0,3})?))?$/;
517
- /** @internal */
518
- const parseAcceptEncoding = (header) => {
519
- const trimmed = header.trim();
520
- if (trimmed === "") return;
521
- const accepted = /* @__PURE__ */ new Map();
522
- for (const part of trimmed.split(",")) {
523
- const member = part.trim().toLowerCase().replace(/[ \t]*;[ \t]*/g, ";");
524
- const match = acceptMember.exec(member);
525
- if (match === null) return;
526
- accepted.set(match[1], match[2] === void 0 ? 1 : Number(match[2]));
527
- }
528
- return accepted;
529
- };
530
- /** @internal */
531
- const negotiate = (header, preferred, supported) => {
532
- if (header === void 0) return;
533
- const accepted = parseAcceptEncoding(header);
534
- if (accepted === void 0) return;
535
- for (const algorithm of preferred) {
536
- if (!supported.has(algorithm)) continue;
537
- const quality = accepted.get(algorithm) ?? accepted.get("*");
538
- if (quality !== void 0 && quality > 0) return algorithm;
539
- }
540
- };
541
357
  //#endregion
542
- //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/http/HttpPlatform.js
358
+ //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/http/Etag.js
543
359
  /**
544
- * Platform-specific support for serving files as HTTP server responses.
360
+ * HTTP entity tag values and metadata-based generator layers.
545
361
  *
546
- * `HttpPlatform` is the boundary between the portable HTTP response model and
547
- * the runtime that knows how to stream bytes from the host platform. Server
548
- * code uses this service when it needs to return local files, static assets,
549
- * downloads, byte ranges, or Web `File`-like values without constructing the
550
- * response body by hand.
362
+ * ETags are validators for a specific representation of a resource. Servers put
363
+ * them in `ETag` response headers so clients and intermediaries can revalidate
364
+ * cached content with `If-None-Match`, or protect writes with preconditions such
365
+ * as `If-Match`.
551
366
  *
552
367
  * @since 4.0.0
553
368
  */
554
369
  /**
555
- * Service for platform-specific HTTP response helpers, including file-backed server responses.
370
+ * Formats an `Etag` as an HTTP header value, including quotes and the `W/` prefix for weak tags.
556
371
  *
557
- * @category services
372
+ * @category converting
558
373
  * @since 4.0.0
559
374
  */
560
- var HttpPlatform = class extends Service()("effect/http/HttpPlatform") {};
375
+ const toString = (self) => {
376
+ switch (self._tag) {
377
+ case "Weak": return `W/"${self.value}"`;
378
+ case "Strong": return `"${self.value}"`;
379
+ }
380
+ };
561
381
  /**
562
- * Creates an `HttpPlatform` service from platform-specific file response constructors, using `FileSystem` and `Etag.Generator`.
382
+ * Service for generating ETags from filesystem file information or Web `File`-like metadata.
563
383
  *
564
- * @category constructors
384
+ * @category services
565
385
  * @since 4.0.0
566
386
  */
567
- const make$8 = /*#__PURE__*/ fnUntraced(function* (impl) {
568
- const fs = yield* FileSystem;
569
- const etagGen = yield* Generator;
570
- return HttpPlatform.of({
571
- platform: impl.platform,
572
- compression: wrapCompression(impl.compression),
573
- fileResponse: fnUntraced(function* (path, options) {
574
- const info = yield* fs.stat(path);
575
- const etag = yield* etagGen.fromFileInfo(info);
576
- const start = Number(options?.offset ?? 0);
577
- const end = options?.bytesToRead !== void 0 ? start + Number(options.bytesToRead) : void 0;
578
- const headers = set(options?.headers ? fromInput(options.headers) : empty$2, "etag", toString(etag));
579
- if (isSome(info.mtime)) headers["last-modified"] = info.mtime.value.toUTCString();
580
- const contentLength = end !== void 0 ? end - start : Number(info.size) - start;
581
- return impl.fileResponse(path, options?.status ?? 200, options?.statusText, headers, start, end, contentLength);
582
- }),
583
- fileWebResponse(file, options) {
584
- return map$1(etagGen.fromFileWeb(file), (etag) => {
585
- const headers = merge(options?.headers ? fromInput(options.headers) : empty$2, fromRecordUnsafe({
586
- etag: toString(etag),
587
- "last-modified": new Date(file.lastModified).toUTCString()
588
- }));
589
- return impl.fileWebResponse(file, options?.status ?? 200, options?.statusText, headers, options);
590
- });
591
- }
387
+ var Generator = class extends Service()("effect/http/Etag/Generator") {};
388
+ const fromFileInfo = (info) => {
389
+ const mtime = match(info.mtime, {
390
+ onNone: () => "0",
391
+ onSome: (mtime) => mtime.getTime().toString(16)
592
392
  });
593
- });
594
- //#endregion
595
- //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/http/HttpServerRespondable.js
393
+ return `${info.size.toString(16)}-${mtime}`;
394
+ };
395
+ const fromFileWeb = (file) => {
396
+ return `${file.size.toString(16)}-${file.lastModified.toString(16)}`;
397
+ };
596
398
  /**
597
- * Converts supported values into HTTP server responses.
598
- *
599
- * Server-side errors and helper values can implement `Respondable` when they
600
- * know which status, headers, cookies, or body should be sent to the client.
601
- * This module detects those values and converts them to `HttpServerResponse`
602
- * values, with fallback handling for schema errors and missing values.
399
+ * Layer that provides a `Generator` which produces strong ETags from file size
400
+ * and modification time metadata.
603
401
  *
604
- * @since 4.0.0
605
- */
606
- /**
607
- * Protocol key used by values that can render themselves as
608
- * `HttpServerResponse` values.
402
+ * **When to use**
609
403
  *
610
- * @category type IDs
611
- * @since 4.0.0
612
- */
613
- const symbol = "~effect/http/HttpServerRespondable";
614
- /**
615
- * Returns `true` when the supplied value implements the `Respondable` protocol.
404
+ * Use when you need the `Generator` service to produce strong ETags and file
405
+ * size plus modification time reliably change for every byte-level change.
616
406
  *
617
- * @category guards
618
- * @since 4.0.0
619
- */
620
- const isRespondable = (u) => hasProperty(u, symbol);
621
- const badRequest = /*#__PURE__*/ empty({ status: 400 });
622
- const notFound = /*#__PURE__*/ empty({ status: 404 });
623
- /**
624
- * Converts a `Respondable` value into an `HttpServerResponse`.
407
+ * **Gotchas**
625
408
  *
626
- * **Details**
409
+ * This layer marks metadata-derived tags as strong. If the underlying storage
410
+ * can update file contents without changing the recorded size or modification
411
+ * time, those tags can stop representing byte-for-byte identity.
627
412
  *
628
- * If the value is already an HTTP server response it is returned directly; errors
629
- * from the response conversion are converted to defects.
413
+ * @see {@link layerWeak} for weak metadata-derived ETags when byte-for-byte identity is not required
414
+ * @see {@link Generator} for the service provided by this layer
630
415
  *
631
- * @category accessors
416
+ * @category layers
632
417
  * @since 4.0.0
633
418
  */
634
- const toResponse = (self) => {
635
- if (isHttpServerResponse(self)) return succeed$1(self);
636
- return orDie(self[symbol]());
637
- };
419
+ const layer = /*#__PURE__*/ succeed$1(Generator)({
420
+ fromFileInfo(info) {
421
+ return sync(() => ({
422
+ _tag: "Strong",
423
+ value: fromFileInfo(info)
424
+ }));
425
+ },
426
+ fromFileWeb(file) {
427
+ return sync(() => ({
428
+ _tag: "Strong",
429
+ value: fromFileWeb(file)
430
+ }));
431
+ }
432
+ });
638
433
  /**
639
- * Attempts to convert an unknown value into an `HttpServerResponse`, falling back
640
- * to the supplied response when no conversion is available.
641
- *
642
- * **Details**
643
- *
644
- * `HttpServerResponse` and `Respondable` values are used directly, schema errors
645
- * become `400` responses, and no-such-element errors become `404` responses.
434
+ * Layer that provides a `Generator` which produces weak ETags from file size and modification time metadata.
646
435
  *
647
- * @category accessors
436
+ * @category layers
648
437
  * @since 4.0.0
649
438
  */
650
- const toResponseOrElse = (u, orElse) => {
651
- if (isHttpServerResponse(u)) return succeed$1(u);
652
- else if (isRespondable(u)) return catchCause(u[symbol](), () => succeed$1(orElse));
653
- else if (isSchemaError(u)) return succeed$1(badRequest);
654
- else if (isNoSuchElementError(u)) return succeed$1(notFound);
655
- return succeed$1(orElse);
656
- };
439
+ const layerWeak = /*#__PURE__*/ succeed$1(Generator)({
440
+ fromFileInfo(info) {
441
+ return sync(() => ({
442
+ _tag: "Weak",
443
+ value: fromFileInfo(info)
444
+ }));
445
+ },
446
+ fromFileWeb(file) {
447
+ return sync(() => ({
448
+ _tag: "Weak",
449
+ value: fromFileWeb(file)
450
+ }));
451
+ }
452
+ });
453
+ //#endregion
454
+ //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/http/HttpServerResponse.js
657
455
  /**
658
- * Attempts to convert an unknown defect into an `HttpServerResponse`, falling
659
- * back to the supplied response when no conversion is available.
660
- *
661
- * **Details**
456
+ * Describes immutable responses returned by Effect HTTP handlers.
662
457
  *
663
- * Only `HttpServerResponse` and `Respondable` values receive special handling.
458
+ * An `HttpServerResponse` stores the status, optional status text, headers,
459
+ * cookies, and body that the server runtime later turns into a platform
460
+ * response such as a Web `Response`. This module includes constructors for
461
+ * common response bodies, helpers for updating response data, file response
462
+ * support through `HttpPlatform`, and conversions to or from Web and Effect
463
+ * HTTP client responses.
664
464
  *
665
- * @category accessors
666
465
  * @since 4.0.0
667
466
  */
668
- const toResponseOrElseDefect = (u, orElse) => {
669
- if (isHttpServerResponse(u)) return succeed$1(u);
670
- else if (isRespondable(u)) return catchCause(u[symbol](), () => succeed$1(orElse));
671
- return succeed$1(orElse);
672
- };
673
- //#endregion
674
- //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/http/HttpServerError.js
467
+ const TypeId$4 = "~effect/http/HttpServerResponse";
675
468
  /**
676
- * Describes failures raised while handling HTTP server requests.
677
- *
678
- * `HttpServerError` covers failures that happen while accepting a request,
679
- * matching a route, running a handler, or building and sending a response.
680
- * Request-scoped failures keep the request that caused them, and response
681
- * failures keep the response being produced. This module also includes helpers
682
- * for turning failed causes or exits into HTTP responses and an annotation for
683
- * interrupts caused by client aborts.
469
+ * Returns `true` when the supplied value is an `HttpServerResponse`.
684
470
  *
471
+ * @category guards
685
472
  * @since 4.0.0
686
473
  */
687
- const TypeId$4 = "~effect/http/HttpServerError";
474
+ const isHttpServerResponse = (u) => hasProperty(u, TypeId$4);
688
475
  /**
689
- * Tagged error for failures that occur while handling an HTTP server request.
476
+ * Creates an empty HTTP response.
690
477
  *
691
478
  * **Details**
692
479
  *
693
- * It wraps a `HttpServerErrorReason`, exposes the associated request and optional
694
- * response, and can be converted to an HTTP response through the `Respondable`
695
- * protocol.
480
+ * The default status is `204`.
696
481
  *
697
- * @category errors
482
+ * @category constructors
698
483
  * @since 4.0.0
699
484
  */
700
- var HttpServerError = class extends TaggedError("HttpServerError") {
701
- constructor(props) {
702
- if ("cause" in props.reason) super({
703
- ...props,
704
- cause: props.reason.cause
705
- });
706
- else super(props);
707
- }
708
- [TypeId$4] = TypeId$4;
709
- stack = `${this.name}: ${this.message}`;
710
- get request() {
711
- return this.reason.request;
712
- }
713
- get response() {
714
- return "response" in this.reason ? this.reason.response : void 0;
715
- }
716
- [symbol]() {
717
- return this.reason[symbol]();
718
- }
719
- get [ignore]() {
720
- return this.reason["~effect/ErrorReporter/ignore"] ?? false;
721
- }
722
- get message() {
723
- return this.reason.message;
724
- }
725
- };
485
+ const empty = (options) => makeResponse({
486
+ status: options?.status ?? 204,
487
+ statusText: options?.statusText,
488
+ headers: options?.headers ? fromInput(options.headers) : void 0,
489
+ cookies: options?.cookies
490
+ });
726
491
  /**
727
- * Error describing a failure to parse or read an incoming request.
492
+ * Creates a redirect response with a `Location` header.
728
493
  *
729
494
  * **Details**
730
495
  *
731
- * When converted to a response it produces an empty `400` response.
496
+ * The default status is `302`; custom headers are merged with the generated
497
+ * `Location` header.
732
498
  *
733
- * @category errors
499
+ * @category constructors
734
500
  * @since 4.0.0
735
501
  */
736
- var RequestParseError = class extends TaggedError("RequestParseError") {
737
- /**
738
- * Converts the request error into a `400 Bad Request` response.
739
- *
740
- * @since 4.0.0
741
- */
742
- [symbol]() {
743
- return succeed$1(empty({ status: 400 }));
744
- }
745
- get methodAndUrl() {
746
- return `${this.request.method} ${this.request.url}`;
747
- }
748
- get message() {
749
- return formatRequestMessage(this._tag, this.description, this.methodAndUrl);
750
- }
502
+ const redirect = (location, options) => {
503
+ const headers = fromRecordUnsafe({ location: location.toString() });
504
+ return makeResponse({
505
+ status: options?.status ?? 302,
506
+ statusText: options?.statusText,
507
+ headers: options?.headers ? merge(headers, fromInput(options.headers)) : headers,
508
+ cookies: options?.cookies ?? empty$1
509
+ });
751
510
  };
752
511
  /**
753
- * Error indicating that no route matched the incoming request.
754
- *
755
- * **Details**
512
+ * Creates an HTTP response whose body is a `Uint8Array`.
756
513
  *
757
- * When converted to a response it produces an empty `404` response, and it is
758
- * ignored by the error reporter.
514
+ * @category constructors
515
+ * @since 4.0.0
516
+ */
517
+ const uint8Array = (body, options) => {
518
+ const headers = options?.headers ? fromInput(options.headers) : empty$2;
519
+ return makeResponse({
520
+ status: options?.status ?? 200,
521
+ statusText: options?.statusText,
522
+ headers,
523
+ cookies: options?.cookies ?? empty$1,
524
+ body: uint8Array$1(body, getContentType(options, headers))
525
+ });
526
+ };
527
+ const getContentType = (options, headers) => {
528
+ if (options?.contentType) return options.contentType;
529
+ else if (options?.headers) return headers["content-type"];
530
+ };
531
+ /**
532
+ * Creates an HTTP response whose body is a string.
759
533
  *
760
- * @category errors
534
+ * @category constructors
761
535
  * @since 4.0.0
762
536
  */
763
- var RouteNotFound = class extends TaggedError("RouteNotFound") {
764
- [symbol]() {
765
- return succeed$1(empty({ status: 404 }));
766
- }
767
- [ignore] = true;
768
- get methodAndUrl() {
769
- return `${this.request.method} ${this.request.url}`;
770
- }
771
- get message() {
772
- return formatRequestMessage(this._tag, this.description, this.methodAndUrl);
773
- }
537
+ const text = (body, options) => {
538
+ const headers = options?.headers ? fromInput(options.headers) : empty$2;
539
+ return makeResponse({
540
+ status: options?.status ?? 200,
541
+ statusText: options?.statusText,
542
+ headers,
543
+ cookies: options?.cookies ?? empty$1,
544
+ body: text$1(body, getContentType(options, headers))
545
+ });
774
546
  };
775
- TaggedError("InternalError");
776
547
  /**
777
- * Error describing a failure related to an HTTP response.
548
+ * Creates a JSON response constructor backed by a schema encoder.
778
549
  *
779
550
  * **Details**
780
551
  *
781
- * It carries the request and response involved in the failure. When converted to
782
- * a response it produces an empty `500` response.
552
+ * The returned function encodes the value with the supplied schema before
553
+ * serializing it as JSON, and can fail with `HttpBodyError` if schema encoding or
554
+ * JSON serialization fails.
783
555
  *
784
- * @category errors
556
+ * @category constructors
785
557
  * @since 4.0.0
786
558
  */
787
- var ResponseError = class extends TaggedError("ResponseError") {
788
- [symbol]() {
789
- return succeed$1(empty({ status: 500 }));
790
- }
791
- get methodAndUrl() {
792
- return `${this.request.method} ${this.request.url}`;
793
- }
794
- get message() {
795
- const info = `${this._tag} (${this.response.status} ${this.methodAndUrl})`;
796
- return this.description ? `${info}: ${this.description}` : info;
797
- }
559
+ const schemaJson = (schema, options) => {
560
+ const encode = jsonSchema(schema, options);
561
+ return (body, options) => {
562
+ const headers = options?.headers ? fromInput(options.headers) : empty$2;
563
+ return map$1(encode(body, getContentType(options, headers)), (body) => makeResponse({
564
+ status: options?.status ?? 200,
565
+ statusText: options?.statusText,
566
+ headers,
567
+ cookies: options?.cookies,
568
+ body
569
+ }));
570
+ };
798
571
  };
799
572
  /**
800
- * Error wrapping a low-level failure from the HTTP server implementation.
573
+ * Creates a JSON HTTP response synchronously.
801
574
  *
802
- * @category errors
803
- * @since 4.0.0
804
- */
805
- var ServeError = class extends TaggedError("ServeError") {};
806
- /**
807
- * Context annotation used to mark an interrupt as caused by the client aborting
808
- * the request.
575
+ * **When to use**
809
576
  *
810
- * **Details**
577
+ * Use when the response body is known to be JSON-serializable and you need a
578
+ * synchronous `HttpServerResponse`.
811
579
  *
812
- * `causeResponse` uses this annotation to map a pure client abort to a `499`
813
- * response instead of a server abort response.
580
+ * **Gotchas**
814
581
  *
815
- * @category services
582
+ * Unlike `json`, serialization errors from `JSON.stringify` are not captured in
583
+ * `Effect`.
584
+ *
585
+ * @category constructors
816
586
  * @since 4.0.0
817
587
  */
818
- var ClientAbort = class extends Service()("effect/http/HttpServerError/ClientAbort") {
819
- static annotation = /*#__PURE__*/ this.context(true).pipe(/*#__PURE__*/ add(StackTrace, {
820
- name: "ClientAbort",
821
- stack: constUndefined,
822
- parent: void 0
823
- }));
588
+ const jsonUnsafe = (body, options) => {
589
+ const headers = options?.headers ? fromInput(options.headers) : empty$2;
590
+ return makeResponse({
591
+ status: options?.status ?? 200,
592
+ statusText: options?.statusText,
593
+ headers,
594
+ cookies: options?.cookies,
595
+ body: jsonUnsafe$1(body, getContentType(options, headers))
596
+ });
824
597
  };
825
- const formatRequestMessage = (reason, description, info) => {
826
- const prefix = `${reason} (${info})`;
827
- return description ? `${prefix}: ${description}` : prefix;
598
+ /**
599
+ * Creates a response from URL parameters using the
600
+ * `application/x-www-form-urlencoded` content type by default.
601
+ *
602
+ * @category constructors
603
+ * @since 4.0.0
604
+ */
605
+ const urlParams = (body, options) => {
606
+ const headers = options?.headers ? fromInput(options.headers) : empty$2;
607
+ return makeResponse({
608
+ status: options?.status ?? 200,
609
+ statusText: options?.statusText,
610
+ headers,
611
+ cookies: options?.cookies,
612
+ body: text$1(toString$1(fromInput$1(body)), getContentType(options, headers) ?? "application/x-www-form-urlencoded")
613
+ });
828
614
  };
829
615
  /**
830
- * Converts a failed handler cause into the HTTP response that should be sent and
831
- * the cause that should be reported.
616
+ * Creates a response with a raw body value.
832
617
  *
833
- * **Details**
618
+ * **When to use**
834
619
  *
835
- * Respondable failures and defects can choose their own response, defects that
836
- * are already `HttpServerResponse` values are used directly, and pure interrupts
837
- * produce either `499` for client aborts or `503` for server aborts.
620
+ * Use when you want to pass through a body value already understood by the
621
+ * underlying runtime, such as a Web `Response`, `Blob`, or `ReadableStream`,
622
+ * for later platform conversion.
838
623
  *
839
- * @category error handling
624
+ * @category constructors
840
625
  * @since 4.0.0
841
626
  */
842
- const causeResponse = (cause) => {
843
- let response;
844
- let effect = succeedInternalServerError;
845
- const failures = [];
846
- let interrupts = [];
847
- let isClientInterrupt = false;
848
- for (let i = 0; i < cause.reasons.length; i++) {
849
- const reason = cause.reasons[i];
850
- switch (reason._tag) {
851
- case "Fail":
852
- effect = toResponseOrElse(reason.error, internalServerError);
853
- failures.push(reason);
854
- break;
855
- case "Die":
856
- if (isHttpServerResponse(reason.defect)) response = reason.defect;
857
- else {
858
- effect = toResponseOrElseDefect(reason.defect, internalServerError);
859
- failures.push(reason);
860
- }
861
- break;
862
- case "Interrupt":
863
- isClientInterrupt = reason.annotations.has(ClientAbort.key);
864
- if (failures.length > 0) break;
865
- interrupts.push(reason);
866
- break;
867
- }
868
- }
869
- if (response) return succeed$1([response, fromReasons(failures)]);
870
- else if (interrupts.length > 0 && failures.length === 0) {
871
- failures.push(...interrupts);
872
- effect = isClientInterrupt ? clientAbortError : serverAbortError;
873
- }
874
- return mapEager(effect, (response) => {
875
- failures.push(makeDieReason(response));
876
- return [response, fromReasons(failures)];
877
- });
878
- };
627
+ const raw = (body, options) => makeResponse({
628
+ status: options?.status ?? 200,
629
+ statusText: options?.statusText,
630
+ headers: options?.headers && fromInput(options.headers),
631
+ cookies: options?.cookies,
632
+ body: raw$1(body, {
633
+ contentType: options?.contentType,
634
+ contentLength: options?.contentLength
635
+ })
636
+ });
879
637
  /**
880
- * Derives an HTTP response from a failed handler cause synchronously.
638
+ * Creates a streaming response from a stream of byte chunks.
881
639
  *
882
640
  * **Details**
883
641
  *
884
- * If the cause contains a defect that is already an `HttpServerResponse`, that
885
- * response is used and removed from the remaining cause. Otherwise the response
886
- * defaults to `500`.
642
+ * Optional response metadata can supply the status, headers, content type, and
643
+ * content length.
887
644
  *
888
- * @category error handling
645
+ * @category constructors
889
646
  * @since 4.0.0
890
647
  */
891
- const causeResponseStripped = (cause) => {
892
- let response;
893
- const failures = cause.reasons.filter((f) => {
894
- if (f._tag === "Die" && isHttpServerResponse(f.defect)) {
895
- response = f.defect;
896
- return false;
897
- }
898
- return true;
648
+ const stream = (body, options) => {
649
+ const headers = options?.headers ? fromInput(options.headers) : empty$2;
650
+ return makeResponse({
651
+ status: options?.status ?? 200,
652
+ statusText: options?.statusText,
653
+ headers,
654
+ cookies: options?.cookies,
655
+ body: stream$1(body, getContentType(options, headers), options?.contentLength)
899
656
  });
900
- return [response ?? internalServerError, failures.length > 0 ? some(fromReasons(failures)) : none()];
901
657
  };
902
- const internalServerError = /*#__PURE__*/ empty({ status: 500 });
903
- const succeedInternalServerError = /*#__PURE__*/ succeed$1(internalServerError);
904
- const clientAbortError = /*#__PURE__*/ succeed$1(/*#__PURE__*/ empty({ status: 499 }));
905
- const serverAbortError = /*#__PURE__*/ succeed$1(/*#__PURE__*/ empty({ status: 503 }));
906
- //#endregion
907
- //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/FiberSet.js
658
+ const HttpPlatformKey = /*#__PURE__*/ Service("effect/http/HttpPlatform");
908
659
  /**
909
- * Manages many fibers together inside one scope.
660
+ * Creates a streamed file response for a file system path.
910
661
  *
911
- * A `FiberSet<A, E>` tracks running fibers, removes each fiber when it
912
- * completes, and interrupts all still-running fibers when the owning scope
913
- * closes. This module includes scoped runtime constructors plus helpers for
914
- * adding, clearing, running, counting, joining, and waiting for managed fibers.
662
+ * **Details**
915
663
  *
916
- * @since 2.0.0
664
+ * The effect requires `HttpPlatform`, can fail with a platform error, and supports
665
+ * options for status, headers, offset, and byte range.
666
+ *
667
+ * @category constructors
668
+ * @since 4.0.0
917
669
  */
918
- const TypeId$3 = "~effect/FiberSet";
670
+ const file = (path, options) => flatMap(HttpPlatformKey, (platform) => platform.fileResponse(path, options));
919
671
  /**
920
- * Checks whether a value is a FiberSet.
921
- *
922
- * **Example** (Checking if a value is a FiberSet)
923
- *
924
- * ```ts import.meta.vitest
925
- * import { Effect, FiberSet } from "effect"
926
- *
927
- * const program = Effect.gen(function*() {
928
- * const set = yield* FiberSet.make()
672
+ * Returns a response with the specified header set to the supplied value.
929
673
  *
930
- * return [FiberSet.isFiberSet(set), FiberSet.isFiberSet({})]
931
- * })
674
+ * @category combinators
675
+ * @since 4.0.0
676
+ */
677
+ const setHeader = /*#__PURE__*/ dual(3, (self, key, value) => makeResponse({
678
+ ...self,
679
+ headers: set(self.headers, key, value)
680
+ }));
681
+ /**
682
+ * Returns a response with the specified header removed.
932
683
  *
933
- * const actual = await Effect.runPromise(Effect.scoped(program))
934
- * actual // => [true, false]
935
- * ```
684
+ * @category combinators
685
+ * @since 4.0.0
686
+ */
687
+ const removeHeader = /*#__PURE__*/ dual(2, (self, key) => makeResponse({
688
+ ...self,
689
+ headers: remove(self.headers, key)
690
+ }));
691
+ /**
692
+ * Returns a response with all supplied headers set on the existing header map.
936
693
  *
937
- * @category guards
938
- * @since 2.0.0
694
+ * @category combinators
695
+ * @since 4.0.0
939
696
  */
940
- const isFiberSet = (u) => hasProperty(u, TypeId$3);
941
- const Proto = {
942
- [TypeId$3]: TypeId$3,
943
- [Symbol.iterator]() {
944
- if (this.state._tag === "Closed") return empty$4();
945
- return this.state.backing[Symbol.iterator]();
946
- },
947
- ...PipeInspectableProto,
948
- toJSON() {
949
- return {
950
- _id: "FiberMap",
951
- state: this.state
952
- };
953
- }
954
- };
955
- const makeUnsafe = (backing, deferred) => {
956
- const self = Object.create(Proto);
957
- self.state = {
958
- _tag: "Open",
959
- backing
960
- };
961
- self.deferred = deferred;
962
- return self;
963
- };
697
+ const setHeaders = /*#__PURE__*/ dual(2, (self, input) => makeResponse({
698
+ ...self,
699
+ headers: setAll(self.headers, input)
700
+ }));
964
701
  /**
965
- * Creates a scoped `FiberSet` for storing fibers.
702
+ * Merges additional cookies into the cookies attached to an
703
+ * `HttpServerResponse`.
966
704
  *
967
705
  * **Details**
968
706
  *
969
- * When the associated Scope is closed, all fibers in the set will be
970
- * interrupted. You can add fibers to the set using `FiberSet.add` or
971
- * `FiberSet.run`, and the fibers will be automatically removed from the
972
- * FiberSet when they complete.
973
- *
974
- * **Example** (Creating a scoped FiberSet)
975
- *
976
- * ```ts import.meta.vitest
977
- * import { Effect, FiberSet } from "effect"
978
- *
979
- * const program = Effect.gen(function*() {
980
- * const set = yield* FiberSet.make()
981
- *
982
- * // run some effects and add the fibers to the set
983
- * yield* FiberSet.run(set, Effect.never)
984
- * yield* FiberSet.run(set, Effect.never)
985
- *
986
- * yield* Effect.yieldNow
987
- * return yield* FiberSet.size(set)
988
- * }).pipe(
989
- * Effect.scoped // The fibers will be interrupted when the scope is closed
990
- * )
991
- *
992
- * const actual = await Effect.runPromise(program)
993
- * actual // => 2
994
- * ```
707
+ * The original response is not mutated; a new response is returned with the merged
708
+ * cookie collection.
995
709
  *
996
- * @category constructors
997
- * @since 2.0.0
710
+ * @category combinators
711
+ * @since 4.0.0
998
712
  */
999
- const make$7 = () => acquireRelease(sync(() => makeUnsafe(/* @__PURE__ */ new Set(), makeUnsafe$1())), (set) => suspend(() => {
1000
- const state = set.state;
1001
- if (state._tag === "Closed") return void_;
1002
- set.state = { _tag: "Closed" };
1003
- const fibers = state.backing;
1004
- return interruptAll(fibers).pipe(into(set.deferred));
713
+ const mergeCookies = /*#__PURE__*/ dual(2, (self, cookies) => makeResponse({
714
+ ...self,
715
+ cookies: merge$1(self.cookies, cookies)
1005
716
  }));
1006
- const internalFiberId = -1;
1007
- const isInternalInterruption = /*#__PURE__*/ toPredicate(/*#__PURE__*/ compose(filterInterruptors, /*#__PURE__*/ has(internalFiberId)));
1008
717
  /**
1009
- * Adds an existing fiber to the `FiberSet` using a synchronous, unsafe
1010
- * mutation.
1011
- *
1012
- * **When to use**
1013
- *
1014
- * Use when an already forked fiber must be registered immediately and
1015
- * synchronous interruption on a closed set is acceptable.
718
+ * Replaces the body of an `HttpServerResponse`.
1016
719
  *
1017
720
  * **Details**
1018
721
  *
1019
- * When the fiber completes, it is removed from the set. If the set is already
1020
- * closed, the supplied fiber is interrupted immediately. Non-interruption
1021
- * failures are recorded for `FiberSet.join`.
1022
- *
1023
- * **Example** (Adding a fiber unsafely)
1024
- *
1025
- * ```ts import.meta.vitest
1026
- * import { Effect, FiberSet } from "effect"
1027
- *
1028
- * const program = Effect.gen(function*() {
1029
- * const set = yield* FiberSet.make()
1030
- * const fiber = yield* Effect.forkChild(Effect.never)
722
+ * When the body carries a content type or content length, the returned response
723
+ * includes the corresponding headers.
1031
724
  *
1032
- * // Unsafe add - doesn't return an Effect
1033
- * FiberSet.addUnsafe(set, fiber)
725
+ * @category combinators
726
+ * @since 4.0.0
727
+ */
728
+ const setBody = /*#__PURE__*/ dual(2, (self, body) => makeResponse({
729
+ ...self,
730
+ body
731
+ }));
732
+ /**
733
+ * Sets the HTTP status code of an `HttpServerResponse`.
1034
734
  *
1035
- * // The fiber is now managed by the set
1036
- * return yield* FiberSet.size(set)
1037
- * })
735
+ * **Details**
1038
736
  *
1039
- * const actual = await Effect.runPromise(Effect.scoped(program))
1040
- * actual // => 1
1041
- * ```
737
+ * When `statusText` is omitted, the existing status text is preserved.
1042
738
  *
1043
739
  * @category combinators
1044
740
  * @since 4.0.0
1045
741
  */
1046
- const addUnsafe = /*#__PURE__*/ dual((args) => isFiberSet(args[0]), (self, fiber, options) => {
1047
- if (self.state._tag === "Closed") {
1048
- fiber.interruptUnsafe(internalFiberId);
1049
- return;
1050
- } else if (self.state.backing.has(fiber)) return;
1051
- self.state.backing.add(fiber);
1052
- fiber.addObserver((exit) => {
1053
- if (self.state._tag === "Closed") return;
1054
- self.state.backing.delete(fiber);
1055
- if (isFailure(exit) && (options?.propagateInterruption === true ? !isInternalInterruption(exit.cause) : !hasInterruptsOnly(exit.cause))) doneUnsafe(self.deferred, exit);
1056
- });
1057
- });
1058
- const constInterruptedFiber = /*#__PURE__*/ function() {
1059
- let fiber = void 0;
1060
- return () => {
1061
- if (fiber === void 0) fiber = runFork(interrupt);
1062
- return fiber;
1063
- };
1064
- }();
742
+ const setStatus = /*#__PURE__*/ dual((args) => isHttpServerResponse(args[0]), (self, status, statusText) => makeResponse({
743
+ ...self,
744
+ status,
745
+ statusText: statusText ?? self.statusText
746
+ }));
747
+ const Proto = {
748
+ ...PipeInspectableProto,
749
+ [TypeId$4]: TypeId$4,
750
+ [ignore]: true,
751
+ toJSON() {
752
+ return {
753
+ _id: "HttpServerResponse",
754
+ status: this.status,
755
+ statusText: this.statusText,
756
+ headers: redact$1(this.headers),
757
+ cookies: this.cookies.toJSON(),
758
+ body: this.body.toJSON()
759
+ };
760
+ }
761
+ };
762
+ const makeResponse = (options) => {
763
+ const self = Object.create(Proto);
764
+ self.status = options.status;
765
+ self.statusText = options.statusText;
766
+ self.cookies = options.cookies ?? empty$1;
767
+ self.body = options.body ?? empty$3;
768
+ if (self.body._tag !== "Empty" && (self.body.contentType || self.body.contentLength)) {
769
+ const newHeaders = fromRecordUnsafe({ ...options.headers });
770
+ if (self.body.contentType) newHeaders["content-type"] = self.body.contentType;
771
+ if (self.body.contentLength) newHeaders["content-length"] = self.body.contentLength.toString();
772
+ self.headers = newHeaders;
773
+ } else self.headers = options.headers ?? empty$2;
774
+ return self;
775
+ };
776
+ //#endregion
777
+ //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/http/internal/compression.js
778
+ /** @internal */
779
+ const varyAcceptEncoding = (headers) => {
780
+ const vary = headers["vary"];
781
+ if (vary === void 0) return "Accept-Encoding";
782
+ const members = vary.split(",").map((member) => member.trim().toLowerCase());
783
+ return members.includes("*") || members.includes("accept-encoding") ? void 0 : `${vary}, Accept-Encoding`;
784
+ };
785
+ /** @internal */
786
+ const wrapCompression = (impl) => ({
787
+ algorithms: impl.algorithms,
788
+ compressResponse(response, algorithm, options) {
789
+ return map$1(impl.compressResponse(response, algorithm, options), (compressed) => {
790
+ if (compressed === response) return response;
791
+ const headers = { "content-encoding": algorithm };
792
+ const vary = varyAcceptEncoding(compressed.headers);
793
+ if (vary !== void 0) headers["vary"] = vary;
794
+ const etag = compressed.headers["etag"];
795
+ if (etag !== void 0 && !etag.startsWith("W/")) headers["etag"] = `W/${etag}`;
796
+ return setHeaders(compressed, headers);
797
+ });
798
+ }
799
+ });
800
+ /** @internal */
801
+ const defaultCompressible = (contentType) => {
802
+ const semi = contentType.indexOf(";");
803
+ const type = (semi === -1 ? contentType : contentType.slice(0, semi)).trim().toLowerCase();
804
+ if (type.startsWith("text/")) return true;
805
+ switch (type) {
806
+ case "application/json":
807
+ case "application/javascript":
808
+ case "application/xml":
809
+ case "image/svg+xml":
810
+ case "application/wasm": return true;
811
+ }
812
+ return type.endsWith("+json") || type.endsWith("+xml");
813
+ };
814
+ const acceptMember = /^([a-z0-9!#$%&'*+.^_`|~-]+)(?:;q=(0(?:\.[0-9]{0,3})?|1(?:\.0{0,3})?))?$/;
815
+ /** @internal */
816
+ const parseAcceptEncoding = (header) => {
817
+ const trimmed = header.trim();
818
+ if (trimmed === "") return;
819
+ const accepted = /* @__PURE__ */ new Map();
820
+ for (const part of trimmed.split(",")) {
821
+ const member = part.trim().toLowerCase().replace(/[ \t]*;[ \t]*/g, ";");
822
+ const match = acceptMember.exec(member);
823
+ if (match === null) return;
824
+ accepted.set(match[1], match[2] === void 0 ? 1 : Number(match[2]));
825
+ }
826
+ return accepted;
827
+ };
828
+ /** @internal */
829
+ const negotiate = (header, preferred, supported) => {
830
+ if (header === void 0) return;
831
+ const accepted = parseAcceptEncoding(header);
832
+ if (accepted === void 0) return;
833
+ for (const algorithm of preferred) {
834
+ if (!supported.has(algorithm)) continue;
835
+ const quality = accepted.get(algorithm) ?? accepted.get("*");
836
+ if (quality !== void 0 && quality > 0) return algorithm;
837
+ }
838
+ };
839
+ //#endregion
840
+ //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/http/HttpPlatform.js
1065
841
  /**
1066
- * Forks an Effect and add the forked fiber to the FiberSet.
1067
- * When the fiber completes, it will be removed from the FiberSet.
842
+ * Platform-specific support for serving files as HTTP server responses.
1068
843
  *
1069
- * **Example** (Forking effects into a set)
844
+ * `HttpPlatform` is the boundary between the portable HTTP response model and
845
+ * the runtime that knows how to stream bytes from the host platform. Server
846
+ * code uses this service when it needs to return local files, static assets,
847
+ * downloads, byte ranges, or Web `File`-like values without constructing the
848
+ * response body by hand.
1070
849
  *
1071
- * ```ts import.meta.vitest
1072
- * import { Effect, Fiber, FiberSet } from "effect"
850
+ * @since 4.0.0
851
+ */
852
+ /**
853
+ * Service for platform-specific HTTP response helpers, including file-backed server responses.
1073
854
  *
1074
- * const program = Effect.gen(function*() {
1075
- * const set = yield* FiberSet.make()
855
+ * @category services
856
+ * @since 4.0.0
857
+ */
858
+ var HttpPlatform = class extends Service()("effect/http/HttpPlatform") {};
859
+ /**
860
+ * Creates an `HttpPlatform` service from platform-specific file response constructors, using `FileSystem` and `Etag.Generator`.
1076
861
  *
1077
- * // Fork and add to set
1078
- * const fiber1 = yield* FiberSet.run(set, Effect.succeed("hello"))
1079
- * const fiber2 = yield* FiberSet.run(set, Effect.succeed("world"))
862
+ * @category constructors
863
+ * @since 4.0.0
864
+ */
865
+ const make$7 = /*#__PURE__*/ fnUntraced(function* (impl) {
866
+ const fs = yield* FileSystem;
867
+ const etagGen = yield* Generator;
868
+ return HttpPlatform.of({
869
+ platform: impl.platform,
870
+ compression: wrapCompression(impl.compression),
871
+ fileResponse: fnUntraced(function* (path, options) {
872
+ const info = yield* fs.stat(path);
873
+ const etag = yield* etagGen.fromFileInfo(info);
874
+ const start = Number(options?.offset ?? 0);
875
+ const end = options?.bytesToRead !== void 0 ? start + Number(options.bytesToRead) : void 0;
876
+ const headers = set(options?.headers ? fromInput(options.headers) : empty$2, "etag", toString(etag));
877
+ if (isSome(info.mtime)) headers["last-modified"] = info.mtime.value.toUTCString();
878
+ const contentLength = end !== void 0 ? end - start : Number(info.size) - start;
879
+ return impl.fileResponse(path, options?.status ?? 200, options?.statusText, headers, start, end, contentLength);
880
+ }),
881
+ fileWebResponse(file, options) {
882
+ return map$1(etagGen.fromFileWeb(file), (etag) => {
883
+ const headers = merge(options?.headers ? fromInput(options.headers) : empty$2, fromRecordUnsafe({
884
+ etag: toString(etag),
885
+ "last-modified": new Date(file.lastModified).toUTCString()
886
+ }));
887
+ return impl.fileWebResponse(file, options?.status ?? 200, options?.statusText, headers, options);
888
+ });
889
+ }
890
+ });
891
+ });
892
+ //#endregion
893
+ //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/http/HttpServerRespondable.js
894
+ /**
895
+ * Converts supported values into HTTP server responses.
1080
896
  *
1081
- * // Get results
1082
- * return [yield* Fiber.join(fiber1), yield* Fiber.join(fiber2)]
1083
- * })
897
+ * Server-side errors and helper values can implement `Respondable` when they
898
+ * know which status, headers, cookies, or body should be sent to the client.
899
+ * This module detects those values and converts them to `HttpServerResponse`
900
+ * values, with fallback handling for schema errors and missing values.
1084
901
  *
1085
- * const actual = await Effect.runPromise(Effect.scoped(program))
1086
- * actual // => ["hello", "world"]
1087
- * ```
902
+ * @since 4.0.0
903
+ */
904
+ /**
905
+ * Protocol key used by values that can render themselves as
906
+ * `HttpServerResponse` values.
1088
907
  *
1089
- * @category combinators
1090
- * @since 2.0.0
908
+ * @category type IDs
909
+ * @since 4.0.0
1091
910
  */
1092
- const run = function() {
1093
- const self = arguments[0];
1094
- if (!isEffect(arguments[1])) {
1095
- const options = arguments[1];
1096
- return (effect) => runImpl(self, effect, options);
1097
- }
1098
- return runImpl(self, arguments[1], arguments[2]);
911
+ const symbol = "~effect/http/HttpServerRespondable";
912
+ /**
913
+ * Returns `true` when the supplied value implements the `Respondable` protocol.
914
+ *
915
+ * @category guards
916
+ * @since 4.0.0
917
+ */
918
+ const isRespondable = (u) => hasProperty(u, symbol);
919
+ const badRequest = /*#__PURE__*/ empty({ status: 400 });
920
+ const notFound = /*#__PURE__*/ empty({ status: 404 });
921
+ /**
922
+ * Converts a `Respondable` value into an `HttpServerResponse`.
923
+ *
924
+ * **Details**
925
+ *
926
+ * If the value is already an HTTP server response it is returned directly; errors
927
+ * from the response conversion are converted to defects.
928
+ *
929
+ * @category accessors
930
+ * @since 4.0.0
931
+ */
932
+ const toResponse = (self) => {
933
+ if (isHttpServerResponse(self)) return succeed(self);
934
+ return orDie(self[symbol]());
1099
935
  };
1100
- const runImpl = (self, effect, options) => withFiber((parent) => {
1101
- if (self.state._tag === "Closed") return sync(constInterruptedFiber);
1102
- const fiber = runForkWith(parent.context)(effect);
1103
- addUnsafe(self, fiber, options);
1104
- return succeed$1(fiber);
1105
- });
1106
936
  /**
1107
- * Captures a `Runtime` and uses it to fork effects into the `FiberSet`.
937
+ * Attempts to convert an unknown value into an `HttpServerResponse`, falling back
938
+ * to the supplied response when no conversion is available.
1108
939
  *
1109
- * **Example** (Capturing a runtime)
940
+ * **Details**
1110
941
  *
1111
- * ```ts import.meta.vitest
1112
- * import { Context, Effect, Fiber, FiberSet } from "effect"
942
+ * `HttpServerResponse` and `Respondable` values are used directly, schema errors
943
+ * become `400` responses, and no-such-element errors become `404` responses.
1113
944
  *
1114
- * class Users extends Context.Service<Users, {
1115
- * readonly getAll: Effect.Effect<Array<unknown>>
1116
- * }>()("Users") {}
945
+ * @category accessors
946
+ * @since 4.0.0
947
+ */
948
+ const toResponseOrElse = (u, orElse) => {
949
+ if (isHttpServerResponse(u)) return succeed(u);
950
+ else if (isRespondable(u)) return catchCause(u[symbol](), () => succeed(orElse));
951
+ else if (isSchemaError(u)) return succeed(badRequest);
952
+ else if (isNoSuchElementError(u)) return succeed(notFound);
953
+ return succeed(orElse);
954
+ };
955
+ /**
956
+ * Attempts to convert an unknown defect into an `HttpServerResponse`, falling
957
+ * back to the supplied response when no conversion is available.
1117
958
  *
1118
- * const program = Effect.gen(function*() {
1119
- * const set = yield* FiberSet.make()
1120
- * const run = yield* FiberSet.runtime(set)<Users>()
959
+ * **Details**
1121
960
  *
1122
- * // run some effects and add the fibers to the set
1123
- * const fiber = run(Effect.andThen(Users, (_) => _.getAll))
1124
- * return (yield* Fiber.join(fiber)).length
1125
- * }).pipe(
1126
- * Effect.scoped // The fibers will be interrupted when the scope is closed
1127
- * )
961
+ * Only `HttpServerResponse` and `Respondable` values receive special handling.
1128
962
  *
1129
- * const actual = await Effect.runPromise(Effect.provideService(program, Users, {
1130
- * getAll: Effect.succeed([])
1131
- * }))
1132
- * actual // => 0
1133
- * ```
963
+ * @category accessors
964
+ * @since 4.0.0
965
+ */
966
+ const toResponseOrElseDefect = (u, orElse) => {
967
+ if (isHttpServerResponse(u)) return succeed(u);
968
+ else if (isRespondable(u)) return catchCause(u[symbol](), () => succeed(orElse));
969
+ return succeed(orElse);
970
+ };
971
+ //#endregion
972
+ //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/http/HttpServerError.js
973
+ /**
974
+ * Describes failures raised while handling HTTP server requests.
1134
975
  *
1135
- * @category combinators
1136
- * @since 2.0.0
976
+ * `HttpServerError` covers failures that happen while accepting a request,
977
+ * matching a route, running a handler, or building and sending a response.
978
+ * Request-scoped failures keep the request that caused them, and response
979
+ * failures keep the response being produced. This module also includes helpers
980
+ * for turning failed causes or exits into HTTP responses and an annotation for
981
+ * interrupts caused by client aborts.
982
+ *
983
+ * @since 4.0.0
1137
984
  */
1138
- const runtime = (self) => () => map$1(context(), (services) => {
1139
- const runFork = runForkWith(services);
1140
- return (effect, options) => {
1141
- if (self.state._tag === "Closed") return constInterruptedFiber();
1142
- const fiber = runFork(effect, options);
1143
- addUnsafe(self, fiber, options);
1144
- return fiber;
1145
- };
1146
- });
985
+ const TypeId$3 = "~effect/http/HttpServerError";
1147
986
  /**
1148
- * Joins all fibers in the FiberSet. If any fiber in the set terminates with a failure,
1149
- * the returned Effect will terminate with the first failure that occurred.
987
+ * Tagged error for failures that occur while handling an HTTP server request.
1150
988
  *
1151
- * **Example** (Joining failing fibers)
989
+ * **Details**
1152
990
  *
1153
- * ```ts import.meta.vitest
1154
- * import { Effect, Exit, FiberSet } from "effect"
991
+ * It wraps a `HttpServerErrorReason`, exposes the associated request and optional
992
+ * response, and can be converted to an HTTP response through the `Respondable`
993
+ * protocol.
1155
994
  *
1156
- * const program = Effect.gen(function*() {
1157
- * const set = yield* FiberSet.make()
1158
- * yield* FiberSet.add(set, Effect.runFork(Effect.fail("error")))
995
+ * @category errors
996
+ * @since 4.0.0
997
+ */
998
+ var HttpServerError = class extends TaggedError("HttpServerError") {
999
+ constructor(props) {
1000
+ if ("cause" in props.reason) super({
1001
+ ...props,
1002
+ cause: props.reason.cause
1003
+ });
1004
+ else super(props);
1005
+ }
1006
+ [TypeId$3] = TypeId$3;
1007
+ stack = `${this.name}: ${this.message}`;
1008
+ get request() {
1009
+ return this.reason.request;
1010
+ }
1011
+ get response() {
1012
+ return "response" in this.reason ? this.reason.response : void 0;
1013
+ }
1014
+ [symbol]() {
1015
+ return this.reason[symbol]();
1016
+ }
1017
+ get [ignore]() {
1018
+ return this.reason["~effect/ErrorReporter/ignore"] ?? false;
1019
+ }
1020
+ get message() {
1021
+ return this.reason.message;
1022
+ }
1023
+ };
1024
+ /**
1025
+ * Error describing a failure to parse or read an incoming request.
1159
1026
  *
1160
- * // parent fiber will fail with "error"
1161
- * yield* FiberSet.join(set)
1162
- * })
1027
+ * **Details**
1163
1028
  *
1164
- * const actual = await Effect.runPromise(Effect.exit(Effect.scoped(program)))
1165
- * actual // => Exit.fail("error")
1166
- * ```
1029
+ * When converted to a response it produces an empty `400` response.
1167
1030
  *
1168
- * @category combinators
1169
- * @since 2.0.0
1031
+ * @category errors
1032
+ * @since 4.0.0
1170
1033
  */
1171
- const join = (self) => _await(self.deferred);
1034
+ var RequestParseError = class extends TaggedError("RequestParseError") {
1035
+ /**
1036
+ * Converts the request error into a `400 Bad Request` response.
1037
+ *
1038
+ * @since 4.0.0
1039
+ */
1040
+ [symbol]() {
1041
+ return succeed(empty({ status: 400 }));
1042
+ }
1043
+ get methodAndUrl() {
1044
+ return `${this.request.method} ${this.request.url}`;
1045
+ }
1046
+ get message() {
1047
+ return formatRequestMessage(this._tag, this.description, this.methodAndUrl);
1048
+ }
1049
+ };
1172
1050
  /**
1173
- * Waits until the fiber set is empty.
1051
+ * Error indicating that no route matched the incoming request.
1174
1052
  *
1175
- * **Example** (Waiting for an empty set)
1053
+ * **Details**
1176
1054
  *
1177
- * ```ts import.meta.vitest
1178
- * import { Effect, FiberSet } from "effect"
1055
+ * When converted to a response it produces an empty `404` response, and it is
1056
+ * ignored by the error reporter.
1179
1057
  *
1180
- * const program = Effect.gen(function*() {
1181
- * const set = yield* FiberSet.make()
1058
+ * @category errors
1059
+ * @since 4.0.0
1060
+ */
1061
+ var RouteNotFound = class extends TaggedError("RouteNotFound") {
1062
+ [symbol]() {
1063
+ return succeed(empty({ status: 404 }));
1064
+ }
1065
+ [ignore] = true;
1066
+ get methodAndUrl() {
1067
+ return `${this.request.method} ${this.request.url}`;
1068
+ }
1069
+ get message() {
1070
+ return formatRequestMessage(this._tag, this.description, this.methodAndUrl);
1071
+ }
1072
+ };
1073
+ TaggedError("InternalError");
1074
+ /**
1075
+ * Error describing a failure related to an HTTP response.
1182
1076
  *
1183
- * yield* FiberSet.run(set, Effect.yieldNow)
1184
- * yield* FiberSet.run(set, Effect.yieldNow)
1077
+ * **Details**
1185
1078
  *
1186
- * // Wait for all fibers to complete
1187
- * yield* FiberSet.awaitEmpty(set)
1079
+ * It carries the request and response involved in the failure. When converted to
1080
+ * a response it produces an empty `500` response.
1188
1081
  *
1189
- * return yield* FiberSet.size(set)
1190
- * })
1082
+ * @category errors
1083
+ * @since 4.0.0
1084
+ */
1085
+ var ResponseError = class extends TaggedError("ResponseError") {
1086
+ [symbol]() {
1087
+ return succeed(empty({ status: 500 }));
1088
+ }
1089
+ get methodAndUrl() {
1090
+ return `${this.request.method} ${this.request.url}`;
1091
+ }
1092
+ get message() {
1093
+ const info = `${this._tag} (${this.response.status} ${this.methodAndUrl})`;
1094
+ return this.description ? `${info}: ${this.description}` : info;
1095
+ }
1096
+ };
1097
+ /**
1098
+ * Error wrapping a low-level failure from the HTTP server implementation.
1191
1099
  *
1192
- * const actual = await Effect.runPromise(Effect.scoped(program))
1193
- * actual // => 0
1194
- * ```
1100
+ * @category errors
1101
+ * @since 4.0.0
1102
+ */
1103
+ var ServeError = class extends TaggedError("ServeError") {};
1104
+ /**
1105
+ * Context annotation used to mark an interrupt as caused by the client aborting
1106
+ * the request.
1195
1107
  *
1196
- * @category combinators
1197
- * @since 3.13.0
1108
+ * **Details**
1109
+ *
1110
+ * `causeResponse` uses this annotation to map a pure client abort to a `499`
1111
+ * response instead of a server abort response.
1112
+ *
1113
+ * @category services
1114
+ * @since 4.0.0
1198
1115
  */
1199
- const awaitEmpty = (self) => whileLoop({
1200
- while: () => self.state._tag === "Open" && self.state.backing.size > 0,
1201
- body: () => await_(headUnsafe(self)),
1202
- step: constVoid
1203
- });
1116
+ var ClientAbort = class extends Service()("effect/http/HttpServerError/ClientAbort") {
1117
+ static annotation = /*#__PURE__*/ this.context(true).pipe(/*#__PURE__*/ add(StackTrace, {
1118
+ name: "ClientAbort",
1119
+ stack: constUndefined,
1120
+ parent: void 0
1121
+ }));
1122
+ };
1123
+ const formatRequestMessage = (reason, description, info) => {
1124
+ const prefix = `${reason} (${info})`;
1125
+ return description ? `${prefix}: ${description}` : prefix;
1126
+ };
1127
+ /**
1128
+ * Converts a failed handler cause into the HTTP response that should be sent and
1129
+ * the cause that should be reported.
1130
+ *
1131
+ * **Details**
1132
+ *
1133
+ * Respondable failures and defects can choose their own response, defects that
1134
+ * are already `HttpServerResponse` values are used directly, and pure interrupts
1135
+ * produce either `499` for client aborts or `503` for server aborts.
1136
+ *
1137
+ * @category error handling
1138
+ * @since 4.0.0
1139
+ */
1140
+ const causeResponse = (cause) => {
1141
+ let response;
1142
+ let effect = succeedInternalServerError;
1143
+ const failures = [];
1144
+ let interrupts = [];
1145
+ let isClientInterrupt = false;
1146
+ for (let i = 0; i < cause.reasons.length; i++) {
1147
+ const reason = cause.reasons[i];
1148
+ switch (reason._tag) {
1149
+ case "Fail":
1150
+ effect = toResponseOrElse(reason.error, internalServerError);
1151
+ failures.push(reason);
1152
+ break;
1153
+ case "Die":
1154
+ if (isHttpServerResponse(reason.defect)) response = reason.defect;
1155
+ else {
1156
+ effect = toResponseOrElseDefect(reason.defect, internalServerError);
1157
+ failures.push(reason);
1158
+ }
1159
+ break;
1160
+ case "Interrupt":
1161
+ isClientInterrupt = reason.annotations.has(ClientAbort.key);
1162
+ if (failures.length > 0) break;
1163
+ interrupts.push(reason);
1164
+ break;
1165
+ }
1166
+ }
1167
+ if (response) return succeed([response, fromReasons(failures)]);
1168
+ else if (interrupts.length > 0 && failures.length === 0) {
1169
+ failures.push(...interrupts);
1170
+ effect = isClientInterrupt ? clientAbortError : serverAbortError;
1171
+ }
1172
+ return mapEager(effect, (response) => {
1173
+ failures.push(makeDieReason(response));
1174
+ return [response, fromReasons(failures)];
1175
+ });
1176
+ };
1177
+ /**
1178
+ * Derives an HTTP response from a failed handler cause synchronously.
1179
+ *
1180
+ * **Details**
1181
+ *
1182
+ * If the cause contains a defect that is already an `HttpServerResponse`, that
1183
+ * response is used and removed from the remaining cause. Otherwise the response
1184
+ * defaults to `500`.
1185
+ *
1186
+ * @category error handling
1187
+ * @since 4.0.0
1188
+ */
1189
+ const causeResponseStripped = (cause) => {
1190
+ let response;
1191
+ const failures = cause.reasons.filter((f) => {
1192
+ if (f._tag === "Die" && isHttpServerResponse(f.defect)) {
1193
+ response = f.defect;
1194
+ return false;
1195
+ }
1196
+ return true;
1197
+ });
1198
+ return [response ?? internalServerError, failures.length > 0 ? some(fromReasons(failures)) : none()];
1199
+ };
1200
+ const internalServerError = /*#__PURE__*/ empty({ status: 500 });
1201
+ const succeedInternalServerError = /*#__PURE__*/ succeed(internalServerError);
1202
+ const clientAbortError = /*#__PURE__*/ succeed(/*#__PURE__*/ empty({ status: 499 }));
1203
+ const serverAbortError = /*#__PURE__*/ succeed(/*#__PURE__*/ empty({ status: 503 }));
1204
1204
  //#endregion
1205
1205
  //#region ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6/node_modules/effect/dist/unstable/socket/Socket.js
1206
1206
  /**
@@ -1448,7 +1448,7 @@ var WebSocketConstructor = class extends Service()("@effect/platform/Socket/WebS
1448
1448
  * @category layers
1449
1449
  * @since 4.0.0
1450
1450
  */
1451
- const layerWebSocketConstructorGlobal = /*#__PURE__*/ succeed(WebSocketConstructor)((url, protocols) => new globalThis.WebSocket(url, protocols));
1451
+ const layerWebSocketConstructorGlobal = /*#__PURE__*/ succeed$1(WebSocketConstructor)((url, protocols) => new globalThis.WebSocket(url, protocols));
1452
1452
  /**
1453
1453
  * Creates a `Socket` backed by a `WebSocketConstructor`, acquiring the
1454
1454
  * WebSocket for each run and using the close-code classifier to decide which
@@ -1457,7 +1457,7 @@ const layerWebSocketConstructorGlobal = /*#__PURE__*/ succeed(WebSocketConstruct
1457
1457
  * @category constructors
1458
1458
  * @since 4.0.0
1459
1459
  */
1460
- const makeWebSocket = (url, options) => WebSocketConstructor.use((makeWs) => fromWebSocket(acquireRelease((typeof url === "string" ? succeed$1(url) : url).pipe(map$1((url) => makeWs(url, options?.protocols))), (ws) => sync(() => ws.close(1e3))), options));
1460
+ const makeWebSocket = (url, options) => WebSocketConstructor.use((makeWs) => fromWebSocket(acquireRelease((typeof url === "string" ? succeed(url) : url).pipe(map$1((url) => makeWs(url, options?.protocols))), (ws) => sync(() => ws.close(1e3))), options));
1461
1461
  /**
1462
1462
  * Builds a `Socket` from a scoped WebSocket acquisition effect, waiting for the
1463
1463
  * socket to open, dispatching message handlers in fibers, and translating
@@ -1473,7 +1473,7 @@ const fromWebSocket = (acquire, options) => withFiber((fiber) => {
1473
1473
  const acquireContext = fiber.context;
1474
1474
  const closeCodeIsError = options?.closeCodeIsError ?? defaultCloseCodeIsError;
1475
1475
  const runRaw = (handler, opts) => scopedWith(fnUntraced(function* (scope) {
1476
- const fiberSet = yield* make$7().pipe(provide(scope));
1476
+ const fiberSet = yield* make$8().pipe(provide(scope));
1477
1477
  const ws = yield* provide(acquire, scope);
1478
1478
  const run = yield* provideService(runtime(fiberSet)(), WebSocket, ws);
1479
1479
  let open = false;
@@ -1540,8 +1540,8 @@ const fromWebSocket = (acquire, options) => withFiber((fiber) => {
1540
1540
  if (isCloseEvent(chunk)) ws.close(chunk.code, chunk.reason);
1541
1541
  else ws.send(chunk);
1542
1542
  }));
1543
- const writer = succeed$1(write);
1544
- return succeed$1(make$6({
1543
+ const writer = succeed(write);
1544
+ return succeed(make$6({
1545
1545
  runRaw,
1546
1546
  writer
1547
1547
  }));
@@ -2521,7 +2521,7 @@ var MultipartError = class MultipartError extends TaggedError("MultipartError")
2521
2521
  * @since 4.0.0
2522
2522
  */
2523
2523
  [symbol]() {
2524
- return succeed$1(empty({ status: responseStatusByReason[this.reason._tag] }));
2524
+ return succeed(empty({ status: responseStatusByReason[this.reason._tag] }));
2525
2525
  }
2526
2526
  /**
2527
2527
  * Uses the concrete multipart error reason as the public message.
@@ -2546,7 +2546,7 @@ var MultipartError = class MultipartError extends TaggedError("MultipartError")
2546
2546
  */
2547
2547
  const makeConfig = (headers) => withFiber((fiber) => {
2548
2548
  const mimeTypes = get(fiber.context, FieldMimeTypes);
2549
- return succeed$1({
2549
+ return succeed({
2550
2550
  headers,
2551
2551
  maxParts: fiber.getRef(MaxParts),
2552
2552
  maxFieldSize: Number(fiber.getRef(MaxFieldSize)),
@@ -2983,10 +2983,10 @@ const cors = (options) => {
2983
2983
  ...maxAge
2984
2984
  });
2985
2985
  };
2986
- const preResponseHandler = (request, response) => succeed$1(setHeaders(response, headersFromRequest(request)));
2986
+ const preResponseHandler = (request, response) => succeed(setHeaders(response, headersFromRequest(request)));
2987
2987
  return (httpApp) => withFiber((fiber) => {
2988
2988
  const request = getUnsafe(fiber.context, HttpServerRequest);
2989
- if (request.method === "OPTIONS") return succeed$1(empty({
2989
+ if (request.method === "OPTIONS") return succeed(empty({
2990
2990
  status: 204,
2991
2991
  headers: headersFromRequestOptions(request)
2992
2992
  }));
@@ -3051,19 +3051,19 @@ const compression = (options) => {
3051
3051
  zstd: { level: levels.zstd }
3052
3052
  };
3053
3053
  const transform = (compression, acceptEncoding, response) => {
3054
- if (response.status < 200 || response.status === 204 || response.status === 206 || response.status === 304) return succeed$1(response);
3054
+ if (response.status < 200 || response.status === 204 || response.status === 206 || response.status === 304) return succeed(response);
3055
3055
  const currentEncoding = response.headers["content-encoding"];
3056
- if (currentEncoding !== void 0) return succeed$1(currentEncoding.trim().toLowerCase() === "identity" ? removeHeader(response, "content-encoding") : response);
3056
+ if (currentEncoding !== void 0) return succeed(currentEncoding.trim().toLowerCase() === "identity" ? removeHeader(response, "content-encoding") : response);
3057
3057
  const body = response.body;
3058
- if (body._tag === "Empty" || body._tag === "FormData") return succeed$1(response);
3058
+ if (body._tag === "Empty" || body._tag === "FormData") return succeed(response);
3059
3059
  const cacheControl = response.headers["cache-control"];
3060
- if (cacheControl !== void 0 && noTransformRegex.test(cacheControl)) return succeed$1(response);
3060
+ if (cacheControl !== void 0 && noTransformRegex.test(cacheControl)) return succeed(response);
3061
3061
  const contentType = response.headers["content-type"] ?? body.contentType;
3062
- if (contentType === void 0 || !compressible(contentType)) return succeed$1(response);
3062
+ if (contentType === void 0 || !compressible(contentType)) return succeed(response);
3063
3063
  const algorithm = negotiate(acceptEncoding, preferred, compression.algorithms);
3064
- if (algorithm === void 0) return succeed$1(withVary(response));
3064
+ if (algorithm === void 0) return succeed(withVary(response));
3065
3065
  const contentLength = body.contentLength ?? contentLengthHeader(response.headers);
3066
- if (contentLength !== void 0 && contentLength < minSize) return succeed$1(withVary(response));
3066
+ if (contentLength !== void 0 && contentLength < minSize) return succeed(withVary(response));
3067
3067
  return compression.compressResponse(response, algorithm, levelOptions[algorithm]);
3068
3068
  };
3069
3069
  return (httpApp) => withFiber((fiber) => {
@@ -3109,7 +3109,7 @@ const toHandled = (self, handleResponse, middleware) => {
3109
3109
  reportCauseUnsafe(fiber, cause);
3110
3110
  const request = getUnsafe(fiber.context, HttpServerRequest);
3111
3111
  const handler = requestPreResponseHandlers.get(request.source);
3112
- const cont = cause.reasons.length === 0 ? succeed$1(response) : failCause$1(cause);
3112
+ const cont = cause.reasons.length === 0 ? succeed(response) : failCause$1(cause);
3113
3113
  if (handler === void 0) {
3114
3114
  request[handledSymbol] = true;
3115
3115
  return flatMapEager(handleResponse(request, response), () => cont);
@@ -4697,6 +4697,6 @@ _Mime_extensionToType = /* @__PURE__ */ new WeakMap(), _Mime_typeToExtension = /
4697
4697
  */
4698
4698
  var Mime_default = new Mime(types, types$1)._freeze();
4699
4699
  //#endregion
4700
- export { redirect as $, layerWebSocketConstructorGlobal as A, RouteNotFound as B, limitsServices as C, make$2 as D, decodeField as E, runtime as F, HttpPlatform as G, causeResponse as H, ClientAbort as I, file as J, make$8 as K, HttpServerError as L, awaitEmpty as M, make$7 as N, CloseEvent as O, run as P, raw as Q, RequestParseError as R, TypeId$1 as S, toPersisted as T, symbol as U, ServeError as V, toResponse as W, jsonUnsafe as X, isHttpServerResponse as Y, mergeCookies as Z, schemaCookies as _, serve as a, setStatus as at, toURL as b, appendPreResponseHandlerUnsafe as c, uint8Array as ct, cors as d, layer as dt, removeHeader as et, logger as f, layerWeak as ft, TypeId as g, ParsedSearchParams as h, make as i, setHeaders as it, makeWebSocket as j, fromWebSocket as k, toHandled as l, urlParams as lt, HttpServerRequest as m, HttpServer as n, setBody as nt, withLogAddress as o, stream as ot, withLoggerDisabled as p, map as pt, empty as q, layerTestClient as r, setHeader as rt, appendPreResponseHandler as s, text as st, Mime_default as t, schemaJson as tt, compression as u, ignore as ut, schemaHeaders as v, makeConfig as w, MultipartError as x, schemaSearchParams as y, ResponseError as z };
4700
+ export { setHeader as $, layerWebSocketConstructorGlobal as A, toResponse as B, limitsServices as C, make$2 as D, decodeField as E, ResponseError as F, isHttpServerResponse as G, make$7 as H, RouteNotFound as I, raw as J, jsonUnsafe as K, ServeError as L, ClientAbort as M, HttpServerError as N, CloseEvent as O, RequestParseError as P, setBody as Q, causeResponse as R, TypeId$1 as S, toPersisted as T, empty as U, HttpPlatform as V, file as W, removeHeader as X, redirect as Y, schemaJson as Z, schemaCookies as _, serve as a, urlParams as at, toURL as b, appendPreResponseHandlerUnsafe as c, awaitEmpty as ct, cors as d, runtime as dt, setHeaders as et, logger as f, ignore as ft, TypeId as g, ParsedSearchParams as h, make as i, uint8Array as it, makeWebSocket as j, fromWebSocket as k, toHandled as l, make$8 as lt, HttpServerRequest as m, HttpServer as n, stream as nt, withLogAddress as o, layer as ot, withLoggerDisabled as p, map as pt, mergeCookies as q, layerTestClient as r, text as rt, appendPreResponseHandler as s, layerWeak as st, Mime_default as t, setStatus as tt, compression as u, run as ut, schemaHeaders as v, makeConfig as w, MultipartError as x, schemaSearchParams as y, symbol as z };
4701
4701
 
4702
- //# sourceMappingURL=Mime-C6O17O_3.mjs.map
4702
+ //# sourceMappingURL=Mime-mwjBDTG5.mjs.map