@effect/platform 0.50.8 → 0.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) 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/Multipart.js +12 -2
  7. package/dist/cjs/Http/Multipart.js.map +1 -1
  8. package/dist/cjs/Http/Router.js +1 -11
  9. package/dist/cjs/Http/Router.js.map +1 -1
  10. package/dist/cjs/Http/ServerRequest.js +17 -2
  11. package/dist/cjs/Http/ServerRequest.js.map +1 -1
  12. package/dist/cjs/Http/UrlParams.js +11 -1
  13. package/dist/cjs/Http/UrlParams.js.map +1 -1
  14. package/dist/cjs/internal/http/client.js +12 -4
  15. package/dist/cjs/internal/http/client.js.map +1 -1
  16. package/dist/cjs/internal/http/middleware.js +11 -2
  17. package/dist/cjs/internal/http/middleware.js.map +1 -1
  18. package/dist/cjs/internal/http/multipart.js +9 -3
  19. package/dist/cjs/internal/http/multipart.js.map +1 -1
  20. package/dist/cjs/internal/http/router.js +44 -39
  21. package/dist/cjs/internal/http/router.js.map +1 -1
  22. package/dist/cjs/internal/http/serverRequest.js +27 -1
  23. package/dist/cjs/internal/http/serverRequest.js.map +1 -1
  24. package/dist/dts/Http/App.d.ts.map +1 -1
  25. package/dist/dts/Http/Client.d.ts +13 -0
  26. package/dist/dts/Http/Client.d.ts.map +1 -1
  27. package/dist/dts/Http/Middleware.d.ts +5 -0
  28. package/dist/dts/Http/Middleware.d.ts.map +1 -1
  29. package/dist/dts/Http/Multipart.d.ts +11 -1
  30. package/dist/dts/Http/Multipart.d.ts.map +1 -1
  31. package/dist/dts/Http/Router.d.ts +47 -58
  32. package/dist/dts/Http/Router.d.ts.map +1 -1
  33. package/dist/dts/Http/ServerRequest.d.ts +22 -0
  34. package/dist/dts/Http/ServerRequest.d.ts.map +1 -1
  35. package/dist/dts/Http/UrlParams.d.ts +1 -1
  36. package/dist/dts/Http/UrlParams.d.ts.map +1 -1
  37. package/dist/dts/internal/http/router.d.ts.map +1 -1
  38. package/dist/esm/Http/App.js.map +1 -1
  39. package/dist/esm/Http/Client.js +10 -0
  40. package/dist/esm/Http/Client.js.map +1 -1
  41. package/dist/esm/Http/Middleware.js +5 -0
  42. package/dist/esm/Http/Middleware.js.map +1 -1
  43. package/dist/esm/Http/Multipart.js +11 -1
  44. package/dist/esm/Http/Multipart.js.map +1 -1
  45. package/dist/esm/Http/Router.js +0 -10
  46. package/dist/esm/Http/Router.js.map +1 -1
  47. package/dist/esm/Http/ServerRequest.js +15 -0
  48. package/dist/esm/Http/ServerRequest.js.map +1 -1
  49. package/dist/esm/Http/UrlParams.js +11 -1
  50. package/dist/esm/Http/UrlParams.js.map +1 -1
  51. package/dist/esm/internal/http/client.js +11 -3
  52. package/dist/esm/internal/http/client.js.map +1 -1
  53. package/dist/esm/internal/http/middleware.js +9 -1
  54. package/dist/esm/internal/http/middleware.js.map +1 -1
  55. package/dist/esm/internal/http/multipart.js +8 -2
  56. package/dist/esm/internal/http/multipart.js.map +1 -1
  57. package/dist/esm/internal/http/router.js +43 -37
  58. package/dist/esm/internal/http/router.js.map +1 -1
  59. package/dist/esm/internal/http/serverRequest.js +24 -0
  60. package/dist/esm/internal/http/serverRequest.js.map +1 -1
  61. package/package.json +5 -5
  62. package/src/Http/App.ts +1 -3
  63. package/src/Http/Client.ts +15 -0
  64. package/src/Http/Middleware.ts +11 -0
  65. package/src/Http/Multipart.ts +16 -1
  66. package/src/Http/Router.ts +80 -85
  67. package/src/Http/ServerRequest.ts +31 -0
  68. package/src/Http/UrlParams.ts +15 -2
  69. package/src/internal/http/client.ts +25 -2
  70. package/src/internal/http/middleware.ts +20 -1
  71. package/src/internal/http/multipart.ts +12 -2
  72. package/src/internal/http/router.ts +48 -47
  73. package/src/internal/http/serverRequest.ts +33 -0
@@ -38,19 +38,16 @@ const isRouter = (u: unknown): u is Router.Router<unknown, unknown> => Predicate
38
38
  /** @internal */
39
39
  export const params = Effect.map(RouteContext, (_) => _.params)
40
40
 
41
- /** @internal */
42
- export const searchParams = Effect.map(RouteContext, (_) => _.searchParams)
43
-
44
41
  /** @internal */
45
42
  export const schemaJson = <
46
43
  R,
47
44
  I extends Partial<{
48
45
  readonly method: Method.Method
49
46
  readonly url: string
50
- readonly cookies: Readonly<Record<string, string>>
51
- readonly headers: Readonly<Record<string, string>>
52
- readonly pathParams: Readonly<Record<string, string>>
53
- readonly searchParams: Readonly<Record<string, string>>
47
+ readonly cookies: Readonly<Record<string, string | undefined>>
48
+ readonly headers: Readonly<Record<string, string | undefined>>
49
+ readonly pathParams: Readonly<Record<string, string | undefined>>
50
+ readonly searchParams: Readonly<Record<string, string | Array<string> | undefined>>
54
51
  readonly body: any
55
52
  }>,
56
53
  A
@@ -60,18 +57,22 @@ export const schemaJson = <
60
57
  ) => {
61
58
  const parse = Schema.decodeUnknown(schema, options)
62
59
  return Effect.flatMap(
63
- ServerRequest.ServerRequest,
64
- (request) =>
65
- Effect.flatMap(Effect.zip(request.json, RouteContext), ([body, context]) =>
60
+ Effect.context<ServerRequest.ServerRequest | ServerRequest.ParsedSearchParams | Router.RouteContext>(),
61
+ (context) => {
62
+ const request = Context.get(context, ServerRequest.ServerRequest)
63
+ const searchParams = Context.get(context, ServerRequest.ParsedSearchParams)
64
+ const routeContext = Context.get(context, RouteContext)
65
+ return Effect.flatMap(request.json, (body) =>
66
66
  parse({
67
67
  method: request.method,
68
68
  url: request.url,
69
69
  headers: request.headers,
70
70
  cookies: request.cookies,
71
- pathParams: context.params,
72
- searchParams: context.searchParams,
71
+ pathParams: routeContext.params,
72
+ searchParams,
73
73
  body
74
74
  }))
75
+ }
75
76
  )
76
77
  }
77
78
 
@@ -81,10 +82,10 @@ export const schemaNoBody = <
81
82
  I extends Partial<{
82
83
  readonly method: Method.Method
83
84
  readonly url: string
84
- readonly cookies: Readonly<Record<string, string>>
85
- readonly headers: Readonly<Record<string, string>>
86
- readonly pathParams: Readonly<Record<string, string>>
87
- readonly searchParams: Readonly<Record<string, string>>
85
+ readonly cookies: Readonly<Record<string, string | undefined>>
86
+ readonly headers: Readonly<Record<string, string | undefined>>
87
+ readonly pathParams: Readonly<Record<string, string | undefined>>
88
+ readonly searchParams: Readonly<Record<string, string | Array<string> | undefined>>
88
89
  }>,
89
90
  A
90
91
  >(
@@ -93,31 +94,41 @@ export const schemaNoBody = <
93
94
  ) => {
94
95
  const parse = Schema.decodeUnknown(schema, options)
95
96
  return Effect.flatMap(
96
- ServerRequest.ServerRequest,
97
- (request) =>
98
- Effect.flatMap(RouteContext, (context) =>
99
- parse({
100
- method: request.method,
101
- url: request.url,
102
- headers: request.headers,
103
- cookies: request.cookies,
104
- pathParams: context.params,
105
- searchParams: context.searchParams
106
- }))
97
+ Effect.context<ServerRequest.ServerRequest | ServerRequest.ParsedSearchParams | Router.RouteContext>(),
98
+ (context) => {
99
+ const request = Context.get(context, ServerRequest.ServerRequest)
100
+ const searchParams = Context.get(context, ServerRequest.ParsedSearchParams)
101
+ const routeContext = Context.get(context, RouteContext)
102
+ return parse({
103
+ method: request.method,
104
+ url: request.url,
105
+ headers: request.headers,
106
+ cookies: request.cookies,
107
+ pathParams: routeContext.params,
108
+ searchParams
109
+ })
110
+ }
107
111
  )
108
112
  }
109
113
 
110
114
  /** @internal */
111
- export const schemaParams = <R, I extends Readonly<Record<string, string>>, A>(
115
+ export const schemaParams = <R, I extends Readonly<Record<string, string | Array<string> | undefined>>, A>(
112
116
  schema: Schema.Schema<A, I, R>,
113
117
  options?: ParseOptions | undefined
114
118
  ) => {
115
119
  const parse = Schema.decodeUnknown(schema, options)
116
- return Effect.flatMap(RouteContext, (_) => parse({ ..._.searchParams, ..._.params }))
120
+ return Effect.flatMap(
121
+ Effect.context<ServerRequest.ParsedSearchParams | Router.RouteContext>(),
122
+ (context) => {
123
+ const searchParams = Context.get(context, ServerRequest.ParsedSearchParams)
124
+ const routeContext = Context.get(context, RouteContext)
125
+ return parse({ ...searchParams, ...routeContext.params })
126
+ }
127
+ )
117
128
  }
118
129
 
119
130
  /** @internal */
120
- export const schemaPathParams = <R, I extends Readonly<Record<string, string>>, A>(
131
+ export const schemaPathParams = <R, I extends Readonly<Record<string, string | undefined>>, A>(
121
132
  schema: Schema.Schema<A, I, R>,
122
133
  options?: ParseOptions | undefined
123
134
  ) => {
@@ -125,15 +136,6 @@ export const schemaPathParams = <R, I extends Readonly<Record<string, string>>,
125
136
  return Effect.flatMap(RouteContext, (_) => parse(_.params))
126
137
  }
127
138
 
128
- /** @internal */
129
- export const schemaSearchParams = <R, I extends Readonly<Record<string, string>>, A>(
130
- schema: Schema.Schema<A, I, R>,
131
- options?: ParseOptions | undefined
132
- ) => {
133
- const parse = Schema.decodeUnknown(schema, options)
134
- return Effect.flatMap(RouteContext, (_) => parse(_.searchParams))
135
- }
136
-
137
139
  class RouterImpl<E = never, R = never> extends Effectable.StructuralClass<
138
140
  ServerResponse.ServerResponse,
139
141
  E | Error.RouteNotFound,
@@ -193,7 +195,6 @@ const toHttpApp = <R, E>(
193
195
  options?.includePrefix ? Option.none() : Option.some(path),
194
196
  false
195
197
  ),
196
- {},
197
198
  {}
198
199
  ),
199
200
  options
@@ -212,15 +213,15 @@ const toHttpApp = <R, E>(
212
213
  E | Error.RouteNotFound,
213
214
  R | ServerRequest.ServerRequest
214
215
  >((fiber) => {
215
- let context = fiber.getFiberRef(FiberRef.currentContext)
216
+ const context = Context.unsafeMake(new Map(fiber.getFiberRef(FiberRef.currentContext).unsafeMap))
216
217
  const request = Context.unsafeGet(context, ServerRequest.ServerRequest)
217
218
  if (mountsLen > 0) {
218
219
  for (let i = 0; i < mountsLen; i++) {
219
220
  const [path, routeContext, options] = mounts[i]
220
221
  if (request.url.startsWith(path)) {
221
- context = Context.add(context, RouteContext, routeContext)
222
+ context.unsafeMap.set(RouteContext.key, routeContext)
222
223
  if (options?.includePrefix !== true) {
223
- context = Context.add(context, ServerRequest.ServerRequest, sliceRequestUrl(request, path))
224
+ context.unsafeMap.set(ServerRequest.ServerRequest.key, sliceRequestUrl(request, path))
224
225
  }
225
226
  return Effect.locally(
226
227
  routeContext.route.handler as App.Default<E, R>,
@@ -240,9 +241,10 @@ const toHttpApp = <R, E>(
240
241
  }
241
242
  const route = result.handler
242
243
  if (route.prefix._tag === "Some") {
243
- context = Context.add(context, ServerRequest.ServerRequest, sliceRequestUrl(request, route.prefix.value))
244
+ context.unsafeMap.set(ServerRequest.ServerRequest.key, sliceRequestUrl(request, route.prefix.value))
244
245
  }
245
- context = Context.add(context, RouteContext, new RouteContextImpl(route, result.params, result.searchParams))
246
+ context.unsafeMap.set(ServerRequest.ParsedSearchParams.key, result.searchParams)
247
+ context.unsafeMap.set(RouteContext.key, new RouteContextImpl(route, result.params))
246
248
 
247
249
  const span = Context.getOption(context, Tracer.ParentSpan)
248
250
  if (span._tag === "Some" && span.value._tag === "Span") {
@@ -294,8 +296,7 @@ class RouteContextImpl implements Router.RouteContext {
294
296
  readonly [RouteContextTypeId]: Router.RouteContextTypeId
295
297
  constructor(
296
298
  readonly route: Router.Route<unknown, unknown>,
297
- readonly params: Readonly<Record<string, string | undefined>>,
298
- readonly searchParams: Readonly<Record<string, string>>
299
+ readonly params: Readonly<Record<string, string | undefined>>
299
300
  ) {
300
301
  this[RouteContextTypeId] = RouteContextTypeId
301
302
  }
@@ -27,6 +27,12 @@ export const TypeId: ServerRequest.TypeId = Symbol.for("@effect/platform/Http/Se
27
27
  /** @internal */
28
28
  export const serverRequestTag = Context.GenericTag<ServerRequest.ServerRequest>("@effect/platform/Http/ServerRequest")
29
29
 
30
+ /** @internal */
31
+ export const parsedSearchParamsTag = Context.GenericTag<
32
+ ServerRequest.ParsedSearchParams,
33
+ ReadonlyRecord<string, string | Array<string>>
34
+ >("@effect/platform/Http/ServerRequest/ParsedSearchParams")
35
+
30
36
  /** @internal */
31
37
  export const upgrade = Effect.flatMap(serverRequestTag, (request) => request.upgrade)
32
38
 
@@ -36,6 +42,24 @@ export const upgradeChannel = <IE = never>() => Channel.unwrap(Effect.map(upgrad
36
42
  /** @internal */
37
43
  export const multipartPersisted = Effect.flatMap(serverRequestTag, (request) => request.multipart)
38
44
 
45
+ /** @internal */
46
+ export const searchParamsFromURL = (url: URL): ReadonlyRecord<string, string | Array<string>> => {
47
+ const out: Record<string, string | Array<string>> = {}
48
+ for (const [key, value] of url.searchParams.entries()) {
49
+ const entry = out[key]
50
+ if (entry !== undefined) {
51
+ if (Array.isArray(entry)) {
52
+ entry.push(value)
53
+ } else {
54
+ out[key] = [entry, value]
55
+ }
56
+ } else {
57
+ out[key] = value
58
+ }
59
+ }
60
+ return out
61
+ }
62
+
39
63
  /** @internal */
40
64
  export const schemaCookies = <R, I extends Readonly<Record<string, string>>, A>(
41
65
  schema: Schema.Schema<A, I, R>,
@@ -54,6 +78,15 @@ export const schemaHeaders = <R, I extends Readonly<Record<string, string>>, A>(
54
78
  return Effect.flatMap(serverRequestTag, parse)
55
79
  }
56
80
 
81
+ /** @internal */
82
+ export const schemaSearchParams = <R, I extends Readonly<Record<string, string | Array<string> | undefined>>, A>(
83
+ schema: Schema.Schema<A, I, R>,
84
+ options?: ParseOptions | undefined
85
+ ) => {
86
+ const parse = Schema.decodeUnknown(schema, options)
87
+ return Effect.flatMap(parsedSearchParamsTag, parse)
88
+ }
89
+
57
90
  /** @internal */
58
91
  export const schemaBodyJson = <A, I, R>(schema: Schema.Schema<A, I, R>, options?: ParseOptions | undefined) => {
59
92
  const parse = IncomingMessage.schemaBodyJson(schema, options)