@effect/platform 0.51.0 → 0.52.1

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 (61) hide show
  1. package/dist/cjs/Http/App.js.map +1 -1
  2. package/dist/cjs/Http/Client.js +11 -1
  3. package/dist/cjs/Http/Client.js.map +1 -1
  4. package/dist/cjs/Http/Middleware.js +6 -1
  5. package/dist/cjs/Http/Middleware.js.map +1 -1
  6. package/dist/cjs/Http/Router.js +1 -11
  7. package/dist/cjs/Http/Router.js.map +1 -1
  8. package/dist/cjs/Http/ServerRequest.js +17 -2
  9. package/dist/cjs/Http/ServerRequest.js.map +1 -1
  10. package/dist/cjs/Http/UrlParams.js +11 -1
  11. package/dist/cjs/Http/UrlParams.js.map +1 -1
  12. package/dist/cjs/internal/http/client.js +8 -3
  13. package/dist/cjs/internal/http/client.js.map +1 -1
  14. package/dist/cjs/internal/http/middleware.js +9 -1
  15. package/dist/cjs/internal/http/middleware.js.map +1 -1
  16. package/dist/cjs/internal/http/router.js +44 -39
  17. package/dist/cjs/internal/http/router.js.map +1 -1
  18. package/dist/cjs/internal/http/serverRequest.js +27 -1
  19. package/dist/cjs/internal/http/serverRequest.js.map +1 -1
  20. package/dist/dts/Http/App.d.ts.map +1 -1
  21. package/dist/dts/Http/Client.d.ts +13 -0
  22. package/dist/dts/Http/Client.d.ts.map +1 -1
  23. package/dist/dts/Http/Middleware.d.ts +5 -0
  24. package/dist/dts/Http/Middleware.d.ts.map +1 -1
  25. package/dist/dts/Http/Router.d.ts +47 -58
  26. package/dist/dts/Http/Router.d.ts.map +1 -1
  27. package/dist/dts/Http/ServerRequest.d.ts +22 -0
  28. package/dist/dts/Http/ServerRequest.d.ts.map +1 -1
  29. package/dist/dts/Http/UrlParams.d.ts +1 -1
  30. package/dist/dts/Http/UrlParams.d.ts.map +1 -1
  31. package/dist/dts/internal/http/router.d.ts.map +1 -1
  32. package/dist/esm/Http/App.js.map +1 -1
  33. package/dist/esm/Http/Client.js +10 -0
  34. package/dist/esm/Http/Client.js.map +1 -1
  35. package/dist/esm/Http/Middleware.js +5 -0
  36. package/dist/esm/Http/Middleware.js.map +1 -1
  37. package/dist/esm/Http/Router.js +0 -10
  38. package/dist/esm/Http/Router.js.map +1 -1
  39. package/dist/esm/Http/ServerRequest.js +15 -0
  40. package/dist/esm/Http/ServerRequest.js.map +1 -1
  41. package/dist/esm/Http/UrlParams.js +11 -1
  42. package/dist/esm/Http/UrlParams.js.map +1 -1
  43. package/dist/esm/internal/http/client.js +7 -2
  44. package/dist/esm/internal/http/client.js.map +1 -1
  45. package/dist/esm/internal/http/middleware.js +7 -0
  46. package/dist/esm/internal/http/middleware.js.map +1 -1
  47. package/dist/esm/internal/http/router.js +43 -37
  48. package/dist/esm/internal/http/router.js.map +1 -1
  49. package/dist/esm/internal/http/serverRequest.js +24 -0
  50. package/dist/esm/internal/http/serverRequest.js.map +1 -1
  51. package/package.json +5 -5
  52. package/src/Http/App.ts +1 -3
  53. package/src/Http/Client.ts +15 -0
  54. package/src/Http/Middleware.ts +11 -0
  55. package/src/Http/Router.ts +80 -85
  56. package/src/Http/ServerRequest.ts +31 -0
  57. package/src/Http/UrlParams.ts +15 -2
  58. package/src/internal/http/client.ts +23 -2
  59. package/src/internal/http/middleware.ts +19 -0
  60. package/src/internal/http/router.ts +48 -47
  61. package/src/internal/http/serverRequest.ts +33 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect/platform",
3
- "version": "0.51.0",
3
+ "version": "0.52.1",
4
4
  "description": "Unified interfaces for common platform-specific services",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -10,14 +10,14 @@
10
10
  },
11
11
  "sideEffects": [],
12
12
  "dependencies": {
13
- "find-my-way-ts": "^0.1.1",
13
+ "find-my-way-ts": "^0.1.2",
14
14
  "isows": "^1.0.4",
15
- "multipasta": "^0.2.0",
15
+ "multipasta": "^0.2.1",
16
16
  "path-browserify": "^1.0.1"
17
17
  },
18
18
  "peerDependencies": {
19
- "@effect/schema": "^0.66.12",
20
- "effect": "^3.1.0"
19
+ "@effect/schema": "^0.66.13",
20
+ "effect": "^3.1.1"
21
21
  },
22
22
  "publishConfig": {
23
23
  "provenance": true
package/src/Http/App.ts CHANGED
@@ -152,9 +152,7 @@ export const toWebHandlerRuntime = <R>(runtime: Runtime.Runtime<R>) => {
152
152
  const req = ServerRequest.fromWeb(request)
153
153
  ;(req as any)[resolveSymbol] = resolve
154
154
  ;(req as any)[rejectSymbol] = reject
155
- const fiber = run(
156
- Effect.provideService(handled, ServerRequest.ServerRequest, req)
157
- )
155
+ const fiber = run(Effect.provideService(handled, ServerRequest.ServerRequest, req))
158
156
  request.signal.addEventListener("abort", () => {
159
157
  fiber.unsafeInterruptAsFork(ServerError.clientAbortFiberId)
160
158
  })
@@ -459,6 +459,21 @@ export const withTracerDisabledWhen: {
459
459
  ): Effect.Effect<A, E, R>
460
460
  } = internal.withTracerDisabledWhen
461
461
 
462
+ /**
463
+ * @since 1.0.0
464
+ * @category fiber refs
465
+ */
466
+ export const currentTracerPropagation: FiberRef.FiberRef<boolean> = internal.currentTracerPropagation
467
+
468
+ /**
469
+ * @since 1.0.0
470
+ * @category fiber refs
471
+ */
472
+ export const withTracerPropagation: {
473
+ (enabled: boolean): <R, E, A>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
474
+ <R, E, A>(effect: Effect.Effect<A, E, R>, enabled: boolean): Effect.Effect<A, E, R>
475
+ } = internal.withTracerPropagation
476
+
462
477
  /**
463
478
  * @since 1.0.0
464
479
  * @category fiber refs
@@ -103,3 +103,14 @@ export const withTracerDisabledForUrls: {
103
103
  * @category constructors
104
104
  */
105
105
  export const xForwardedHeaders: <R, E>(httpApp: App.Default<E, R>) => App.Default<E, R> = internal.xForwardedHeaders
106
+
107
+ /**
108
+ * @since 1.0.0
109
+ * @category constructors
110
+ */
111
+ export const searchParamsParser: <E, R>(
112
+ httpApp: App.Default<E, R>
113
+ ) => App.Default<
114
+ E,
115
+ Exclude<R, ServerRequest.ParsedSearchParams>
116
+ > = internal.searchParamsParser
@@ -55,7 +55,10 @@ export declare namespace Router {
55
55
  /**
56
56
  * @since 1.0.0
57
57
  */
58
- export type ExcludeProvided<A> = Exclude<A, RouteContext | ServerRequest.ServerRequest | Scope.Scope>
58
+ export type ExcludeProvided<A> = Exclude<
59
+ A,
60
+ RouteContext | ServerRequest.ServerRequest | ServerRequest.ParsedSearchParams | Scope.Scope
61
+ >
59
62
  }
60
63
 
61
64
  /**
@@ -99,7 +102,7 @@ export declare namespace Route {
99
102
  export type Handler<E, R> = Effect.Effect<
100
103
  ServerResponse.ServerResponse,
101
104
  E,
102
- R | RouteContext | ServerRequest.ServerRequest
105
+ R | RouteContext | ServerRequest.ServerRequest | ServerRequest.ParsedSearchParams
103
106
  >
104
107
  }
105
108
 
@@ -123,7 +126,6 @@ export interface RouteContext {
123
126
  readonly [RouteContextTypeId]: RouteContextTypeId
124
127
  readonly params: Readonly<Record<string, string | undefined>>
125
128
  readonly route: Route<unknown, unknown>
126
- readonly searchParams: Readonly<Record<string, string>>
127
129
  }
128
130
 
129
131
  /**
@@ -142,86 +144,75 @@ export const params: Effect.Effect<
142
144
  RouteContext
143
145
  > = internal.params
144
146
 
145
- /**
146
- * @since 1.0.0
147
- * @category route context
148
- */
149
- export const searchParams: Effect.Effect<
150
- Readonly<Record<string, string>>,
151
- never,
152
- RouteContext
153
- > = internal.searchParams
154
-
155
147
  /**
156
148
  * @since 1.0.0
157
149
  * @category route context
158
150
  */
159
151
  export const schemaJson: <
160
- R,
161
- I extends Partial<
162
- {
163
- readonly method: Method.Method
164
- readonly url: string
165
- readonly cookies: Readonly<Record<string, string>>
166
- readonly headers: Readonly<Record<string, string>>
167
- readonly pathParams: Readonly<Record<string, string>>
168
- readonly searchParams: Readonly<Record<string, string>>
169
- readonly body: any
170
- }
171
- >,
172
- A
173
- >(
174
- schema: Schema.Schema<A, I, R>,
175
- options?: ParseOptions | undefined
176
- ) => Effect.Effect<A, Error.RequestError | ParseResult.ParseError, RouteContext | R | ServerRequest.ServerRequest> =
177
- internal.schemaJson
178
-
179
- /**
180
- * @since 1.0.0
181
- * @category route context
182
- */
183
- export const schemaNoBody: <
184
152
  R,
185
153
  I extends Partial<{
186
154
  readonly method: Method.Method
187
155
  readonly url: string
188
- readonly cookies: Readonly<Record<string, string>>
189
- readonly headers: Readonly<Record<string, string>>
190
- readonly pathParams: Readonly<Record<string, string>>
191
- readonly searchParams: Readonly<Record<string, string>>
156
+ readonly cookies: Readonly<Record<string, string | undefined>>
157
+ readonly headers: Readonly<Record<string, string | undefined>>
158
+ readonly pathParams: Readonly<Record<string, string | undefined>>
159
+ readonly searchParams: Readonly<Record<string, string | Array<string> | undefined>>
160
+ readonly body: any
192
161
  }>,
193
162
  A
194
163
  >(
195
164
  schema: Schema.Schema<A, I, R>,
196
165
  options?: ParseOptions | undefined
197
- ) => Effect.Effect<A, ParseResult.ParseError, R | RouteContext | ServerRequest.ServerRequest> = internal.schemaNoBody
166
+ ) => Effect.Effect<
167
+ A,
168
+ Error.RequestError | ParseResult.ParseError,
169
+ RouteContext | R | ServerRequest.ServerRequest | ServerRequest.ParsedSearchParams
170
+ > = internal.schemaJson
198
171
 
199
172
  /**
200
173
  * @since 1.0.0
201
174
  * @category route context
202
175
  */
203
- export const schemaParams: <R, I extends Readonly<Record<string, string>>, A>(
176
+ export const schemaNoBody: <
177
+ R,
178
+ I extends Partial<
179
+ {
180
+ readonly method: Method.Method
181
+ readonly url: string
182
+ readonly cookies: Readonly<Record<string, string | undefined>>
183
+ readonly headers: Readonly<Record<string, string | undefined>>
184
+ readonly pathParams: Readonly<Record<string, string | undefined>>
185
+ readonly searchParams: Readonly<Record<string, string | Array<string> | undefined>>
186
+ }
187
+ >,
188
+ A
189
+ >(
204
190
  schema: Schema.Schema<A, I, R>,
205
191
  options?: ParseOptions | undefined
206
- ) => Effect.Effect<A, ParseResult.ParseError, RouteContext | R> = internal.schemaParams
192
+ ) => Effect.Effect<
193
+ A,
194
+ ParseResult.ParseError,
195
+ R | RouteContext | ServerRequest.ServerRequest | ServerRequest.ParsedSearchParams
196
+ > = internal.schemaNoBody
207
197
 
208
198
  /**
209
199
  * @since 1.0.0
210
200
  * @category route context
211
201
  */
212
- export const schemaPathParams: <R, I extends Readonly<Record<string, string>>, A>(
202
+ export const schemaParams: <R, I extends Readonly<Record<string, string | Array<string> | undefined>>, A>(
213
203
  schema: Schema.Schema<A, I, R>,
214
204
  options?: ParseOptions | undefined
215
- ) => Effect.Effect<A, ParseResult.ParseError, RouteContext | R> = internal.schemaPathParams
205
+ ) => Effect.Effect<A, ParseResult.ParseError, R | RouteContext | ServerRequest.ParsedSearchParams> =
206
+ internal.schemaParams
216
207
 
217
208
  /**
218
209
  * @since 1.0.0
219
210
  * @category route context
220
211
  */
221
- export const schemaSearchParams: <R, I extends Readonly<Record<string, string>>, A>(
212
+ export const schemaPathParams: <R, I extends Readonly<Record<string, string | undefined>>, A>(
222
213
  schema: Schema.Schema<A, I, R>,
223
214
  options?: ParseOptions | undefined
224
- ) => Effect.Effect<A, ParseResult.ParseError, RouteContext | R> = internal.schemaSearchParams
215
+ ) => Effect.Effect<A, ParseResult.ParseError, R | RouteContext> = internal.schemaPathParams
225
216
 
226
217
  /**
227
218
  * @since 1.0.0
@@ -248,7 +239,7 @@ export const makeRoute: <E, R>(
248
239
  handler: Route.Handler<E, R>,
249
240
  prefix?: Option.Option<string>,
250
241
  uninterruptible?: boolean
251
- ) => Route<E, Exclude<R, RouteContext | ServerRequest.ServerRequest | Scope.Scope>> = internal.makeRoute
242
+ ) => Route<E, Router.ExcludeProvided<R>> = internal.makeRoute
252
243
 
253
244
  /**
254
245
  * @since 1.0.0
@@ -295,8 +286,8 @@ export const mountApp: {
295
286
  self: Router<E, R>
296
287
  ) => Router<
297
288
  E1 | E,
298
- | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>
299
- | Exclude<R, RouteContext | ServerRequest.ServerRequest | Scope.Scope>
289
+ | Router.ExcludeProvided<R1>
290
+ | Router.ExcludeProvided<R>
300
291
  >
301
292
  <R, E, R1, E1>(
302
293
  self: Router<E, R>,
@@ -305,8 +296,8 @@ export const mountApp: {
305
296
  options?: { readonly includePrefix?: boolean | undefined } | undefined
306
297
  ): Router<
307
298
  E | E1,
308
- | Exclude<R, RouteContext | ServerRequest.ServerRequest | Scope.Scope>
309
- | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>
299
+ | Router.ExcludeProvided<R>
300
+ | Router.ExcludeProvided<R1>
310
301
  >
311
302
  } = internal.mountApp
312
303
 
@@ -343,13 +334,19 @@ export const all: {
343
334
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
344
335
  ): <R, E>(
345
336
  self: Router<E, R>
346
- ) => Router<E1 | E, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
337
+ ) => Router<
338
+ E1 | E,
339
+ R | Router.ExcludeProvided<R1>
340
+ >
347
341
  <R, E, R1, E1>(
348
342
  self: Router<E, R>,
349
343
  path: PathInput,
350
344
  handler: Route.Handler<E1, R1>,
351
345
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
352
- ): Router<E | E1, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
346
+ ): Router<
347
+ E | E1,
348
+ R | Router.ExcludeProvided<R1>
349
+ >
353
350
  } = internal.all
354
351
 
355
352
  /**
@@ -363,13 +360,13 @@ export const get: {
363
360
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
364
361
  ): <R, E>(
365
362
  self: Router<E, R>
366
- ) => Router<E1 | E, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
363
+ ) => Router<E1 | E, R | Router.ExcludeProvided<R1>>
367
364
  <R, E, R1, E1>(
368
365
  self: Router<E, R>,
369
366
  path: PathInput,
370
367
  handler: Route.Handler<E1, R1>,
371
368
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
372
- ): Router<E | E1, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
369
+ ): Router<E | E1, R | Router.ExcludeProvided<R1>>
373
370
  } = internal.get
374
371
 
375
372
  /**
@@ -383,13 +380,13 @@ export const post: {
383
380
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
384
381
  ): <R, E>(
385
382
  self: Router<E, R>
386
- ) => Router<E1 | E, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
383
+ ) => Router<E1 | E, R | Router.ExcludeProvided<R1>>
387
384
  <R, E, R1, E1>(
388
385
  self: Router<E, R>,
389
386
  path: PathInput,
390
387
  handler: Route.Handler<E1, R1>,
391
388
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
392
- ): Router<E | E1, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
389
+ ): Router<E | E1, R | Router.ExcludeProvided<R1>>
393
390
  } = internal.post
394
391
 
395
392
  /**
@@ -403,13 +400,13 @@ export const patch: {
403
400
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
404
401
  ): <R, E>(
405
402
  self: Router<E, R>
406
- ) => Router<E1 | E, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
403
+ ) => Router<E1 | E, R | Router.ExcludeProvided<R1>>
407
404
  <R, E, R1, E1>(
408
405
  self: Router<E, R>,
409
406
  path: PathInput,
410
407
  handler: Route.Handler<E1, R1>,
411
408
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
412
- ): Router<E | E1, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
409
+ ): Router<E | E1, R | Router.ExcludeProvided<R1>>
413
410
  } = internal.patch
414
411
 
415
412
  /**
@@ -423,13 +420,13 @@ export const put: {
423
420
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
424
421
  ): <R, E>(
425
422
  self: Router<E, R>
426
- ) => Router<E1 | E, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
423
+ ) => Router<E1 | E, R | Router.ExcludeProvided<R1>>
427
424
  <R, E, R1, E1>(
428
425
  self: Router<E, R>,
429
426
  path: PathInput,
430
427
  handler: Route.Handler<E1, R1>,
431
428
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
432
- ): Router<E | E1, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
429
+ ): Router<E | E1, R | Router.ExcludeProvided<R1>>
433
430
  } = internal.put
434
431
 
435
432
  /**
@@ -443,13 +440,13 @@ export const del: {
443
440
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
444
441
  ): <R, E>(
445
442
  self: Router<E, R>
446
- ) => Router<E1 | E, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
443
+ ) => Router<E1 | E, R | Router.ExcludeProvided<R1>>
447
444
  <R, E, R1, E1>(
448
445
  self: Router<E, R>,
449
446
  path: PathInput,
450
447
  handler: Route.Handler<E1, R1>,
451
448
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
452
- ): Router<E | E1, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
449
+ ): Router<E | E1, R | Router.ExcludeProvided<R1>>
453
450
  } = internal.del
454
451
 
455
452
  /**
@@ -463,13 +460,13 @@ export const head: {
463
460
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
464
461
  ): <R, E>(
465
462
  self: Router<E, R>
466
- ) => Router<E1 | E, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
463
+ ) => Router<E1 | E, R | Router.ExcludeProvided<R1>>
467
464
  <R, E, R1, E1>(
468
465
  self: Router<E, R>,
469
466
  path: PathInput,
470
467
  handler: Route.Handler<E1, R1>,
471
468
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
472
- ): Router<E | E1, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
469
+ ): Router<E | E1, R | Router.ExcludeProvided<R1>>
473
470
  } = internal.head
474
471
 
475
472
  /**
@@ -483,13 +480,13 @@ export const options: {
483
480
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
484
481
  ): <R, E>(
485
482
  self: Router<E, R>
486
- ) => Router<E1 | E, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
483
+ ) => Router<E1 | E, R | Router.ExcludeProvided<R1>>
487
484
  <R, E, R1, E1>(
488
485
  self: Router<E, R>,
489
486
  path: PathInput,
490
487
  handler: Route.Handler<E1, R1>,
491
488
  options?: { readonly uninterruptible?: boolean | undefined } | undefined
492
- ): Router<E | E1, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
489
+ ): Router<E | E1, R | Router.ExcludeProvided<R1>>
493
490
  } = internal.options
494
491
 
495
492
  /**
@@ -499,11 +496,11 @@ export const options: {
499
496
  export const use: {
500
497
  <E, R, R1, E1>(
501
498
  f: (self: Route.Handler<E, R>) => App.Default<E1, R1>
502
- ): (self: Router<E, R>) => Router<E1, Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
499
+ ): (self: Router<E, R>) => Router<E1, Router.ExcludeProvided<R1>>
503
500
  <E, R, R1, E1>(
504
501
  self: Router<E, R>,
505
502
  f: (self: Route.Handler<E, R>) => App.Default<E1, R1>
506
- ): Router<E1, Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
503
+ ): Router<E1, Router.ExcludeProvided<R1>>
507
504
  } = internal.use
508
505
 
509
506
  /**
@@ -513,11 +510,11 @@ export const use: {
513
510
  export const catchAll: {
514
511
  <E, E2, R2>(
515
512
  f: (e: E) => Route.Handler<E2, R2>
516
- ): <R>(self: Router<E, R>) => Router<E2, R | Exclude<R2, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
513
+ ): <R>(self: Router<E, R>) => Router<E2, R | Router.ExcludeProvided<R2>>
517
514
  <R, E, E2, R2>(
518
515
  self: Router<E, R>,
519
516
  f: (e: E) => Route.Handler<E2, R2>
520
- ): Router<E2, R | Exclude<R2, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
517
+ ): Router<E2, R | Router.ExcludeProvided<R2>>
521
518
  } = internal.catchAll
522
519
 
523
520
  /**
@@ -527,11 +524,11 @@ export const catchAll: {
527
524
  export const catchAllCause: {
528
525
  <E, E2, R2>(
529
526
  f: (e: Cause.Cause<E>) => Route.Handler<E2, R2>
530
- ): <R>(self: Router<E, R>) => Router<E2, R | Exclude<R2, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
527
+ ): <R>(self: Router<E, R>) => Router<E2, R | Router.ExcludeProvided<R2>>
531
528
  <R, E, E2, R2>(
532
529
  self: Router<E, R>,
533
530
  f: (e: Cause.Cause<E>) => Route.Handler<E2, R2>
534
- ): Router<E2, R | Exclude<R2, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
531
+ ): Router<E2, R | Router.ExcludeProvided<R2>>
535
532
  } = internal.catchAllCause
536
533
 
537
534
  /**
@@ -544,12 +541,12 @@ export const catchTag: {
544
541
  f: (e: Extract<E, { _tag: K }>) => Route.Handler<E1, R1>
545
542
  ): <R>(
546
543
  self: Router<E, R>
547
- ) => Router<E1 | Exclude<E, { _tag: K }>, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
544
+ ) => Router<E1 | Exclude<E, { _tag: K }>, R | Router.ExcludeProvided<R1>>
548
545
  <R, E, K extends E extends { _tag: string } ? E["_tag"] : never, E1, R1>(
549
546
  self: Router<E, R>,
550
547
  k: K,
551
548
  f: (e: Extract<E, { _tag: K }>) => Route.Handler<E1, R1>
552
- ): Router<E1 | Exclude<E, { _tag: K }>, R | Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>>
549
+ ): Router<E1 | Exclude<E, { _tag: K }>, R | Router.ExcludeProvided<R1>>
553
550
  } = internal.catchTag
554
551
 
555
552
  /**
@@ -572,11 +569,10 @@ export const catchTags: {
572
569
  [K in keyof Cases]: Cases[K] extends (...args: Array<any>) => Effect.Effect<any, infer E, any> ? E : never
573
570
  }[keyof Cases],
574
571
  | R
575
- | Exclude<
572
+ | Router.ExcludeProvided<
576
573
  {
577
574
  [K in keyof Cases]: Cases[K] extends (...args: Array<any>) => Effect.Effect<any, any, infer R> ? R : never
578
- }[keyof Cases],
579
- RouteContext | ServerRequest.ServerRequest | Scope.Scope
575
+ }[keyof Cases]
580
576
  >
581
577
  >
582
578
  <
@@ -594,11 +590,10 @@ export const catchTags: {
594
590
  [K in keyof Cases]: Cases[K] extends (...args: Array<any>) => Effect.Effect<any, infer E, any> ? E : never
595
591
  }[keyof Cases],
596
592
  | R
597
- | Exclude<
593
+ | Router.ExcludeProvided<
598
594
  {
599
595
  [K in keyof Cases]: Cases[K] extends (...args: Array<any>) => Effect.Effect<any, any, infer R> ? R : never
600
- }[keyof Cases],
601
- RouteContext | ServerRequest.ServerRequest | Scope.Scope
596
+ }[keyof Cases]
602
597
  >
603
598
  >
604
599
  } = internal.catchTags
@@ -632,7 +627,7 @@ export const provideServiceEffect: {
632
627
  ) => Router<
633
628
  E1 | E,
634
629
  | Exclude<R, Context.Tag.Identifier<T>>
635
- | Exclude<Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>, Context.Tag.Identifier<T>>
630
+ | Exclude<Router.ExcludeProvided<R1>, Context.Tag.Identifier<T>>
636
631
  >
637
632
  <R, E, T extends Context.Tag<any, any>, R1, E1>(
638
633
  self: Router<E, R>,
@@ -641,6 +636,6 @@ export const provideServiceEffect: {
641
636
  ): Router<
642
637
  E | E1,
643
638
  | Exclude<R, Context.Tag.Identifier<T>>
644
- | Exclude<Exclude<R1, RouteContext | ServerRequest.ServerRequest | Scope.Scope>, Context.Tag.Identifier<T>>
639
+ | Exclude<Router.ExcludeProvided<R1>, Context.Tag.Identifier<T>>
645
640
  >
646
641
  } = internal.provideServiceEffect
@@ -77,6 +77,28 @@ export interface ServerRequest extends IncomingMessage.IncomingMessage<Error.Req
77
77
  */
78
78
  export const ServerRequest: Context.Tag<ServerRequest, ServerRequest> = internal.serverRequestTag
79
79
 
80
+ /**
81
+ * @since 1.0.0
82
+ * @category search params
83
+ */
84
+ export interface ParsedSearchParams {
85
+ readonly _: unique symbol
86
+ }
87
+
88
+ /**
89
+ * @since 1.0.0
90
+ * @category search params
91
+ */
92
+ export const ParsedSearchParams: Context.Tag<ParsedSearchParams, ReadonlyRecord<string, string | Array<string>>> =
93
+ internal.parsedSearchParamsTag
94
+
95
+ /**
96
+ * @since 1.0.0
97
+ * @category search params
98
+ */
99
+ export const searchParamsFromURL: (url: URL) => ReadonlyRecord<string, string | Array<string>> =
100
+ internal.searchParamsFromURL
101
+
80
102
  /**
81
103
  * @since 1.0.0
82
104
  * @category accessors
@@ -125,6 +147,15 @@ export const schemaHeaders: <R, I extends Readonly<Record<string, string>>, A>(
125
147
  options?: ParseOptions | undefined
126
148
  ) => Effect.Effect<A, ParseResult.ParseError, ServerRequest | R> = internal.schemaHeaders
127
149
 
150
+ /**
151
+ * @since 1.0.0
152
+ * @category schema
153
+ */
154
+ export const schemaSearchParams: <R, I extends Readonly<Record<string, string | Array<string> | undefined>>, A>(
155
+ schema: Schema.Schema<A, I, R>,
156
+ options?: ParseOptions | undefined
157
+ ) => Effect.Effect<A, ParseResult.ParseError, ParsedSearchParams | R> = internal.schemaSearchParams
158
+
128
159
  /**
129
160
  * @since 1.0.0
130
161
  * @category schema
@@ -20,7 +20,10 @@ export interface UrlParams extends ReadonlyArray<readonly [string, string]> {}
20
20
  * @since 1.0.0
21
21
  * @category models
22
22
  */
23
- export type Input = Readonly<Record<string, string>> | Iterable<readonly [string, string]> | URLSearchParams
23
+ export type Input =
24
+ | Readonly<Record<string, string | ReadonlyArray<string>>>
25
+ | Iterable<readonly [string, string]>
26
+ | URLSearchParams
24
27
 
25
28
  /**
26
29
  * @since 1.0.0
@@ -30,7 +33,17 @@ export const fromInput = (input: Input): UrlParams => {
30
33
  if (Symbol.iterator in input) {
31
34
  return Arr.fromIterable(input)
32
35
  }
33
- return Arr.fromIterable(Object.entries(input))
36
+ const out: Array<readonly [string, string]> = []
37
+ for (const [key, value] of Object.entries(input)) {
38
+ if (Array.isArray(value)) {
39
+ for (let i = 0; i < value.length; i++) {
40
+ out.push([key, value[i]])
41
+ }
42
+ } else {
43
+ out.push([key, value as string])
44
+ }
45
+ }
46
+ return out
34
47
  }
35
48
 
36
49
  /**
@@ -53,6 +53,23 @@ export const withTracerDisabledWhen = dual<
53
53
  ) => Effect.Effect<A, E, R>
54
54
  >(2, (self, pred) => Effect.locally(self, currentTracerDisabledWhen, pred))
55
55
 
56
+ /** @internal */
57
+ export const currentTracerPropagation = globalValue(
58
+ Symbol.for("@effect/platform/Http/Client/currentTracerPropagation"),
59
+ () => FiberRef.unsafeMake(true)
60
+ )
61
+
62
+ /** @internal */
63
+ export const withTracerPropagation = dual<
64
+ (
65
+ enabled: boolean
66
+ ) => <R, E, A>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>,
67
+ <R, E, A>(
68
+ effect: Effect.Effect<A, E, R>,
69
+ enabled: boolean
70
+ ) => Effect.Effect<A, E, R>
71
+ >(2, (self, enabled) => Effect.locally(self, currentTracerPropagation, enabled))
72
+
56
73
  /** @internal */
57
74
  export const currentFetchOptions = globalValue(
58
75
  Symbol.for("@effect/platform/Http/Client/currentFetchOptions"),
@@ -115,7 +132,8 @@ export const makeDefault = (
115
132
  return Effect.fail(new Error.RequestError({ request, reason: "InvalidUrl", error: urlResult.left }))
116
133
  }
117
134
  const url = urlResult.right
118
- const tracerDisabled = fiber.getFiberRef(currentTracerDisabledWhen)(request)
135
+ const tracerDisabled = !fiber.getFiberRef(FiberRef.currentTracerEnabled) ||
136
+ fiber.getFiberRef(currentTracerDisabledWhen)(request)
119
137
  if (tracerDisabled) {
120
138
  return Effect.zipRight(
121
139
  addAbort,
@@ -145,10 +163,13 @@ export const makeDefault = (
145
163
  for (const name in redactedHeaders) {
146
164
  span.attribute(`http.request.header.${name}`, String(redactedHeaders[name]))
147
165
  }
166
+ request = fiber.getFiberRef(currentTracerPropagation)
167
+ ? internalRequest.setHeaders(request, TraceContext.toHeaders(span))
168
+ : request
148
169
  return Effect.tap(
149
170
  Effect.withParentSpan(
150
171
  f(
151
- internalRequest.setHeaders(request, TraceContext.toHeaders(span)),
172
+ request,
152
173
  url,
153
174
  controller.signal,
154
175
  fiber
@@ -6,10 +6,12 @@ import { globalValue } from "effect/GlobalValue"
6
6
  import * as Layer from "effect/Layer"
7
7
  import * as Option from "effect/Option"
8
8
  import type * as Predicate from "effect/Predicate"
9
+ import type * as App from "../../Http/App.js"
9
10
  import * as Headers from "../../Http/Headers.js"
10
11
  import type * as Middleware from "../../Http/Middleware.js"
11
12
  import * as ServerError from "../../Http/ServerError.js"
12
13
  import * as ServerRequest from "../../Http/ServerRequest.js"
14
+ import type { ServerResponse } from "../../Http/ServerResponse.js"
13
15
  import * as TraceContext from "../../Http/TraceContext.js"
14
16
 
15
17
  /** @internal */
@@ -179,3 +181,20 @@ export const xForwardedHeaders = make((httpApp) =>
179
181
  })
180
182
  : request)
181
183
  )
184
+
185
+ /** @internal */
186
+ export const searchParamsParser = <E, R>(httpApp: App.Default<E, R>) =>
187
+ Effect.withFiberRuntime<
188
+ ServerResponse,
189
+ E,
190
+ ServerRequest.ServerRequest | Exclude<R, ServerRequest.ParsedSearchParams>
191
+ >((fiber) => {
192
+ const context = fiber.getFiberRef(FiberRef.currentContext)
193
+ const request = Context.unsafeGet(context, ServerRequest.ServerRequest)
194
+ const params = ServerRequest.searchParamsFromURL(new URL(request.url))
195
+ return Effect.locally(
196
+ httpApp,
197
+ FiberRef.currentContext,
198
+ Context.add(context, ServerRequest.ParsedSearchParams, params)
199
+ ) as any
200
+ })