effect 4.0.0-beta.33 → 4.0.0-beta.35

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 (132) hide show
  1. package/dist/Channel.d.ts +10 -1
  2. package/dist/Channel.d.ts.map +1 -1
  3. package/dist/Channel.js +5 -1
  4. package/dist/Channel.js.map +1 -1
  5. package/dist/Config.d.ts +4 -0
  6. package/dist/Config.d.ts.map +1 -1
  7. package/dist/Config.js.map +1 -1
  8. package/dist/Effect.d.ts +5 -3
  9. package/dist/Effect.d.ts.map +1 -1
  10. package/dist/Effect.js +4 -4
  11. package/dist/Effect.js.map +1 -1
  12. package/dist/FileSystem.d.ts.map +1 -1
  13. package/dist/FileSystem.js +2 -1
  14. package/dist/FileSystem.js.map +1 -1
  15. package/dist/Graph.d.ts.map +1 -1
  16. package/dist/Graph.js +2 -1
  17. package/dist/Graph.js.map +1 -1
  18. package/dist/Layer.d.ts +5 -2
  19. package/dist/Layer.d.ts.map +1 -1
  20. package/dist/Layer.js +14 -1
  21. package/dist/Layer.js.map +1 -1
  22. package/dist/MutableHashMap.d.ts +7 -0
  23. package/dist/MutableHashMap.d.ts.map +1 -1
  24. package/dist/MutableHashMap.js +8 -0
  25. package/dist/MutableHashMap.js.map +1 -1
  26. package/dist/MutableHashSet.d.ts +7 -0
  27. package/dist/MutableHashSet.d.ts.map +1 -1
  28. package/dist/MutableHashSet.js +8 -0
  29. package/dist/MutableHashSet.js.map +1 -1
  30. package/dist/Resource.d.ts.map +1 -1
  31. package/dist/Resource.js +2 -1
  32. package/dist/Resource.js.map +1 -1
  33. package/dist/Schema.d.ts +21 -0
  34. package/dist/Schema.d.ts.map +1 -1
  35. package/dist/Schema.js +20 -0
  36. package/dist/Schema.js.map +1 -1
  37. package/dist/Stream.d.ts +10 -1
  38. package/dist/Stream.d.ts.map +1 -1
  39. package/dist/Stream.js +5 -1
  40. package/dist/Stream.js.map +1 -1
  41. package/dist/SubscriptionRef.d.ts.map +1 -1
  42. package/dist/SubscriptionRef.js +2 -1
  43. package/dist/SubscriptionRef.js.map +1 -1
  44. package/dist/TxDeferred.d.ts.map +1 -1
  45. package/dist/TxDeferred.js +2 -1
  46. package/dist/TxDeferred.js.map +1 -1
  47. package/dist/TxHashMap.d.ts.map +1 -1
  48. package/dist/TxHashMap.js +2 -1
  49. package/dist/TxHashMap.js.map +1 -1
  50. package/dist/TxHashSet.d.ts +1 -1
  51. package/dist/TxHashSet.d.ts.map +1 -1
  52. package/dist/TxHashSet.js +2 -1
  53. package/dist/TxHashSet.js.map +1 -1
  54. package/dist/TxPriorityQueue.d.ts +1 -1
  55. package/dist/TxPriorityQueue.d.ts.map +1 -1
  56. package/dist/TxPriorityQueue.js +2 -1
  57. package/dist/TxPriorityQueue.js.map +1 -1
  58. package/dist/TxSemaphore.d.ts.map +1 -1
  59. package/dist/TxSemaphore.js +2 -1
  60. package/dist/TxSemaphore.js.map +1 -1
  61. package/dist/internal/dateTime.js +8 -1
  62. package/dist/internal/dateTime.js.map +1 -1
  63. package/dist/internal/effect.js +1 -1
  64. package/dist/internal/effect.js.map +1 -1
  65. package/dist/unstable/ai/AiError.d.ts +2 -3
  66. package/dist/unstable/ai/AiError.d.ts.map +1 -1
  67. package/dist/unstable/ai/AiError.js +8 -6
  68. package/dist/unstable/ai/AiError.js.map +1 -1
  69. package/dist/unstable/ai/EmbeddingModel.d.ts +130 -0
  70. package/dist/unstable/ai/EmbeddingModel.d.ts.map +1 -0
  71. package/dist/unstable/ai/EmbeddingModel.js +127 -0
  72. package/dist/unstable/ai/EmbeddingModel.js.map +1 -0
  73. package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
  74. package/dist/unstable/ai/LanguageModel.js +34 -8
  75. package/dist/unstable/ai/LanguageModel.js.map +1 -1
  76. package/dist/unstable/ai/ResponseIdTracker.js +3 -3
  77. package/dist/unstable/ai/ResponseIdTracker.js.map +1 -1
  78. package/dist/unstable/ai/Tool.d.ts +1 -1
  79. package/dist/unstable/ai/Tool.d.ts.map +1 -1
  80. package/dist/unstable/ai/Tool.js +1 -1
  81. package/dist/unstable/ai/Tool.js.map +1 -1
  82. package/dist/unstable/ai/index.d.ts +17 -0
  83. package/dist/unstable/ai/index.d.ts.map +1 -1
  84. package/dist/unstable/ai/index.js +17 -0
  85. package/dist/unstable/ai/index.js.map +1 -1
  86. package/dist/unstable/cli/CliOutput.js +4 -3
  87. package/dist/unstable/cli/CliOutput.js.map +1 -1
  88. package/dist/unstable/http/Url.d.ts +604 -0
  89. package/dist/unstable/http/Url.d.ts.map +1 -0
  90. package/dist/unstable/http/Url.js +256 -0
  91. package/dist/unstable/http/Url.js.map +1 -0
  92. package/dist/unstable/http/index.d.ts +4 -0
  93. package/dist/unstable/http/index.d.ts.map +1 -1
  94. package/dist/unstable/http/index.js +4 -0
  95. package/dist/unstable/http/index.js.map +1 -1
  96. package/dist/unstable/httpapi/HttpApiMiddleware.d.ts +30 -1
  97. package/dist/unstable/httpapi/HttpApiMiddleware.d.ts.map +1 -1
  98. package/dist/unstable/httpapi/HttpApiMiddleware.js +27 -0
  99. package/dist/unstable/httpapi/HttpApiMiddleware.js.map +1 -1
  100. package/dist/unstable/rpc/RpcSerialization.js +1 -1
  101. package/dist/unstable/rpc/RpcSerialization.js.map +1 -1
  102. package/package.json +1 -1
  103. package/src/Channel.ts +11 -1
  104. package/src/Config.ts +5 -0
  105. package/src/Effect.ts +8 -7
  106. package/src/FileSystem.ts +2 -1
  107. package/src/Graph.ts +2 -1
  108. package/src/Layer.ts +27 -9
  109. package/src/MutableHashMap.ts +9 -0
  110. package/src/MutableHashSet.ts +9 -0
  111. package/src/Resource.ts +2 -1
  112. package/src/Schema.ts +30 -0
  113. package/src/Stream.ts +11 -1
  114. package/src/SubscriptionRef.ts +2 -1
  115. package/src/TxDeferred.ts +2 -2
  116. package/src/TxHashMap.ts +2 -1
  117. package/src/TxHashSet.ts +2 -2
  118. package/src/TxPriorityQueue.ts +2 -3
  119. package/src/TxSemaphore.ts +2 -1
  120. package/src/internal/dateTime.ts +8 -1
  121. package/src/internal/effect.ts +15 -6
  122. package/src/unstable/ai/AiError.ts +5 -5
  123. package/src/unstable/ai/EmbeddingModel.ts +209 -0
  124. package/src/unstable/ai/LanguageModel.ts +44 -8
  125. package/src/unstable/ai/ResponseIdTracker.ts +3 -3
  126. package/src/unstable/ai/Tool.ts +2 -2
  127. package/src/unstable/ai/index.ts +18 -0
  128. package/src/unstable/cli/CliOutput.ts +5 -4
  129. package/src/unstable/http/Url.ts +650 -0
  130. package/src/unstable/http/index.ts +5 -0
  131. package/src/unstable/httpapi/HttpApiMiddleware.ts +46 -1
  132. package/src/unstable/rpc/RpcSerialization.ts +1 -1
@@ -0,0 +1,650 @@
1
+ /**
2
+ * @since 4.0.0
3
+ */
4
+ import * as Cause from "../../Cause.ts"
5
+ import { dual } from "../../Function.ts"
6
+ import * as Redacted from "../../Redacted.ts"
7
+ import * as Result from "../../Result.ts"
8
+ import * as UrlParams from "./UrlParams.ts"
9
+
10
+ /**
11
+ * Parses a URL string into a `URL` object, returning an `Result` type for safe
12
+ * error handling.
13
+ *
14
+ * **Details**
15
+ *
16
+ * This function converts a string into a `URL` object, enabling safe URL
17
+ * parsing with built-in error handling. If the string is invalid or fails to
18
+ * parse, this function does not throw an error; instead, it wraps the error in
19
+ * a `IllegalArgumentError` and returns it as the `Failure` value of an
20
+ * `Result`. The `Success` value contains the successfully parsed `URL`.
21
+ *
22
+ * An optional `base` parameter can be provided to resolve relative URLs. If
23
+ * specified, the function interprets the input `url` as relative to this
24
+ * `base`. This is especially useful when dealing with URLs that might not be
25
+ * fully qualified.
26
+ *
27
+ * **Example**
28
+ *
29
+ * ```ts
30
+ * import { Url } from "effect/unstable/http"
31
+ * import { Result } from "effect"
32
+ *
33
+ * // Parse an absolute URL
34
+ * //
35
+ * // ┌─── Result<URL, IllegalArgumentError>
36
+ * // ▼
37
+ * const parsed = Url.fromString("https://example.com/path")
38
+ *
39
+ * if (Result.isSuccess(parsed)) {
40
+ * console.log("Parsed URL:", parsed.success.toString())
41
+ * } else {
42
+ * console.log("Error:", parsed.failure.message)
43
+ * }
44
+ * // Output: Parsed URL: https://example.com/path
45
+ *
46
+ * // Parse a relative URL with a base
47
+ * const relativeParsed = Url.fromString("/relative-path", "https://example.com")
48
+ *
49
+ * if (Result.isSuccess(relativeParsed)) {
50
+ * console.log("Parsed relative URL:", relativeParsed.success.toString())
51
+ * } else {
52
+ * console.log("Error:", relativeParsed.failure.message)
53
+ * }
54
+ * // Output: Parsed relative URL: https://example.com/relative-path
55
+ * ```
56
+ *
57
+ * @since 4.0.0
58
+ * @category Constructors
59
+ */
60
+ export const fromString: {
61
+ /**
62
+ * Parses a URL string into a `URL` object, returning an `Result` type for safe
63
+ * error handling.
64
+ *
65
+ * **Details**
66
+ *
67
+ * This function converts a string into a `URL` object, enabling safe URL
68
+ * parsing with built-in error handling. If the string is invalid or fails to
69
+ * parse, this function does not throw an error; instead, it wraps the error in
70
+ * a `IllegalArgumentError` and returns it as the `Failure` value of an
71
+ * `Result`. The `Success` value contains the successfully parsed `URL`.
72
+ *
73
+ * An optional `base` parameter can be provided to resolve relative URLs. If
74
+ * specified, the function interprets the input `url` as relative to this
75
+ * `base`. This is especially useful when dealing with URLs that might not be
76
+ * fully qualified.
77
+ *
78
+ * **Example**
79
+ *
80
+ * ```ts
81
+ * import { Url } from "effect/unstable/http"
82
+ * import { Result } from "effect"
83
+ *
84
+ * // Parse an absolute URL
85
+ * //
86
+ * // ┌─── Result<URL, IllegalArgumentError>
87
+ * // ▼
88
+ * const parsed = Url.fromString("https://example.com/path")
89
+ *
90
+ * if (Result.isSuccess(parsed)) {
91
+ * console.log("Parsed URL:", parsed.success.toString())
92
+ * } else {
93
+ * console.log("Error:", parsed.failure.message)
94
+ * }
95
+ * // Output: Parsed URL: https://example.com/path
96
+ *
97
+ * // Parse a relative URL with a base
98
+ * const relativeParsed = Url.fromString("/relative-path", "https://example.com")
99
+ *
100
+ * if (Result.isSuccess(relativeParsed)) {
101
+ * console.log("Parsed relative URL:", relativeParsed.success.toString())
102
+ * } else {
103
+ * console.log("Error:", relativeParsed.failure.message)
104
+ * }
105
+ * // Output: Parsed relative URL: https://example.com/relative-path
106
+ * ```
107
+ *
108
+ * @since 4.0.0
109
+ * @category Constructors
110
+ */
111
+ (url: string, base?: string | URL | undefined): Result.Result<URL, Cause.IllegalArgumentError>
112
+ } = (url, base) =>
113
+ Result.try({
114
+ try: () => new URL(url, base),
115
+ catch: () =>
116
+ new Cause.IllegalArgumentError(`Invalid URL: "${url}"${base !== undefined ? ` with base "${base}"` : ""}`)
117
+ })
118
+
119
+ /**
120
+ * This function clones the original `URL` object and applies a callback to the
121
+ * clone, allowing multiple updates at once.
122
+ *
123
+ * **Example**
124
+ *
125
+ * ```ts
126
+ * import { Url } from "effect/unstable/http"
127
+ *
128
+ * const myUrl = new URL("https://example.com")
129
+ *
130
+ * const mutatedUrl = Url.mutate(myUrl, (url) => {
131
+ * url.username = "user"
132
+ * url.password = "pass"
133
+ * })
134
+ *
135
+ * console.log("Mutated:", mutatedUrl.toString())
136
+ * // Output: Mutated: https://user:pass@example.com/
137
+ * ```
138
+ *
139
+ * @since 4.0.0
140
+ * @category Modifiers
141
+ */
142
+ export const mutate: {
143
+ /**
144
+ * This function clones the original `URL` object and applies a callback to the
145
+ * clone, allowing multiple updates at once.
146
+ *
147
+ * **Example**
148
+ *
149
+ * ```ts
150
+ * import { Url } from "effect/unstable/http"
151
+ *
152
+ * const myUrl = new URL("https://example.com")
153
+ *
154
+ * const mutatedUrl = Url.mutate(myUrl, (url) => {
155
+ * url.username = "user"
156
+ * url.password = "pass"
157
+ * })
158
+ *
159
+ * console.log("Mutated:", mutatedUrl.toString())
160
+ * // Output: Mutated: https://user:pass@example.com/
161
+ * ```
162
+ *
163
+ * @since 4.0.0
164
+ * @category Modifiers
165
+ */
166
+ (f: (url: URL) => void): (self: URL) => URL
167
+ /**
168
+ * This function clones the original `URL` object and applies a callback to the
169
+ * clone, allowing multiple updates at once.
170
+ *
171
+ * **Example**
172
+ *
173
+ * ```ts
174
+ * import { Url } from "effect/unstable/http"
175
+ *
176
+ * const myUrl = new URL("https://example.com")
177
+ *
178
+ * const mutatedUrl = Url.mutate(myUrl, (url) => {
179
+ * url.username = "user"
180
+ * url.password = "pass"
181
+ * })
182
+ *
183
+ * console.log("Mutated:", mutatedUrl.toString())
184
+ * // Output: Mutated: https://user:pass@example.com/
185
+ * ```
186
+ *
187
+ * @since 4.0.0
188
+ * @category Modifiers
189
+ */
190
+ (self: URL, f: (url: URL) => void): URL
191
+ } = dual(2, (self: URL, f: (url: URL) => void) => {
192
+ const copy = new URL(self)
193
+ f(copy)
194
+ return copy
195
+ })
196
+
197
+ /** @internal */
198
+ const immutableURLSetter = <P extends keyof URL, A = never>(property: P): {
199
+ (value: URL[P] | A): (url: URL) => URL
200
+ (url: URL, value: URL[P] | A): URL
201
+ } =>
202
+ dual(2, (url: URL, value: URL[P]) =>
203
+ mutate(url, (url) => {
204
+ url[property] = value
205
+ }))
206
+
207
+ /**
208
+ * Updates the hash fragment of the URL.
209
+ *
210
+ * @since 4.0.0
211
+ * @category Setters
212
+ */
213
+ export const setHash: {
214
+ /**
215
+ * Updates the hash fragment of the URL.
216
+ *
217
+ * @since 4.0.0
218
+ * @category Setters
219
+ */
220
+ (hash: string): (url: URL) => URL
221
+ /**
222
+ * Updates the hash fragment of the URL.
223
+ *
224
+ * @since 4.0.0
225
+ * @category Setters
226
+ */
227
+ (url: URL, hash: string): URL
228
+ } = immutableURLSetter("hash")
229
+
230
+ /**
231
+ * Updates the host (domain and port) of the URL.
232
+ *
233
+ * @since 4.0.0
234
+ * @category Setters
235
+ */
236
+ export const setHost: {
237
+ /**
238
+ * Updates the host (domain and port) of the URL.
239
+ *
240
+ * @since 4.0.0
241
+ * @category Setters
242
+ */
243
+ (host: string): (url: URL) => URL
244
+ /**
245
+ * Updates the host (domain and port) of the URL.
246
+ *
247
+ * @since 4.0.0
248
+ * @category Setters
249
+ */
250
+ (url: URL, host: string): URL
251
+ } = immutableURLSetter("host")
252
+
253
+ /**
254
+ * Updates the domain of the URL without modifying the port.
255
+ *
256
+ * @since 4.0.0
257
+ * @category Setters
258
+ */
259
+ export const setHostname: {
260
+ /**
261
+ * Updates the domain of the URL without modifying the port.
262
+ *
263
+ * @since 4.0.0
264
+ * @category Setters
265
+ */
266
+ (hostname: string): (url: URL) => URL
267
+ /**
268
+ * Updates the domain of the URL without modifying the port.
269
+ *
270
+ * @since 4.0.0
271
+ * @category Setters
272
+ */
273
+ (url: URL, hostname: string): URL
274
+ } = immutableURLSetter("hostname")
275
+
276
+ /**
277
+ * Replaces the entire URL string.
278
+ *
279
+ * @since 4.0.0
280
+ * @category Setters
281
+ */
282
+ export const setHref: {
283
+ /**
284
+ * Replaces the entire URL string.
285
+ *
286
+ * @since 4.0.0
287
+ * @category Setters
288
+ */
289
+ (href: string): (url: URL) => URL
290
+ /**
291
+ * Replaces the entire URL string.
292
+ *
293
+ * @since 4.0.0
294
+ * @category Setters
295
+ */
296
+ (url: URL, href: string): URL
297
+ } = immutableURLSetter("href")
298
+
299
+ /**
300
+ * Updates the password used for authentication.
301
+ *
302
+ * @since 4.0.0
303
+ * @category Setters
304
+ */
305
+ export const setPassword: {
306
+ /**
307
+ * Updates the password used for authentication.
308
+ *
309
+ * @since 4.0.0
310
+ * @category Setters
311
+ */
312
+ (password: string | Redacted.Redacted): (url: URL) => URL
313
+ /**
314
+ * Updates the password used for authentication.
315
+ *
316
+ * @since 4.0.0
317
+ * @category Setters
318
+ */
319
+ (url: URL, password: string | Redacted.Redacted): URL
320
+ } = dual(2, (url: URL, password: string | Redacted.Redacted) =>
321
+ mutate(url, (url) => {
322
+ url.password = typeof password === "string"
323
+ ? password :
324
+ Redacted.value(password)
325
+ }))
326
+
327
+ /**
328
+ * Updates the path of the URL.
329
+ *
330
+ * @since 4.0.0
331
+ * @category Setters
332
+ */
333
+ export const setPathname: {
334
+ /**
335
+ * Updates the path of the URL.
336
+ *
337
+ * @since 4.0.0
338
+ * @category Setters
339
+ */
340
+ (pathname: string): (url: URL) => URL
341
+ /**
342
+ * Updates the path of the URL.
343
+ *
344
+ * @since 4.0.0
345
+ * @category Setters
346
+ */
347
+ (url: URL, pathname: string): URL
348
+ } = immutableURLSetter("pathname")
349
+
350
+ /**
351
+ * Updates the port of the URL.
352
+ *
353
+ * @since 4.0.0
354
+ * @category Setters
355
+ */
356
+ export const setPort: {
357
+ /**
358
+ * Updates the port of the URL.
359
+ *
360
+ * @since 4.0.0
361
+ * @category Setters
362
+ */
363
+ (port: string | number): (url: URL) => URL
364
+ /**
365
+ * Updates the port of the URL.
366
+ *
367
+ * @since 4.0.0
368
+ * @category Setters
369
+ */
370
+ (url: URL, port: string | number): URL
371
+ } = immutableURLSetter("port")
372
+
373
+ /**
374
+ * Updates the protocol (e.g., `http`, `https`).
375
+ *
376
+ * @since 4.0.0
377
+ * @category Setters
378
+ */
379
+ export const setProtocol: {
380
+ /**
381
+ * Updates the protocol (e.g., `http`, `https`).
382
+ *
383
+ * @since 4.0.0
384
+ * @category Setters
385
+ */
386
+ (protocol: string): (url: URL) => URL
387
+ /**
388
+ * Updates the protocol (e.g., `http`, `https`).
389
+ *
390
+ * @since 4.0.0
391
+ * @category Setters
392
+ */
393
+ (url: URL, protocol: string): URL
394
+ } = immutableURLSetter("protocol")
395
+
396
+ /**
397
+ * Updates the query string of the URL.
398
+ *
399
+ * @since 4.0.0
400
+ * @category Setters
401
+ */
402
+ export const setSearch: {
403
+ /**
404
+ * Updates the query string of the URL.
405
+ *
406
+ * @since 4.0.0
407
+ * @category Setters
408
+ */
409
+ (search: string): (url: URL) => URL
410
+ /**
411
+ * Updates the query string of the URL.
412
+ *
413
+ * @since 4.0.0
414
+ * @category Setters
415
+ */
416
+ (url: URL, search: string): URL
417
+ } = immutableURLSetter("search")
418
+
419
+ /**
420
+ * Updates the username used for authentication.
421
+ *
422
+ * @since 4.0.0
423
+ * @category Setters
424
+ */
425
+ export const setUsername: {
426
+ /**
427
+ * Updates the username used for authentication.
428
+ *
429
+ * @since 4.0.0
430
+ * @category Setters
431
+ */
432
+ (username: string): (url: URL) => URL
433
+ /**
434
+ * Updates the username used for authentication.
435
+ *
436
+ * @since 4.0.0
437
+ * @category Setters
438
+ */
439
+ (url: URL, username: string): URL
440
+ } = immutableURLSetter("username")
441
+
442
+ /**
443
+ * Updates the query parameters of a URL.
444
+ *
445
+ * **Details**
446
+ *
447
+ * This function allows you to set or replace the query parameters of a `URL`
448
+ * object using the provided `UrlParams`. It creates a new `URL` object with the
449
+ * updated parameters, leaving the original object unchanged.
450
+ *
451
+ * **Example**
452
+ *
453
+ * ```ts
454
+ * import { Url, UrlParams } from "effect/unstable/http"
455
+ *
456
+ * const myUrl = new URL("https://example.com?foo=bar")
457
+ *
458
+ * // Write parameters
459
+ * const updatedUrl = Url.setUrlParams(
460
+ * myUrl,
461
+ * UrlParams.fromInput([["key", "value"]])
462
+ * )
463
+ *
464
+ * console.log(updatedUrl.toString())
465
+ * // Output: https://example.com/?key=value
466
+ * ```
467
+ *
468
+ * @since 4.0.0
469
+ * @category Setters
470
+ */
471
+ export const setUrlParams: {
472
+ /**
473
+ * Updates the query parameters of a URL.
474
+ *
475
+ * **Details**
476
+ *
477
+ * This function allows you to set or replace the query parameters of a `URL`
478
+ * object using the provided `UrlParams`. It creates a new `URL` object with the
479
+ * updated parameters, leaving the original object unchanged.
480
+ *
481
+ * **Example**
482
+ *
483
+ * ```ts
484
+ * import { Url, UrlParams } from "effect/unstable/http"
485
+ *
486
+ * const myUrl = new URL("https://example.com?foo=bar")
487
+ *
488
+ * // Write parameters
489
+ * const updatedUrl = Url.setUrlParams(
490
+ * myUrl,
491
+ * UrlParams.fromInput([["key", "value"]])
492
+ * )
493
+ *
494
+ * console.log(updatedUrl.toString())
495
+ * // Output: https://example.com/?key=value
496
+ * ```
497
+ *
498
+ * @since 4.0.0
499
+ * @category Setters
500
+ */
501
+ (urlParams: UrlParams.UrlParams): (url: URL) => URL
502
+ /**
503
+ * Updates the query parameters of a URL.
504
+ *
505
+ * **Details**
506
+ *
507
+ * This function allows you to set or replace the query parameters of a `URL`
508
+ * object using the provided `UrlParams`. It creates a new `URL` object with the
509
+ * updated parameters, leaving the original object unchanged.
510
+ *
511
+ * **Example**
512
+ *
513
+ * ```ts
514
+ * import { Url, UrlParams } from "effect/unstable/http"
515
+ *
516
+ * const myUrl = new URL("https://example.com?foo=bar")
517
+ *
518
+ * // Write parameters
519
+ * const updatedUrl = Url.setUrlParams(
520
+ * myUrl,
521
+ * UrlParams.fromInput([["key", "value"]])
522
+ * )
523
+ *
524
+ * console.log(updatedUrl.toString())
525
+ * // Output: https://example.com/?key=value
526
+ * ```
527
+ *
528
+ * @since 4.0.0
529
+ * @category Setters
530
+ */
531
+ (url: URL, urlParams: UrlParams.UrlParams): URL
532
+ } = dual(2, (url: URL, searchParams: UrlParams.UrlParams) =>
533
+ mutate(url, (url) => {
534
+ url.search = UrlParams.toString(searchParams)
535
+ }))
536
+
537
+ /**
538
+ * Retrieves the query parameters from a URL.
539
+ *
540
+ * **Details**
541
+ *
542
+ * This function extracts the query parameters from a `URL` object and returns
543
+ * them as `UrlParams`. The resulting structure can be easily manipulated or
544
+ * inspected.
545
+ *
546
+ * **Example**
547
+ *
548
+ * ```ts
549
+ * import { Url } from "effect/unstable/http"
550
+ *
551
+ * const myUrl = new URL("https://example.com?foo=bar")
552
+ *
553
+ * // Read parameters
554
+ * const params = Url.urlParams(myUrl)
555
+ *
556
+ * console.log(params)
557
+ * // Output: [ [ 'foo', 'bar' ] ]
558
+ * ```
559
+ *
560
+ * @since 4.0.0
561
+ * @category Getters
562
+ */
563
+ export const urlParams = (url: URL): UrlParams.UrlParams => UrlParams.fromInput(url.searchParams)
564
+
565
+ /**
566
+ * Reads, modifies, and updates the query parameters of a URL.
567
+ *
568
+ * **Details**
569
+ *
570
+ * This function provides a functional way to interact with query parameters by
571
+ * reading the current parameters, applying a transformation function, and then
572
+ * writing the updated parameters back to the URL. It returns a new `URL` object
573
+ * with the modified parameters, ensuring immutability.
574
+ *
575
+ * **Example**
576
+ *
577
+ * ```ts
578
+ * import { Url, UrlParams } from "effect/unstable/http"
579
+ *
580
+ * const myUrl = new URL("https://example.com?foo=bar")
581
+ *
582
+ * const changedUrl = Url.modifyUrlParams(myUrl, UrlParams.append("key", "value"))
583
+ *
584
+ * console.log(changedUrl.toString())
585
+ * // Output: https://example.com/?foo=bar&key=value
586
+ * ```
587
+ *
588
+ * @since 4.0.0
589
+ * @category Modifiers
590
+ */
591
+ export const modifyUrlParams: {
592
+ /**
593
+ * Reads, modifies, and updates the query parameters of a URL.
594
+ *
595
+ * **Details**
596
+ *
597
+ * This function provides a functional way to interact with query parameters by
598
+ * reading the current parameters, applying a transformation function, and then
599
+ * writing the updated parameters back to the URL. It returns a new `URL` object
600
+ * with the modified parameters, ensuring immutability.
601
+ *
602
+ * **Example**
603
+ *
604
+ * ```ts
605
+ * import { Url, UrlParams } from "effect/unstable/http"
606
+ *
607
+ * const myUrl = new URL("https://example.com?foo=bar")
608
+ *
609
+ * const changedUrl = Url.modifyUrlParams(myUrl, UrlParams.append("key", "value"))
610
+ *
611
+ * console.log(changedUrl.toString())
612
+ * // Output: https://example.com/?foo=bar&key=value
613
+ * ```
614
+ *
615
+ * @since 4.0.0
616
+ * @category Modifiers
617
+ */
618
+ (f: (urlParams: UrlParams.UrlParams) => UrlParams.UrlParams): (url: URL) => URL
619
+ /**
620
+ * Reads, modifies, and updates the query parameters of a URL.
621
+ *
622
+ * **Details**
623
+ *
624
+ * This function provides a functional way to interact with query parameters by
625
+ * reading the current parameters, applying a transformation function, and then
626
+ * writing the updated parameters back to the URL. It returns a new `URL` object
627
+ * with the modified parameters, ensuring immutability.
628
+ *
629
+ * **Example**
630
+ *
631
+ * ```ts
632
+ * import { Url, UrlParams } from "effect/unstable/http"
633
+ *
634
+ * const myUrl = new URL("https://example.com?foo=bar")
635
+ *
636
+ * const changedUrl = Url.modifyUrlParams(myUrl, UrlParams.append("key", "value"))
637
+ *
638
+ * console.log(changedUrl.toString())
639
+ * // Output: https://example.com/?foo=bar&key=value
640
+ * ```
641
+ *
642
+ * @since 4.0.0
643
+ * @category Modifiers
644
+ */
645
+ (url: URL, f: (urlParams: UrlParams.UrlParams) => UrlParams.UrlParams): URL
646
+ } = dual(2, (url: URL, f: (urlParams: UrlParams.UrlParams) => UrlParams.UrlParams) =>
647
+ mutate(url, (url) => {
648
+ const params = f(UrlParams.fromInput(url.searchParams))
649
+ url.search = UrlParams.toString(params)
650
+ }))
@@ -138,3 +138,8 @@ export * as Template from "./Template.ts"
138
138
  * @since 4.0.0
139
139
  */
140
140
  export * as UrlParams from "./UrlParams.ts"
141
+
142
+ /**
143
+ * @since 4.0.0
144
+ */
145
+ export * as Url from "./Url.ts"
@@ -4,7 +4,7 @@
4
4
  import * as Effect from "../../Effect.ts"
5
5
  import * as Layer from "../../Layer.ts"
6
6
  import { hasProperty } from "../../Predicate.ts"
7
- import type * as Schema from "../../Schema.ts"
7
+ import * as Schema from "../../Schema.ts"
8
8
  import { Scope } from "../../Scope.ts"
9
9
  import * as ServiceMap from "../../ServiceMap.ts"
10
10
  import type { unhandled } from "../../Types.ts"
@@ -292,6 +292,51 @@ export const Service = <
292
292
  return self
293
293
  }
294
294
 
295
+ /**
296
+ * Implement a middleware Layer that transforms `SchemaError`'s.
297
+ *
298
+ * ```ts
299
+ * import { Effect, Schema } from "effect"
300
+ * import { HttpApiMiddleware } from "effect/unstable/httpapi"
301
+ *
302
+ * export class CustomError extends Schema.TaggedErrorClass<CustomError>()("CustomError", {}) {}
303
+ *
304
+ * export class ErrorHandler extends HttpApiMiddleware.Service<ErrorHandler>()("api/ErrorHandler", {
305
+ * error: CustomError
306
+ * }) {}
307
+ *
308
+ * export const ErrorHandlerLayer = HttpApiMiddleware.layerSchemaErrorTransform(
309
+ * ErrorHandler,
310
+ * (schemaError) =>
311
+ * Effect.log("Got SchemaError", schemaError).pipe(
312
+ * Effect.andThen(Effect.fail(new CustomError()))
313
+ * )
314
+ * )
315
+ * ```
316
+ *
317
+ * @since 4.0.0
318
+ * @category SchemaError transform
319
+ */
320
+ export const layerSchemaErrorTransform = <Id, E extends Schema.Top, Requires>(
321
+ service: ServiceMap.Service<Id, HttpApiMiddleware<never, E, Requires>>,
322
+ transform: (
323
+ error: Schema.SchemaError,
324
+ context: { readonly endpoint: HttpApiEndpoint.AnyWithProps; readonly group: HttpApiGroup.AnyWithProps }
325
+ ) => Effect.Effect<HttpServerResponse, E["Type"] | Schema.SchemaError, Requires | HttpRouter.Provided>
326
+ ): Layer.Layer<Id> =>
327
+ Layer.succeed(
328
+ service,
329
+ (httpEffect, options) =>
330
+ Effect.catch(
331
+ httpEffect,
332
+ (e): Effect.Effect<
333
+ HttpServerResponse,
334
+ unhandled | Schema.SchemaError | E["Type"],
335
+ Requires | HttpRouter.Provided
336
+ > => Schema.isSchemaError(e) ? transform(e, options) : Effect.fail(e)
337
+ )
338
+ )
339
+
295
340
  /**
296
341
  * @since 4.0.0
297
342
  * @category client