@effect/platform 0.11.4 → 0.12.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 (201) hide show
  1. package/Command.d.ts +3 -2
  2. package/Command.d.ts.map +1 -1
  3. package/Command.js.map +1 -1
  4. package/FileSystem.d.ts +16 -9
  5. package/FileSystem.d.ts.map +1 -1
  6. package/FileSystem.js.map +1 -1
  7. package/Http/App.d.ts +18 -0
  8. package/Http/App.d.ts.map +1 -0
  9. package/Http/App.js +6 -0
  10. package/Http/App.js.map +1 -0
  11. package/Http/Body.d.ts +37 -14
  12. package/Http/Body.d.ts.map +1 -1
  13. package/Http/Body.js +17 -5
  14. package/Http/Body.js.map +1 -1
  15. package/Http/Client.d.ts +8 -2
  16. package/Http/Client.d.ts.map +1 -1
  17. package/Http/Client.js +10 -4
  18. package/Http/Client.js.map +1 -1
  19. package/Http/ClientRequest.d.ts +44 -1
  20. package/Http/ClientRequest.d.ts.map +1 -1
  21. package/Http/ClientRequest.js +21 -3
  22. package/Http/ClientRequest.js.map +1 -1
  23. package/Http/ClientResponse.d.ts +13 -1
  24. package/Http/ClientResponse.d.ts.map +1 -1
  25. package/Http/ClientResponse.js +14 -2
  26. package/Http/ClientResponse.js.map +1 -1
  27. package/Http/FormData.d.ts +97 -4
  28. package/Http/FormData.d.ts.map +1 -1
  29. package/Http/FormData.js +77 -2
  30. package/Http/FormData.js.map +1 -1
  31. package/Http/Headers.d.ts +29 -3
  32. package/Http/Headers.d.ts.map +1 -1
  33. package/Http/Headers.js +13 -1
  34. package/Http/Headers.js.map +1 -1
  35. package/Http/IncomingMessage.d.ts +26 -5
  36. package/Http/IncomingMessage.d.ts.map +1 -1
  37. package/Http/IncomingMessage.js +38 -3
  38. package/Http/IncomingMessage.js.map +1 -1
  39. package/Http/Middleware.d.ts +56 -0
  40. package/Http/Middleware.d.ts.map +1 -0
  41. package/Http/Middleware.js +46 -0
  42. package/Http/Middleware.js.map +1 -0
  43. package/Http/Router.d.ts +221 -0
  44. package/Http/Router.d.ts.map +1 -0
  45. package/Http/Router.js +148 -0
  46. package/Http/Router.js.map +1 -0
  47. package/Http/Server.d.ts +85 -0
  48. package/Http/Server.d.ts.map +1 -0
  49. package/Http/Server.js +34 -0
  50. package/Http/Server.js.map +1 -0
  51. package/Http/ServerError.d.ts +96 -0
  52. package/Http/ServerError.d.ts.map +1 -0
  53. package/Http/ServerError.js +40 -0
  54. package/Http/ServerError.js.map +1 -0
  55. package/Http/ServerRequest.d.ts +82 -0
  56. package/Http/ServerRequest.d.ts.map +1 -0
  57. package/Http/ServerRequest.js +66 -0
  58. package/Http/ServerRequest.js.map +1 -0
  59. package/Http/ServerResponse.d.ts +168 -0
  60. package/Http/ServerResponse.d.ts.map +1 -0
  61. package/Http/ServerResponse.js +116 -0
  62. package/Http/ServerResponse.js.map +1 -0
  63. package/Http/UrlParams.d.ts +20 -5
  64. package/Http/UrlParams.d.ts.map +1 -1
  65. package/Http/UrlParams.js.map +1 -1
  66. package/HttpServer.d.ts +44 -0
  67. package/HttpServer.d.ts.map +1 -0
  68. package/HttpServer.js +29 -0
  69. package/HttpServer.js.map +1 -0
  70. package/internal/command.js +9 -2
  71. package/internal/command.js.map +1 -1
  72. package/internal/fileSystem.js +15 -11
  73. package/internal/fileSystem.js.map +1 -1
  74. package/internal/http/body.js +28 -28
  75. package/internal/http/body.js.map +1 -1
  76. package/internal/http/client.d.ts.map +1 -1
  77. package/internal/http/client.js +41 -27
  78. package/internal/http/client.js.map +1 -1
  79. package/internal/http/clientRequest.js +22 -6
  80. package/internal/http/clientRequest.js.map +1 -1
  81. package/internal/http/clientResponse.js +15 -12
  82. package/internal/http/clientResponse.js.map +1 -1
  83. package/internal/http/formData.d.ts +8 -0
  84. package/internal/http/formData.d.ts.map +1 -0
  85. package/internal/http/formData.js +88 -0
  86. package/internal/http/formData.js.map +1 -0
  87. package/internal/http/middleware.d.ts +2 -0
  88. package/internal/http/middleware.d.ts.map +1 -0
  89. package/internal/http/middleware.js +43 -0
  90. package/internal/http/middleware.js.map +1 -0
  91. package/internal/http/router.d.ts +2 -0
  92. package/internal/http/router.d.ts.map +1 -0
  93. package/internal/http/router.js +187 -0
  94. package/internal/http/router.js.map +1 -0
  95. package/internal/http/server.d.ts +2 -0
  96. package/internal/http/server.d.ts.map +1 -0
  97. package/internal/http/server.js +30 -0
  98. package/internal/http/server.js.map +1 -0
  99. package/internal/http/serverError.d.ts +2 -0
  100. package/internal/http/serverError.d.ts.map +1 -0
  101. package/internal/http/serverError.js +30 -0
  102. package/internal/http/serverError.js.map +1 -0
  103. package/internal/http/serverRequest.d.ts +2 -0
  104. package/internal/http/serverRequest.d.ts.map +1 -0
  105. package/internal/http/serverRequest.js +57 -0
  106. package/internal/http/serverRequest.js.map +1 -0
  107. package/internal/http/serverResponse.d.ts +2 -0
  108. package/internal/http/serverResponse.d.ts.map +1 -0
  109. package/internal/http/serverResponse.js +109 -0
  110. package/internal/http/serverResponse.js.map +1 -0
  111. package/mjs/Command.mjs.map +1 -1
  112. package/mjs/FileSystem.mjs.map +1 -1
  113. package/mjs/Http/App.mjs +2 -0
  114. package/mjs/Http/App.mjs.map +1 -0
  115. package/mjs/Http/Body.mjs +12 -2
  116. package/mjs/Http/Body.mjs.map +1 -1
  117. package/mjs/Http/Client.mjs +6 -1
  118. package/mjs/Http/Client.mjs.map +1 -1
  119. package/mjs/Http/ClientRequest.mjs +16 -1
  120. package/mjs/Http/ClientRequest.mjs.map +1 -1
  121. package/mjs/Http/ClientResponse.mjs +11 -1
  122. package/mjs/Http/ClientResponse.mjs.map +1 -1
  123. package/mjs/Http/FormData.mjs +62 -1
  124. package/mjs/Http/FormData.mjs.map +1 -1
  125. package/mjs/Http/Headers.mjs +10 -0
  126. package/mjs/Http/Headers.mjs.map +1 -1
  127. package/mjs/Http/IncomingMessage.mjs +32 -1
  128. package/mjs/Http/IncomingMessage.mjs.map +1 -1
  129. package/mjs/Http/Middleware.mjs +32 -0
  130. package/mjs/Http/Middleware.mjs.map +1 -0
  131. package/mjs/Http/Router.mjs +117 -0
  132. package/mjs/Http/Router.mjs.map +1 -0
  133. package/mjs/Http/Server.mjs +22 -0
  134. package/mjs/Http/Server.mjs.map +1 -0
  135. package/mjs/Http/ServerError.mjs +27 -0
  136. package/mjs/Http/ServerError.mjs.map +1 -0
  137. package/mjs/Http/ServerRequest.mjs +48 -0
  138. package/mjs/Http/ServerRequest.mjs.map +1 -0
  139. package/mjs/Http/ServerResponse.mjs +90 -0
  140. package/mjs/Http/ServerResponse.mjs.map +1 -0
  141. package/mjs/Http/UrlParams.mjs.map +1 -1
  142. package/mjs/HttpServer.mjs +24 -0
  143. package/mjs/HttpServer.mjs.map +1 -0
  144. package/mjs/internal/command.mjs +9 -2
  145. package/mjs/internal/command.mjs.map +1 -1
  146. package/mjs/internal/fileSystem.mjs +15 -11
  147. package/mjs/internal/fileSystem.mjs.map +1 -1
  148. package/mjs/internal/http/body.mjs +23 -25
  149. package/mjs/internal/http/body.mjs.map +1 -1
  150. package/mjs/internal/http/client.mjs +37 -24
  151. package/mjs/internal/http/client.mjs.map +1 -1
  152. package/mjs/internal/http/clientRequest.mjs +16 -4
  153. package/mjs/internal/http/clientRequest.mjs.map +1 -1
  154. package/mjs/internal/http/clientResponse.mjs +15 -12
  155. package/mjs/internal/http/clientResponse.mjs.map +1 -1
  156. package/mjs/internal/http/formData.mjs +67 -0
  157. package/mjs/internal/http/formData.mjs.map +1 -0
  158. package/mjs/internal/http/middleware.mjs +29 -0
  159. package/mjs/internal/http/middleware.mjs.map +1 -0
  160. package/mjs/internal/http/router.mjs +155 -0
  161. package/mjs/internal/http/router.mjs.map +1 -0
  162. package/mjs/internal/http/server.mjs +17 -0
  163. package/mjs/internal/http/server.mjs.map +1 -0
  164. package/mjs/internal/http/serverError.mjs +17 -0
  165. package/mjs/internal/http/serverError.mjs.map +1 -0
  166. package/mjs/internal/http/serverRequest.mjs +41 -0
  167. package/mjs/internal/http/serverRequest.mjs.map +1 -0
  168. package/mjs/internal/http/serverResponse.mjs +82 -0
  169. package/mjs/internal/http/serverResponse.mjs.map +1 -0
  170. package/package.json +2 -1
  171. package/src/Command.ts +3 -2
  172. package/src/FileSystem.ts +20 -25
  173. package/src/Http/App.ts +19 -0
  174. package/src/Http/Body.ts +41 -14
  175. package/src/Http/Client.ts +13 -2
  176. package/src/Http/ClientRequest.ts +52 -2
  177. package/src/Http/ClientResponse.ts +13 -1
  178. package/src/Http/FormData.ts +121 -5
  179. package/src/Http/Headers.ts +37 -3
  180. package/src/Http/IncomingMessage.ts +46 -3
  181. package/src/Http/Middleware.ts +69 -0
  182. package/src/Http/Router.ts +342 -0
  183. package/src/Http/Server.ts +134 -0
  184. package/src/Http/ServerError.ts +111 -0
  185. package/src/Http/ServerRequest.ts +120 -0
  186. package/src/Http/ServerResponse.ts +202 -0
  187. package/src/Http/UrlParams.ts +20 -5
  188. package/src/HttpServer.ts +44 -0
  189. package/src/internal/command.ts +9 -2
  190. package/src/internal/fileSystem.ts +10 -7
  191. package/src/internal/http/body.ts +65 -39
  192. package/src/internal/http/client.ts +96 -76
  193. package/src/internal/http/clientRequest.ts +64 -4
  194. package/src/internal/http/clientResponse.ts +21 -13
  195. package/src/internal/http/formData.ts +140 -0
  196. package/src/internal/http/middleware.ts +72 -0
  197. package/src/internal/http/router.ts +298 -0
  198. package/src/internal/http/server.ts +80 -0
  199. package/src/internal/http/serverError.ts +26 -0
  200. package/src/internal/http/serverRequest.ts +71 -0
  201. package/src/internal/http/serverResponse.ts +255 -0
package/src/FileSystem.ts CHANGED
@@ -219,7 +219,7 @@ export interface FileSystem {
219
219
  */
220
220
  readonly truncate: (
221
221
  path: string,
222
- length?: Size
222
+ length?: SizeInput
223
223
  ) => Effect.Effect<never, PlatformError, void>
224
224
  /**
225
225
  * Change the file system timestamps of the file at `path`.
@@ -255,11 +255,19 @@ export interface FileSystem {
255
255
  */
256
256
  export type Size = Brand.Branded<bigint, "Size">
257
257
 
258
+ /**
259
+ * Represents a size in bytes.
260
+ *
261
+ * @since 1.0.0
262
+ * @category model
263
+ */
264
+ export type SizeInput = bigint | number | Size
265
+
258
266
  /**
259
267
  * @since 1.0.0
260
268
  * @category constructor
261
269
  */
262
- export const Size: (bytes: number | bigint) => Size = internal.Size
270
+ export const Size: (bytes: SizeInput) => Size = internal.Size
263
271
 
264
272
  /**
265
273
  * @since 1.0.0
@@ -360,9 +368,9 @@ export interface SinkOptions extends OpenFileOptions {}
360
368
  */
361
369
  export interface StreamOptions {
362
370
  readonly bufferSize?: number
363
- readonly bytesToRead?: Size
364
- readonly chunkSize?: Size
365
- readonly offset?: Size
371
+ readonly bytesToRead?: SizeInput
372
+ readonly chunkSize?: SizeInput
373
+ readonly offset?: SizeInput
366
374
  }
367
375
 
368
376
  /**
@@ -422,28 +430,15 @@ export const isFile = (u: unknown): u is File => typeof u === "object" && u !==
422
430
  * @category model
423
431
  */
424
432
  export interface File {
425
- readonly [FileTypeId]: (_: never) => unknown
433
+ readonly [FileTypeId]: FileTypeId
426
434
  readonly fd: File.Descriptor
427
435
  readonly stat: Effect.Effect<never, PlatformError, File.Info>
428
- readonly seek: (
429
- offset: Size,
430
- from: SeekMode
431
- ) => Effect.Effect<never, never, void>
432
- readonly read: (
433
- buffer: Uint8Array
434
- ) => Effect.Effect<never, PlatformError, Size>
435
- readonly readAlloc: (
436
- size: Size
437
- ) => Effect.Effect<never, PlatformError, Option<Uint8Array>>
438
- readonly truncate: (
439
- length?: Size
440
- ) => Effect.Effect<never, PlatformError, void>
441
- readonly write: (
442
- buffer: Uint8Array
443
- ) => Effect.Effect<never, PlatformError, Size>
444
- readonly writeAll: (
445
- buffer: Uint8Array
446
- ) => Effect.Effect<never, PlatformError, void>
436
+ readonly seek: (offset: SizeInput, from: SeekMode) => Effect.Effect<never, never, void>
437
+ readonly read: (buffer: Uint8Array) => Effect.Effect<never, PlatformError, Size>
438
+ readonly readAlloc: (size: SizeInput) => Effect.Effect<never, PlatformError, Option<Uint8Array>>
439
+ readonly truncate: (length?: SizeInput) => Effect.Effect<never, PlatformError, void>
440
+ readonly write: (buffer: Uint8Array) => Effect.Effect<never, PlatformError, Size>
441
+ readonly writeAll: (buffer: Uint8Array) => Effect.Effect<never, PlatformError, void>
447
442
  }
448
443
 
449
444
  /**
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @since 1.0.0
3
+ */
4
+ import type * as Effect from "@effect/io/Effect"
5
+ import type * as ServerRequest from "@effect/platform/Http/ServerRequest"
6
+ import type * as ServerResponse from "@effect/platform/Http/ServerResponse"
7
+
8
+ /**
9
+ * @since 1.0.0
10
+ * @category models
11
+ */
12
+ export interface HttpApp<R, E, A> extends Effect.Effect<R | ServerRequest.ServerRequest, E, A> {
13
+ }
14
+
15
+ /**
16
+ * @since 1.0.0
17
+ * @category models
18
+ */
19
+ export type Default<R, E> = HttpApp<R, E, ServerResponse.ServerResponse>
package/src/Http/Body.ts CHANGED
@@ -2,6 +2,8 @@
2
2
  * @since 1.0.0
3
3
  */
4
4
  import type * as Effect from "@effect/io/Effect"
5
+ import type * as PlatformError from "@effect/platform/Error"
6
+ import type * as FileSystem from "@effect/platform/FileSystem"
5
7
  import * as internal from "@effect/platform/internal/http/body"
6
8
  import type * as Schema from "@effect/schema/Schema"
7
9
  import type * as Stream_ from "@effect/stream/Stream"
@@ -22,7 +24,13 @@ export type TypeId = typeof TypeId
22
24
  * @since 1.0.0
23
25
  * @category models
24
26
  */
25
- export type Body = Empty | Raw | Bytes | BytesEffect | FormData | Stream
27
+ export type Body = Empty | Raw | Uint8Array | EffectBody | FormData | Stream
28
+
29
+ /**
30
+ * @since 1.0.0
31
+ * @category models
32
+ */
33
+ export type NonEffect = Exclude<Body, EffectBody>
26
34
 
27
35
  /**
28
36
  * @since 1.0.0
@@ -73,49 +81,57 @@ export const raw: (body: unknown) => Raw = internal.raw
73
81
  * @since 1.0.0
74
82
  * @category models
75
83
  */
76
- export interface Bytes extends Body.Proto {
77
- readonly _tag: "Bytes"
78
- readonly body: Uint8Array
84
+ export interface Uint8Array extends Body.Proto {
85
+ readonly _tag: "Uint8Array"
86
+ readonly body: globalThis.Uint8Array
87
+ readonly contentType: string
88
+ readonly contentLength: number
79
89
  }
80
90
 
81
91
  /**
82
92
  * @since 1.0.0
83
93
  * @category constructors
84
94
  */
85
- export const bytes: (body: Uint8Array) => Bytes = internal.bytes
95
+ export const uint8Array: (body: globalThis.Uint8Array) => Uint8Array = internal.uint8Array
86
96
 
87
97
  /**
88
98
  * @since 1.0.0
89
99
  * @category constructors
90
100
  */
91
- export const text: (body: string, contentType?: string) => Bytes = internal.text
101
+ export const text: (body: string, contentType?: string) => Uint8Array = internal.text
92
102
 
93
103
  /**
94
104
  * @since 1.0.0
95
105
  * @category models
96
106
  */
97
- export interface BytesEffect extends Body.Proto {
98
- readonly _tag: "BytesEffect"
99
- readonly body: Effect.Effect<never, unknown, Uint8Array>
107
+ export interface EffectBody extends Body.Proto {
108
+ readonly _tag: "Effect"
109
+ readonly effect: Effect.Effect<never, unknown, NonEffect>
100
110
  }
101
111
 
102
112
  /**
103
113
  * @since 1.0.0
104
114
  * @category constructors
105
115
  */
106
- export const bytesEffect: (body: Effect.Effect<never, unknown, Uint8Array>) => BytesEffect = internal.bytesEffect
116
+ export const effect: (body: Effect.Effect<never, unknown, NonEffect>) => EffectBody = internal.effect
107
117
 
108
118
  /**
109
119
  * @since 1.0.0
110
120
  * @category constructors
111
121
  */
112
- export const json: (body: unknown) => BytesEffect = internal.json
122
+ export const unsafeJson: (body: unknown) => Uint8Array = internal.unsafeJson
113
123
 
114
124
  /**
115
125
  * @since 1.0.0
116
126
  * @category constructors
117
127
  */
118
- export const jsonSchema: <I, A>(schema: Schema.Schema<I, A>) => (body: A) => BytesEffect = internal.jsonSchema
128
+ export const json: (body: unknown) => EffectBody = internal.json
129
+
130
+ /**
131
+ * @since 1.0.0
132
+ * @category constructors
133
+ */
134
+ export const jsonSchema: <I, A>(schema: Schema.Schema<I, A>) => (body: A) => EffectBody = internal.jsonSchema
119
135
 
120
136
  /**
121
137
  * @since 1.0.0
@@ -138,11 +154,22 @@ export const formData: (body: globalThis.FormData) => FormData = internal.formDa
138
154
  */
139
155
  export interface Stream extends Body.Proto {
140
156
  readonly _tag: "Stream"
141
- readonly stream: Stream_.Stream<never, unknown, Uint8Array>
157
+ readonly stream: Stream_.Stream<never, unknown, globalThis.Uint8Array>
158
+ readonly contentType: string
159
+ readonly contentLength?: number
142
160
  }
143
161
 
144
162
  /**
145
163
  * @since 1.0.0
146
164
  * @category constructors
147
165
  */
148
- export const stream: (body: Stream_.Stream<never, unknown, Uint8Array>) => Stream = internal.stream
166
+ export const stream: (body: Stream_.Stream<never, unknown, globalThis.Uint8Array>) => Stream = internal.stream
167
+
168
+ /**
169
+ * @since 1.0.0
170
+ * @category constructors
171
+ */
172
+ export const file: (
173
+ path: string,
174
+ options?: FileSystem.StreamOptions & { readonly contentType?: string }
175
+ ) => Effect.Effect<FileSystem.FileSystem, PlatformError.PlatformError, Stream> = internal.file
@@ -2,6 +2,7 @@
2
2
  * @since 1.0.0
3
3
  */
4
4
  import type * as Context from "@effect/data/Context"
5
+ import type { Pipeable } from "@effect/data/Pipeable"
5
6
  import type * as Predicate from "@effect/data/Predicate"
6
7
  import type * as Effect from "@effect/io/Effect"
7
8
  import type * as Layer from "@effect/io/Layer"
@@ -17,7 +18,7 @@ import type * as Schema from "@effect/schema/Schema"
17
18
  * @since 1.0.0
18
19
  * @category models
19
20
  */
20
- export interface Client<R, E, A> {
21
+ export interface Client<R, E, A> extends Pipeable {
21
22
  (request: ClientRequest.ClientRequest): Effect.Effect<R, E, A>
22
23
  }
23
24
 
@@ -48,7 +49,7 @@ export const Client: Context.Tag<Client.Default, Client.Default> = internal.tag
48
49
  * @since 1.0.0
49
50
  * @category layers
50
51
  */
51
- export const fetchLayer: Layer.Layer<never, never, Client.Default> = internal.fetchLayer
52
+ export const layer: Layer.Layer<never, never, Client.Default> = internal.layer
52
53
 
53
54
  /**
54
55
  * @since 1.0.0
@@ -184,6 +185,16 @@ export const filterStatusOk: <R, E>(
184
185
  self: Client.WithResponse<R, E>
185
186
  ) => Client.WithResponse<R, Error.ResponseError | E> = internal.filterStatusOk
186
187
 
188
+ /**
189
+ * @since 1.0.0
190
+ * @category constructors
191
+ */
192
+ export const make: (
193
+ f: (
194
+ request: ClientRequest.ClientRequest.NonEffectBody
195
+ ) => Effect.Effect<never, Error.HttpClientError, ClientResponse.ClientResponse>
196
+ ) => Client.Default = internal.make
197
+
187
198
  /**
188
199
  * @since 1.0.0
189
200
  * @category mapping & sequencing
@@ -2,6 +2,9 @@
2
2
  * @since 1.0.0
3
3
  */
4
4
  import type { Pipeable } from "@effect/data/Pipeable"
5
+ import type * as Effect from "@effect/io/Effect"
6
+ import type * as PlatformError from "@effect/platform/Error"
7
+ import type * as FileSystem from "@effect/platform/FileSystem"
5
8
  import type * as Body from "@effect/platform/Http/Body"
6
9
  import type * as Error from "@effect/platform/Http/ClientError"
7
10
  import type * as Headers from "@effect/platform/Http/Headers"
@@ -36,6 +39,19 @@ export interface ClientRequest extends Pipeable {
36
39
  readonly body: Body.Body
37
40
  }
38
41
 
42
+ /**
43
+ * @since 1.0.0
44
+ */
45
+ export namespace ClientRequest {
46
+ /**
47
+ * @since 1.0.0
48
+ * @category models
49
+ */
50
+ export interface NonEffectBody extends ClientRequest {
51
+ readonly body: Body.NonEffect
52
+ }
53
+ }
54
+
39
55
  /**
40
56
  * @since 1.0.0
41
57
  * @category models
@@ -253,10 +269,19 @@ export const setBody: {
253
269
  * @since 1.0.0
254
270
  * @category combinators
255
271
  */
256
- export const binaryBody: {
272
+ export const uint8ArrayBody: {
257
273
  (body: Uint8Array, contentType?: string): (self: ClientRequest) => ClientRequest
258
274
  (self: ClientRequest, body: Uint8Array, contentType?: string): ClientRequest
259
- } = internal.binaryBody
275
+ } = internal.uint8ArrayBody
276
+
277
+ /**
278
+ * @since 1.0.0
279
+ * @category combinators
280
+ */
281
+ export const effectBody: {
282
+ (body: Effect.Effect<never, unknown, Body.NonEffect>): (self: ClientRequest) => ClientRequest
283
+ (self: ClientRequest, body: Effect.Effect<never, unknown, Body.NonEffect>): ClientRequest
284
+ } = internal.effectBody
260
285
 
261
286
  /**
262
287
  * @since 1.0.0
@@ -276,6 +301,15 @@ export const jsonBody: {
276
301
  (self: ClientRequest, body: unknown): ClientRequest
277
302
  } = internal.jsonBody
278
303
 
304
+ /**
305
+ * @since 1.0.0
306
+ * @category combinators
307
+ */
308
+ export const unsafeJsonBody: {
309
+ (body: unknown): (self: ClientRequest) => ClientRequest
310
+ (self: ClientRequest, body: unknown): ClientRequest
311
+ } = internal.unsafeJsonBody
312
+
279
313
  /**
280
314
  * @since 1.0.0
281
315
  * @category combinators
@@ -318,3 +352,19 @@ export const streamBody: {
318
352
  options?: { readonly contentType?: string; readonly contentLength?: number }
319
353
  ): ClientRequest
320
354
  } = internal.streamBody
355
+
356
+ /**
357
+ * @since 1.0.0
358
+ * @category combinators
359
+ */
360
+ export const fileBody: {
361
+ (
362
+ path: string,
363
+ options?: FileSystem.StreamOptions & { readonly contentType?: string }
364
+ ): (self: ClientRequest) => Effect.Effect<FileSystem.FileSystem, PlatformError.PlatformError, ClientRequest>
365
+ (
366
+ self: ClientRequest,
367
+ path: string,
368
+ options?: FileSystem.StreamOptions & { readonly contentType?: string }
369
+ ): Effect.Effect<FileSystem.FileSystem, PlatformError.PlatformError, ClientRequest>
370
+ } = internal.fileBody
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * @since 1.0.0
3
3
  */
4
+ import type * as Effect from "@effect/io/Effect"
4
5
  import type * as Error from "@effect/platform/Http/ClientError"
5
6
  import type * as ClientRequest from "@effect/platform/Http/ClientRequest"
6
7
  import type * as IncomingMessage from "@effect/platform/Http/IncomingMessage"
@@ -11,7 +12,17 @@ export {
11
12
  * @since 1.0.0
12
13
  * @category schema
13
14
  */
14
- parseSchema
15
+ schemaBodyJson,
16
+ /**
17
+ * @since 1.0.0
18
+ * @category schema
19
+ */
20
+ schemaBodyUrlParams,
21
+ /**
22
+ * @since 1.0.0
23
+ * @category schema
24
+ */
25
+ schemaHeaders
15
26
  } from "@effect/platform/Http/IncomingMessage"
16
27
 
17
28
  /**
@@ -33,6 +44,7 @@ export type TypeId = typeof TypeId
33
44
  export interface ClientResponse extends IncomingMessage.IncomingMessage<Error.ResponseError> {
34
45
  readonly [TypeId]: TypeId
35
46
  readonly status: number
47
+ readonly formData: Effect.Effect<never, Error.ResponseError, FormData>
36
48
  }
37
49
 
38
50
  /**
@@ -1,14 +1,22 @@
1
1
  /**
2
2
  * @since 1.0.0
3
3
  */
4
- import type * as Error from "@effect/platform/Http/ClientError"
4
+ import type * as Chunk from "@effect/data/Chunk"
5
+ import type * as Data from "@effect/data/Data"
6
+ import type * as Option from "@effect/data/Option"
7
+ import type * as Effect from "@effect/io/Effect"
8
+ import type * as FiberRef from "@effect/io/FiberRef"
9
+ import type * as FileSystem from "@effect/platform/FileSystem"
10
+ import * as internal from "@effect/platform/internal/http/formData"
11
+ import type * as ParseResult from "@effect/schema/ParseResult"
12
+ import type * as Schema from "@effect/schema/Schema"
5
13
  import type * as Stream from "@effect/stream/Stream"
6
14
 
7
15
  /**
8
16
  * @since 1.0.0
9
17
  * @category type ids
10
18
  */
11
- export const TypeId = Symbol.for("@effect/platform/Http/FormData")
19
+ export const TypeId: unique symbol = internal.TypeId
12
20
 
13
21
  /**
14
22
  * @since 1.0.0
@@ -41,7 +49,7 @@ export namespace Part {
41
49
  * @category models
42
50
  */
43
51
  export interface Field extends Part.Proto {
44
- readonly _tag: "FormDataField"
52
+ readonly _tag: "Field"
45
53
  readonly key: string
46
54
  readonly contentType: string
47
55
  readonly value: string
@@ -56,6 +64,114 @@ export interface File extends Part.Proto {
56
64
  readonly key: string
57
65
  readonly name: string
58
66
  readonly contentType: string
59
- readonly content: Stream.Stream<never, Error.RequestError, Uint8Array>
60
- readonly source?: unknown
67
+ readonly content: Stream.Stream<never, FormDataError, Uint8Array>
61
68
  }
69
+
70
+ /**
71
+ * @since 1.0.0
72
+ * @category type ids
73
+ */
74
+ export const ErrorTypeId: unique symbol = internal.ErrorTypeId
75
+
76
+ /**
77
+ * @since 1.0.0
78
+ * @category type ids
79
+ */
80
+ export type ErrorTypeId = typeof ErrorTypeId
81
+
82
+ /**
83
+ * @since 1.0.0
84
+ * @category errors
85
+ */
86
+ export interface FormDataError extends Data.Case {
87
+ readonly [ErrorTypeId]: ErrorTypeId
88
+ readonly _tag: "FormDataError"
89
+ readonly reason: "FileTooLarge" | "FieldTooLarge" | "InternalError" | "Parse"
90
+ readonly error: unknown
91
+ }
92
+
93
+ /**
94
+ * @since 1.0.0
95
+ * @category errors
96
+ */
97
+ export const FormDataError: (
98
+ reason: FormDataError["reason"],
99
+ error: unknown
100
+ ) => FormDataError = internal.FormDataError
101
+
102
+ /**
103
+ * @since 1.0.0
104
+ * @category fiber refs
105
+ */
106
+ export const maxFieldSize: FiberRef.FiberRef<FileSystem.Size> = internal.maxFieldSize
107
+
108
+ /**
109
+ * @since 1.0.0
110
+ * @category fiber refs
111
+ */
112
+ export const withMaxFieldSize: {
113
+ (size: FileSystem.SizeInput): <R, E, A>(effect: Effect.Effect<R, E, A>) => Effect.Effect<R, E, A>
114
+ <R, E, A>(effect: Effect.Effect<R, E, A>, size: FileSystem.SizeInput): Effect.Effect<R, E, A>
115
+ } = internal.withMaxFieldSize
116
+
117
+ /**
118
+ * @since 1.0.0
119
+ * @category fiber refs
120
+ */
121
+ export const maxFileSize: FiberRef.FiberRef<Option.Option<FileSystem.Size>> = internal.maxFileSize
122
+
123
+ /**
124
+ * @since 1.0.0
125
+ * @category fiber refs
126
+ */
127
+ export const withMaxFileSize: {
128
+ (size: Option.Option<FileSystem.SizeInput>): <R, E, A>(effect: Effect.Effect<R, E, A>) => Effect.Effect<R, E, A>
129
+ <R, E, A>(effect: Effect.Effect<R, E, A>, size: Option.Option<FileSystem.SizeInput>): Effect.Effect<R, E, A>
130
+ } = internal.withMaxFileSize
131
+
132
+ /**
133
+ * @since 1.0.0
134
+ * @category fiber refs
135
+ */
136
+ export const fieldMimeTypes: FiberRef.FiberRef<Chunk.Chunk<string>> = internal.fieldMimeTypes
137
+
138
+ /**
139
+ * @since 1.0.0
140
+ * @category fiber refs
141
+ */
142
+ export const withFieldMimeTypes: {
143
+ (mimeTypes: ReadonlyArray<string>): <R, E, A>(effect: Effect.Effect<R, E, A>) => Effect.Effect<R, E, A>
144
+ <R, E, A>(effect: Effect.Effect<R, E, A>, mimeTypes: ReadonlyArray<string>): Effect.Effect<R, E, A>
145
+ } = internal.withFieldMimeTypes
146
+
147
+ /**
148
+ * @since 1.0.0
149
+ * @category conversions
150
+ */
151
+ export const toRecord: (formData: FormData) => Record<string, string | Array<globalThis.File>> = internal.toRecord
152
+
153
+ /**
154
+ * @since 1.0.0
155
+ * @category schema
156
+ */
157
+ export const filesSchema: Schema.Schema<ReadonlyArray<globalThis.File>, ReadonlyArray<globalThis.File>> =
158
+ internal.filesSchema
159
+
160
+ /**
161
+ * @since 1.0.0
162
+ * @category schema
163
+ */
164
+ export const schemaJson: <I, A>(
165
+ schema: Schema.Schema<I, A>
166
+ ) => {
167
+ (field: string): (formData: FormData) => Effect.Effect<never, FormDataError | ParseResult.ParseError, A>
168
+ (formData: FormData, field: string): Effect.Effect<never, FormDataError | ParseResult.ParseError, A>
169
+ } = internal.schemaJson
170
+
171
+ /**
172
+ * @since 1.0.0
173
+ * @category schema
174
+ */
175
+ export const schemaRecord: <I extends Readonly<Record<string, string | ReadonlyArray<globalThis.File>>>, A>(
176
+ schema: Schema.Schema<I, A>
177
+ ) => (formData: FormData) => Effect.Effect<never, ParseResult.ParseError, A> = internal.schemaRecord
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { dual } from "@effect/data/Function"
5
5
  import * as HashMap from "@effect/data/HashMap"
6
+ import type * as Option from "@effect/data/Option"
6
7
 
7
8
  /**
8
9
  * @since 1.0.0
@@ -41,7 +42,34 @@ export const fromInput: (input?: Input) => Headers = (input) => {
41
42
  * @since 1.0.0
42
43
  * @category combinators
43
44
  */
44
- export const set = dual<
45
+ export const has: {
46
+ (key: string): (self: Headers) => boolean
47
+ (self: Headers, key: string): boolean
48
+ } = dual<
49
+ (key: string) => (self: Headers) => boolean,
50
+ (self: Headers, key: string) => boolean
51
+ >(2, (self, key) => HashMap.has(self, key.toLowerCase()))
52
+
53
+ /**
54
+ * @since 1.0.0
55
+ * @category combinators
56
+ */
57
+ export const get: {
58
+ (key: string): (self: Headers) => Option.Option<string>
59
+ (self: Headers, key: string): Option.Option<string>
60
+ } = dual<
61
+ (key: string) => (self: Headers) => Option.Option<string>,
62
+ (self: Headers, key: string) => Option.Option<string>
63
+ >(2, (self, key) => HashMap.get(self, key.toLowerCase()))
64
+
65
+ /**
66
+ * @since 1.0.0
67
+ * @category combinators
68
+ */
69
+ export const set: {
70
+ (key: string, value: string): (self: Headers) => Headers
71
+ (self: Headers, key: string, value: string): Headers
72
+ } = dual<
45
73
  (key: string, value: string) => (self: Headers) => Headers,
46
74
  (self: Headers, key: string, value: string) => Headers
47
75
  >(3, (self, key, value) => HashMap.set(self, key.toLowerCase(), value))
@@ -50,7 +78,10 @@ export const set = dual<
50
78
  * @since 1.0.0
51
79
  * @category combinators
52
80
  */
53
- export const setAll = dual<
81
+ export const setAll: {
82
+ (headers: Input): (self: Headers) => Headers
83
+ (self: Headers, headers: Input): Headers
84
+ } = dual<
54
85
  (headers: Input) => (self: Headers) => Headers,
55
86
  (self: Headers, headers: Input) => Headers
56
87
  >(2, (self, headers) =>
@@ -63,7 +94,10 @@ export const setAll = dual<
63
94
  * @since 1.0.0
64
95
  * @category combinators
65
96
  */
66
- export const remove = dual<
97
+ export const remove: {
98
+ (key: string): (self: Headers) => Headers
99
+ (self: Headers, key: string): Headers
100
+ } = dual<
67
101
  (key: string) => (self: Headers) => Headers,
68
102
  (self: Headers, key: string) => Headers
69
103
  >(2, (self, key) => HashMap.remove(self, key.toLowerCase()))
@@ -1,8 +1,14 @@
1
1
  /**
2
2
  * @since 1.0.0
3
3
  */
4
+ import { dual } from "@effect/data/Function"
5
+ import * as Global from "@effect/data/Global"
6
+ import * as Option from "@effect/data/Option"
4
7
  import * as Effect from "@effect/io/Effect"
8
+ import * as FiberRef from "@effect/io/FiberRef"
9
+ import * as FileSystem from "@effect/platform/FileSystem"
5
10
  import type * as Headers from "@effect/platform/Http/Headers"
11
+ import type * as UrlParams from "@effect/platform/Http/UrlParams"
6
12
  import type * as ParseResult from "@effect/schema/ParseResult"
7
13
  import * as Schema from "@effect/schema/Schema"
8
14
  import type * as Stream from "@effect/stream/Stream"
@@ -28,9 +34,8 @@ export interface IncomingMessage<E> {
28
34
  readonly headers: Headers.Headers
29
35
  readonly json: Effect.Effect<never, E, unknown>
30
36
  readonly text: Effect.Effect<never, E, string>
37
+ readonly urlParams: Effect.Effect<never, E, UrlParams.UrlParams>
31
38
  readonly arrayBuffer: Effect.Effect<never, E, ArrayBuffer>
32
- readonly formData: Effect.Effect<never, E, FormData>
33
- // readonly formDataStream: Stream.Stream<never, Error.TransportError, FormData.Part>
34
39
  readonly stream: Stream.Stream<never, E, Uint8Array>
35
40
  }
36
41
 
@@ -38,8 +43,46 @@ export interface IncomingMessage<E> {
38
43
  * @since 1.0.0
39
44
  * @category schema
40
45
  */
41
- export const parseSchema = <I, A>(schema: Schema.Schema<I, A>) => {
46
+ export const schemaBodyJson = <I, A>(schema: Schema.Schema<I, A>) => {
42
47
  const parse = Schema.parse(schema)
43
48
  return <E>(self: IncomingMessage<E>): Effect.Effect<never, E | ParseResult.ParseError, A> =>
44
49
  Effect.flatMap(self.json, parse)
45
50
  }
51
+
52
+ /**
53
+ * @since 1.0.0
54
+ * @category schema
55
+ */
56
+ export const schemaBodyUrlParams = <I extends Readonly<Record<string, string>>, A>(schema: Schema.Schema<I, A>) => {
57
+ const parse = Schema.parse(schema)
58
+ return <E>(self: IncomingMessage<E>): Effect.Effect<never, E | ParseResult.ParseError, A> =>
59
+ Effect.flatMap(self.urlParams, (_) => parse(Object.fromEntries(_)))
60
+ }
61
+
62
+ /**
63
+ * @since 1.0.0
64
+ * @category schema
65
+ */
66
+ export const schemaHeaders = <I extends Readonly<Record<string, string>>, A>(schema: Schema.Schema<I, A>) => {
67
+ const parse = Schema.parse(schema)
68
+ return <E>(self: IncomingMessage<E>): Effect.Effect<never, ParseResult.ParseError, A> =>
69
+ parse(Object.fromEntries(self.headers))
70
+ }
71
+
72
+ /**
73
+ * @since 1.0.0
74
+ * @category fiber refs
75
+ */
76
+ export const maxBodySize: FiberRef.FiberRef<Option.Option<FileSystem.Size>> = Global.globalValue(
77
+ "@effect/platform/Http/ImcomingMessage/maxBodySize",
78
+ () => FiberRef.unsafeMake(Option.none<FileSystem.Size>())
79
+ )
80
+
81
+ /**
82
+ * @since 1.0.0
83
+ * @category fiber refs
84
+ */
85
+ export const withMaxBodySize = dual<
86
+ (size: Option.Option<FileSystem.SizeInput>) => <R, E, A>(effect: Effect.Effect<R, E, A>) => Effect.Effect<R, E, A>,
87
+ <R, E, A>(effect: Effect.Effect<R, E, A>, size: Option.Option<FileSystem.SizeInput>) => Effect.Effect<R, E, A>
88
+ >(2, (effect, size) => Effect.locally(effect, maxBodySize, Option.map(size, FileSystem.Size)))