@effect/platform 0.11.5 → 0.12.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.
- package/FileSystem.d.ts +43 -11
- package/FileSystem.d.ts.map +1 -1
- package/FileSystem.js +33 -3
- package/FileSystem.js.map +1 -1
- package/Http/App.d.ts +18 -0
- package/Http/App.d.ts.map +1 -0
- package/Http/App.js +6 -0
- package/Http/App.js.map +1 -0
- package/Http/Body.d.ts +37 -14
- package/Http/Body.d.ts.map +1 -1
- package/Http/Body.js +17 -5
- package/Http/Body.js.map +1 -1
- package/Http/Client.d.ts +2 -2
- package/Http/Client.d.ts.map +1 -1
- package/Http/Client.js +3 -3
- package/Http/Client.js.map +1 -1
- package/Http/ClientRequest.d.ts +44 -1
- package/Http/ClientRequest.d.ts.map +1 -1
- package/Http/ClientRequest.js +21 -3
- package/Http/ClientRequest.js.map +1 -1
- package/Http/ClientResponse.d.ts +13 -1
- package/Http/ClientResponse.d.ts.map +1 -1
- package/Http/ClientResponse.js +14 -2
- package/Http/ClientResponse.js.map +1 -1
- package/Http/FormData.d.ts +97 -4
- package/Http/FormData.d.ts.map +1 -1
- package/Http/FormData.js +77 -2
- package/Http/FormData.js.map +1 -1
- package/Http/Headers.d.ts +29 -3
- package/Http/Headers.d.ts.map +1 -1
- package/Http/Headers.js +13 -1
- package/Http/Headers.js.map +1 -1
- package/Http/IncomingMessage.d.ts +26 -5
- package/Http/IncomingMessage.d.ts.map +1 -1
- package/Http/IncomingMessage.js +38 -3
- package/Http/IncomingMessage.js.map +1 -1
- package/Http/Middleware.d.ts +56 -0
- package/Http/Middleware.d.ts.map +1 -0
- package/Http/Middleware.js +46 -0
- package/Http/Middleware.js.map +1 -0
- package/Http/Router.d.ts +221 -0
- package/Http/Router.d.ts.map +1 -0
- package/Http/Router.js +148 -0
- package/Http/Router.js.map +1 -0
- package/Http/Server.d.ts +85 -0
- package/Http/Server.d.ts.map +1 -0
- package/Http/Server.js +34 -0
- package/Http/Server.js.map +1 -0
- package/Http/ServerError.d.ts +96 -0
- package/Http/ServerError.d.ts.map +1 -0
- package/Http/ServerError.js +40 -0
- package/Http/ServerError.js.map +1 -0
- package/Http/ServerRequest.d.ts +82 -0
- package/Http/ServerRequest.d.ts.map +1 -0
- package/Http/ServerRequest.js +66 -0
- package/Http/ServerRequest.js.map +1 -0
- package/Http/ServerResponse.d.ts +168 -0
- package/Http/ServerResponse.d.ts.map +1 -0
- package/Http/ServerResponse.js +116 -0
- package/Http/ServerResponse.js.map +1 -0
- package/Http/UrlParams.d.ts +20 -5
- package/Http/UrlParams.d.ts.map +1 -1
- package/Http/UrlParams.js.map +1 -1
- package/HttpServer.d.ts +44 -0
- package/HttpServer.d.ts.map +1 -0
- package/HttpServer.js +29 -0
- package/HttpServer.js.map +1 -0
- package/internal/fileSystem.js +33 -12
- package/internal/fileSystem.js.map +1 -1
- package/internal/http/body.js +28 -28
- package/internal/http/body.js.map +1 -1
- package/internal/http/client.d.ts.map +1 -1
- package/internal/http/client.js +32 -26
- package/internal/http/client.js.map +1 -1
- package/internal/http/clientRequest.js +22 -6
- package/internal/http/clientRequest.js.map +1 -1
- package/internal/http/clientResponse.js +15 -12
- package/internal/http/clientResponse.js.map +1 -1
- package/internal/http/formData.d.ts +8 -0
- package/internal/http/formData.d.ts.map +1 -0
- package/internal/http/formData.js +88 -0
- package/internal/http/formData.js.map +1 -0
- package/internal/http/middleware.d.ts +2 -0
- package/internal/http/middleware.d.ts.map +1 -0
- package/internal/http/middleware.js +43 -0
- package/internal/http/middleware.js.map +1 -0
- package/internal/http/router.d.ts +2 -0
- package/internal/http/router.d.ts.map +1 -0
- package/internal/http/router.js +187 -0
- package/internal/http/router.js.map +1 -0
- package/internal/http/server.d.ts +2 -0
- package/internal/http/server.d.ts.map +1 -0
- package/internal/http/server.js +30 -0
- package/internal/http/server.js.map +1 -0
- package/internal/http/serverError.d.ts +2 -0
- package/internal/http/serverError.d.ts.map +1 -0
- package/internal/http/serverError.js +30 -0
- package/internal/http/serverError.js.map +1 -0
- package/internal/http/serverRequest.d.ts +2 -0
- package/internal/http/serverRequest.d.ts.map +1 -0
- package/internal/http/serverRequest.js +57 -0
- package/internal/http/serverRequest.js.map +1 -0
- package/internal/http/serverResponse.d.ts +2 -0
- package/internal/http/serverResponse.d.ts.map +1 -0
- package/internal/http/serverResponse.js +109 -0
- package/internal/http/serverResponse.js.map +1 -0
- package/mjs/FileSystem.mjs +26 -1
- package/mjs/FileSystem.mjs.map +1 -1
- package/mjs/Http/App.mjs +2 -0
- package/mjs/Http/App.mjs.map +1 -0
- package/mjs/Http/Body.mjs +12 -2
- package/mjs/Http/Body.mjs.map +1 -1
- package/mjs/Http/Client.mjs +1 -1
- package/mjs/Http/Client.mjs.map +1 -1
- package/mjs/Http/ClientRequest.mjs +16 -1
- package/mjs/Http/ClientRequest.mjs.map +1 -1
- package/mjs/Http/ClientResponse.mjs +11 -1
- package/mjs/Http/ClientResponse.mjs.map +1 -1
- package/mjs/Http/FormData.mjs +62 -1
- package/mjs/Http/FormData.mjs.map +1 -1
- package/mjs/Http/Headers.mjs +10 -0
- package/mjs/Http/Headers.mjs.map +1 -1
- package/mjs/Http/IncomingMessage.mjs +32 -1
- package/mjs/Http/IncomingMessage.mjs.map +1 -1
- package/mjs/Http/Middleware.mjs +32 -0
- package/mjs/Http/Middleware.mjs.map +1 -0
- package/mjs/Http/Router.mjs +117 -0
- package/mjs/Http/Router.mjs.map +1 -0
- package/mjs/Http/Server.mjs +22 -0
- package/mjs/Http/Server.mjs.map +1 -0
- package/mjs/Http/ServerError.mjs +27 -0
- package/mjs/Http/ServerError.mjs.map +1 -0
- package/mjs/Http/ServerRequest.mjs +48 -0
- package/mjs/Http/ServerRequest.mjs.map +1 -0
- package/mjs/Http/ServerResponse.mjs +90 -0
- package/mjs/Http/ServerResponse.mjs.map +1 -0
- package/mjs/Http/UrlParams.mjs.map +1 -1
- package/mjs/HttpServer.mjs +24 -0
- package/mjs/HttpServer.mjs.map +1 -0
- package/mjs/internal/fileSystem.mjs +27 -11
- package/mjs/internal/fileSystem.mjs.map +1 -1
- package/mjs/internal/http/body.mjs +23 -25
- package/mjs/internal/http/body.mjs.map +1 -1
- package/mjs/internal/http/client.mjs +30 -24
- package/mjs/internal/http/client.mjs.map +1 -1
- package/mjs/internal/http/clientRequest.mjs +16 -4
- package/mjs/internal/http/clientRequest.mjs.map +1 -1
- package/mjs/internal/http/clientResponse.mjs +15 -12
- package/mjs/internal/http/clientResponse.mjs.map +1 -1
- package/mjs/internal/http/formData.mjs +67 -0
- package/mjs/internal/http/formData.mjs.map +1 -0
- package/mjs/internal/http/middleware.mjs +29 -0
- package/mjs/internal/http/middleware.mjs.map +1 -0
- package/mjs/internal/http/router.mjs +155 -0
- package/mjs/internal/http/router.mjs.map +1 -0
- package/mjs/internal/http/server.mjs +17 -0
- package/mjs/internal/http/server.mjs.map +1 -0
- package/mjs/internal/http/serverError.mjs +17 -0
- package/mjs/internal/http/serverError.mjs.map +1 -0
- package/mjs/internal/http/serverRequest.mjs +41 -0
- package/mjs/internal/http/serverRequest.mjs.map +1 -0
- package/mjs/internal/http/serverResponse.mjs +82 -0
- package/mjs/internal/http/serverResponse.mjs.map +1 -0
- package/package.json +2 -1
- package/src/FileSystem.ts +52 -27
- package/src/Http/App.ts +19 -0
- package/src/Http/Body.ts +41 -14
- package/src/Http/Client.ts +6 -3
- package/src/Http/ClientRequest.ts +52 -2
- package/src/Http/ClientResponse.ts +13 -1
- package/src/Http/FormData.ts +121 -5
- package/src/Http/Headers.ts +37 -3
- package/src/Http/IncomingMessage.ts +46 -3
- package/src/Http/Middleware.ts +69 -0
- package/src/Http/Router.ts +342 -0
- package/src/Http/Server.ts +134 -0
- package/src/Http/ServerError.ts +111 -0
- package/src/Http/ServerRequest.ts +120 -0
- package/src/Http/ServerResponse.ts +202 -0
- package/src/Http/UrlParams.ts +20 -5
- package/src/HttpServer.ts +44 -0
- package/src/internal/fileSystem.ts +28 -7
- package/src/internal/http/body.ts +65 -39
- package/src/internal/http/client.ts +45 -36
- package/src/internal/http/clientRequest.ts +64 -4
- package/src/internal/http/clientResponse.ts +21 -13
- package/src/internal/http/formData.ts +140 -0
- package/src/internal/http/middleware.ts +72 -0
- package/src/internal/http/router.ts +298 -0
- package/src/internal/http/server.ts +80 -0
- package/src/internal/http/serverError.ts +26 -0
- package/src/internal/http/serverRequest.ts +71 -0
- package/src/internal/http/serverResponse.ts +255 -0
|
@@ -9,6 +9,7 @@ import type * as Body from "@effect/platform/Http/Body"
|
|
|
9
9
|
import type * as Client from "@effect/platform/Http/Client"
|
|
10
10
|
import type * as Error from "@effect/platform/Http/ClientError"
|
|
11
11
|
import type * as ClientRequest from "@effect/platform/Http/ClientRequest"
|
|
12
|
+
import type * as ClientResponse from "@effect/platform/Http/ClientResponse"
|
|
12
13
|
import * as Method from "@effect/platform/Http/Method"
|
|
13
14
|
import * as UrlParams from "@effect/platform/Http/UrlParams"
|
|
14
15
|
import * as internalBody from "@effect/platform/internal/http/body"
|
|
@@ -22,15 +23,33 @@ import * as Stream from "@effect/stream/Stream"
|
|
|
22
23
|
/** @internal */
|
|
23
24
|
export const tag = Context.Tag<Client.Client.Default>("@effect/platform/Http/Client")
|
|
24
25
|
|
|
26
|
+
const clientProto = {
|
|
27
|
+
pipe() {
|
|
28
|
+
return pipeArguments(this, arguments)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const setProto = <R, E, A>(
|
|
33
|
+
f: (request: ClientRequest.ClientRequest.NonEffectBody) => Effect.Effect<R, E, A>
|
|
34
|
+
) => {
|
|
35
|
+
Object.setPrototypeOf(f, clientProto)
|
|
36
|
+
return f as Client.Client<R, E, A>
|
|
37
|
+
}
|
|
38
|
+
|
|
25
39
|
/** @internal */
|
|
26
|
-
export const make =
|
|
27
|
-
f: (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
export const make = (
|
|
41
|
+
f: (
|
|
42
|
+
request: ClientRequest.ClientRequest.NonEffectBody
|
|
43
|
+
) => Effect.Effect<never, Error.HttpClientError, ClientResponse.ClientResponse>
|
|
44
|
+
): Client.Client.Default => {
|
|
45
|
+
function client(request: ClientRequest.ClientRequest) {
|
|
46
|
+
return Effect.flatMap(
|
|
47
|
+
internalRequest.resolveBody(request),
|
|
48
|
+
(request) => f(request)
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
return setProto(client)
|
|
52
|
+
}
|
|
34
53
|
|
|
35
54
|
/** @internal */
|
|
36
55
|
export const fetch = (
|
|
@@ -68,30 +87,20 @@ export const fetch = (
|
|
|
68
87
|
(_) => internalResponse.fromWeb(request, _)
|
|
69
88
|
)
|
|
70
89
|
if (Method.hasBody(request.method)) {
|
|
71
|
-
return request.body
|
|
72
|
-
Effect.flatMap(
|
|
73
|
-
Effect.mapError(request.body.body, (error) =>
|
|
74
|
-
internalError.requestError({
|
|
75
|
-
reason: "Encode",
|
|
76
|
-
request,
|
|
77
|
-
error
|
|
78
|
-
})),
|
|
79
|
-
(body) => send(body)
|
|
80
|
-
) :
|
|
81
|
-
send(convertBody(request.body))
|
|
90
|
+
return send(convertBody(request.body))
|
|
82
91
|
}
|
|
83
92
|
return send(undefined)
|
|
84
93
|
})
|
|
85
94
|
)
|
|
86
95
|
)
|
|
87
96
|
|
|
88
|
-
const convertBody = (body:
|
|
97
|
+
const convertBody = (body: Body.NonEffect): BodyInit | undefined => {
|
|
89
98
|
switch (body._tag) {
|
|
90
99
|
case "Empty":
|
|
91
100
|
return undefined
|
|
92
101
|
case "Raw":
|
|
93
102
|
return body.body as any
|
|
94
|
-
case "
|
|
103
|
+
case "Uint8Array":
|
|
95
104
|
return body.body
|
|
96
105
|
case "FormData":
|
|
97
106
|
return body.formData
|
|
@@ -105,7 +114,7 @@ export const fetchOk = (
|
|
|
105
114
|
): Client.Client.Default => filterStatusOk(fetch(options))
|
|
106
115
|
|
|
107
116
|
/** @internal */
|
|
108
|
-
export const
|
|
117
|
+
export const layer = Layer.succeed(tag, fetch())
|
|
109
118
|
|
|
110
119
|
/** @internal */
|
|
111
120
|
export const catchTag: {
|
|
@@ -127,7 +136,7 @@ export const catchTag: {
|
|
|
127
136
|
tag: K,
|
|
128
137
|
f: (e: Extract<E, { _tag: K }>) => Effect.Effect<R1, E1, A1>
|
|
129
138
|
): Client.Client<R1 | R, E1 | Exclude<E, { _tag: K }>, A1 | A> =>
|
|
130
|
-
|
|
139
|
+
setProto((request) => Effect.catchTag(self(request), tag, f))
|
|
131
140
|
)
|
|
132
141
|
|
|
133
142
|
/** @internal */
|
|
@@ -237,7 +246,7 @@ export const catchTags: {
|
|
|
237
246
|
) => Effect.Effect<any, any, infer A> ? A
|
|
238
247
|
: never
|
|
239
248
|
}[keyof Cases]
|
|
240
|
-
> =>
|
|
249
|
+
> => setProto((request) => Effect.catchTags(self(request), cases))
|
|
241
250
|
)
|
|
242
251
|
|
|
243
252
|
/** @internal */
|
|
@@ -254,7 +263,7 @@ export const catchAll: {
|
|
|
254
263
|
<R, E, A, R2, E2, A2>(
|
|
255
264
|
self: Client.Client<R, E, A>,
|
|
256
265
|
f: (e: E) => Effect.Effect<R2, E2, A2>
|
|
257
|
-
): Client.Client<R | R2, E2, A2 | A> =>
|
|
266
|
+
): Client.Client<R | R2, E2, A2 | A> => setProto((request) => Effect.catchAll(self(request), f))
|
|
258
267
|
)
|
|
259
268
|
|
|
260
269
|
/** @internal */
|
|
@@ -267,7 +276,7 @@ export const filterOrElse = dual<
|
|
|
267
276
|
f: Predicate.Predicate<A>,
|
|
268
277
|
orElse: (a: A) => Effect.Effect<R2, E2, B>
|
|
269
278
|
) => Client.Client<R2 | R, E2 | E, A | B>
|
|
270
|
-
>(3, (self, f, orElse) =>
|
|
279
|
+
>(3, (self, f, orElse) => setProto((request) => Effect.filterOrElse(self(request), f, orElse)))
|
|
271
280
|
|
|
272
281
|
/** @internal */
|
|
273
282
|
export const filterOrFail = dual<
|
|
@@ -279,7 +288,7 @@ export const filterOrFail = dual<
|
|
|
279
288
|
f: Predicate.Predicate<A>,
|
|
280
289
|
orFailWith: (a: A) => E2
|
|
281
290
|
) => Client.Client<R, E2 | E, A>
|
|
282
|
-
>(3, (self, f, orFailWith) =>
|
|
291
|
+
>(3, (self, f, orFailWith) => setProto((request) => Effect.filterOrFail(self(request), f, orFailWith)))
|
|
283
292
|
|
|
284
293
|
/** @internal */
|
|
285
294
|
export const filterStatus = dual<
|
|
@@ -293,7 +302,7 @@ export const filterStatus = dual<
|
|
|
293
302
|
>(
|
|
294
303
|
2,
|
|
295
304
|
(self, f) =>
|
|
296
|
-
|
|
305
|
+
setProto((request) =>
|
|
297
306
|
Effect.filterOrFail(
|
|
298
307
|
self(request),
|
|
299
308
|
(response) => f(response.status),
|
|
@@ -322,7 +331,7 @@ export const map = dual<
|
|
|
322
331
|
self: Client.Client<R, E, A>,
|
|
323
332
|
f: (a: A) => B
|
|
324
333
|
) => Client.Client<R, E, B>
|
|
325
|
-
>(2, (self, f) =>
|
|
334
|
+
>(2, (self, f) => setProto((request) => Effect.map(self(request), f)))
|
|
326
335
|
|
|
327
336
|
/** @internal */
|
|
328
337
|
export const mapEffect = dual<
|
|
@@ -333,7 +342,7 @@ export const mapEffect = dual<
|
|
|
333
342
|
self: Client.Client<R, E, A>,
|
|
334
343
|
f: (a: A) => Effect.Effect<R2, E2, B>
|
|
335
344
|
) => Client.Client<R | R2, E | E2, B>
|
|
336
|
-
>(2, (self, f) =>
|
|
345
|
+
>(2, (self, f) => setProto((request) => Effect.flatMap(self(request), f)))
|
|
337
346
|
|
|
338
347
|
/** @internal */
|
|
339
348
|
export const mapRequest = dual<
|
|
@@ -344,7 +353,7 @@ export const mapRequest = dual<
|
|
|
344
353
|
self: Client.Client<R, E, A>,
|
|
345
354
|
f: (a: ClientRequest.ClientRequest) => ClientRequest.ClientRequest
|
|
346
355
|
) => Client.Client<R, E, A>
|
|
347
|
-
>(2, (self, f) =>
|
|
356
|
+
>(2, (self, f) => setProto((request) => self(f(request))))
|
|
348
357
|
|
|
349
358
|
/** @internal */
|
|
350
359
|
export const mapRequestEffect = dual<
|
|
@@ -355,7 +364,7 @@ export const mapRequestEffect = dual<
|
|
|
355
364
|
self: Client.Client<R, E, A>,
|
|
356
365
|
f: (a: ClientRequest.ClientRequest) => Effect.Effect<R2, E2, ClientRequest.ClientRequest>
|
|
357
366
|
) => Client.Client<R | R2, E | E2, A>
|
|
358
|
-
>(2, (self, f) =>
|
|
367
|
+
>(2, (self, f) => setProto((request) => Effect.flatMap(f(request), self)))
|
|
359
368
|
|
|
360
369
|
/** @internal */
|
|
361
370
|
export const retry: {
|
|
@@ -371,7 +380,7 @@ export const retry: {
|
|
|
371
380
|
<R, E extends E0, E0, A, R1, B>(
|
|
372
381
|
self: Client.Client<R, E, A>,
|
|
373
382
|
policy: Schedule.Schedule<R1, E0, B>
|
|
374
|
-
): Client.Client<R | R1, E, A> =>
|
|
383
|
+
): Client.Client<R | R1, E, A> => setProto((request) => Effect.retry(self(request), policy))
|
|
375
384
|
)
|
|
376
385
|
|
|
377
386
|
/** @internal */
|
|
@@ -405,7 +414,7 @@ export const schemaFunction = dual<
|
|
|
405
414
|
(body) =>
|
|
406
415
|
self(internalRequest.setBody(
|
|
407
416
|
request,
|
|
408
|
-
internalBody.
|
|
417
|
+
internalBody.uint8Array(body, "application/json")
|
|
409
418
|
))
|
|
410
419
|
)
|
|
411
420
|
})
|
|
@@ -419,7 +428,7 @@ export const tap = dual<
|
|
|
419
428
|
self: Client.Client<R, E, A>,
|
|
420
429
|
f: (a: A) => Effect.Effect<R2, E2, _>
|
|
421
430
|
) => Client.Client<R | R2, E | E2, A>
|
|
422
|
-
>(2, (self, f) =>
|
|
431
|
+
>(2, (self, f) => setProto((request) => Effect.tap(self(request), f)))
|
|
423
432
|
|
|
424
433
|
/** @internal */
|
|
425
434
|
export const tapRequest = dual<
|
|
@@ -430,4 +439,4 @@ export const tapRequest = dual<
|
|
|
430
439
|
self: Client.Client<R, E, A>,
|
|
431
440
|
f: (a: ClientRequest.ClientRequest) => Effect.Effect<R2, E2, _>
|
|
432
441
|
) => Client.Client<R | R2, E | E2, A>
|
|
433
|
-
>(2, (self, f) =>
|
|
442
|
+
>(2, (self, f) => setProto((request) => Effect.zipRight(f(request), self(request))))
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { dual } from "@effect/data/Function"
|
|
2
2
|
import { pipeArguments } from "@effect/data/Pipeable"
|
|
3
|
+
import * as Effect from "@effect/io/Effect"
|
|
4
|
+
import type * as PlatformError from "@effect/platform/Error"
|
|
5
|
+
import type * as FileSystem from "@effect/platform/FileSystem"
|
|
3
6
|
import type * as Body from "@effect/platform/Http/Body"
|
|
4
7
|
import type * as Error from "@effect/platform/Http/ClientError"
|
|
5
8
|
import type * as ClientRequest from "@effect/platform/Http/ClientRequest"
|
|
@@ -7,6 +10,7 @@ import * as Headers from "@effect/platform/Http/Headers"
|
|
|
7
10
|
import type { Method } from "@effect/platform/Http/Method"
|
|
8
11
|
import * as UrlParams from "@effect/platform/Http/UrlParams"
|
|
9
12
|
import * as internalBody from "@effect/platform/internal/http/body"
|
|
13
|
+
import * as internalError from "@effect/platform/internal/http/clientError"
|
|
10
14
|
import type * as Schema from "@effect/schema/Schema"
|
|
11
15
|
import type * as Stream from "@effect/stream/Stream"
|
|
12
16
|
|
|
@@ -14,14 +18,16 @@ import type * as Stream from "@effect/stream/Stream"
|
|
|
14
18
|
export const TypeId: ClientRequest.TypeId = Symbol.for("@effect/platform/Http/ClientRequest") as ClientRequest.TypeId
|
|
15
19
|
|
|
16
20
|
class ClientRequestImpl implements ClientRequest.ClientRequest {
|
|
17
|
-
readonly [TypeId]: ClientRequest.TypeId
|
|
21
|
+
readonly [TypeId]: ClientRequest.TypeId
|
|
18
22
|
constructor(
|
|
19
23
|
readonly method: Method,
|
|
20
24
|
readonly url: string,
|
|
21
25
|
readonly urlParams: UrlParams.UrlParams,
|
|
22
26
|
readonly headers: Headers.Headers,
|
|
23
27
|
readonly body: Body.Body
|
|
24
|
-
) {
|
|
28
|
+
) {
|
|
29
|
+
this[TypeId] = TypeId
|
|
30
|
+
}
|
|
25
31
|
pipe() {
|
|
26
32
|
return pipeArguments(this, arguments)
|
|
27
33
|
}
|
|
@@ -293,12 +299,26 @@ export const setBody = dual<
|
|
|
293
299
|
})
|
|
294
300
|
|
|
295
301
|
/** @internal */
|
|
296
|
-
export const
|
|
302
|
+
export const uint8ArrayBody = dual<
|
|
297
303
|
(body: Uint8Array, contentType?: string) => (self: ClientRequest.ClientRequest) => ClientRequest.ClientRequest,
|
|
298
304
|
(self: ClientRequest.ClientRequest, body: Uint8Array, contentType?: string) => ClientRequest.ClientRequest
|
|
299
305
|
>(
|
|
300
306
|
(args) => isClientRequest(args[0]),
|
|
301
|
-
(self, body, contentType = "application/octet-stream") => setBody(self, internalBody.
|
|
307
|
+
(self, body, contentType = "application/octet-stream") => setBody(self, internalBody.uint8Array(body, contentType))
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
/** @internal */
|
|
311
|
+
export const effectBody = dual<
|
|
312
|
+
(
|
|
313
|
+
body: Effect.Effect<never, unknown, Body.NonEffect>
|
|
314
|
+
) => (self: ClientRequest.ClientRequest) => ClientRequest.ClientRequest,
|
|
315
|
+
(
|
|
316
|
+
self: ClientRequest.ClientRequest,
|
|
317
|
+
body: Effect.Effect<never, unknown, Body.NonEffect>
|
|
318
|
+
) => ClientRequest.ClientRequest
|
|
319
|
+
>(
|
|
320
|
+
2,
|
|
321
|
+
(self, body) => setBody(self, internalBody.effect(body))
|
|
302
322
|
)
|
|
303
323
|
|
|
304
324
|
/** @internal */
|
|
@@ -316,6 +336,30 @@ export const jsonBody = dual<
|
|
|
316
336
|
(self: ClientRequest.ClientRequest, body: unknown) => ClientRequest.ClientRequest
|
|
317
337
|
>(2, (self, body) => setBody(self, internalBody.json(body)))
|
|
318
338
|
|
|
339
|
+
/** @internal */
|
|
340
|
+
export const unsafeJsonBody = dual<
|
|
341
|
+
(body: unknown) => (self: ClientRequest.ClientRequest) => ClientRequest.ClientRequest,
|
|
342
|
+
(self: ClientRequest.ClientRequest, body: unknown) => ClientRequest.ClientRequest
|
|
343
|
+
>(2, (self, body) => setBody(self, internalBody.unsafeJson(body)))
|
|
344
|
+
|
|
345
|
+
/** @internal */
|
|
346
|
+
export const fileBody = dual<
|
|
347
|
+
(
|
|
348
|
+
path: string,
|
|
349
|
+
options?: FileSystem.StreamOptions & { readonly contentType?: string }
|
|
350
|
+
) => (
|
|
351
|
+
self: ClientRequest.ClientRequest
|
|
352
|
+
) => Effect.Effect<FileSystem.FileSystem, PlatformError.PlatformError, ClientRequest.ClientRequest>,
|
|
353
|
+
(
|
|
354
|
+
self: ClientRequest.ClientRequest,
|
|
355
|
+
path: string,
|
|
356
|
+
options?: FileSystem.StreamOptions & { readonly contentType?: string }
|
|
357
|
+
) => Effect.Effect<FileSystem.FileSystem, PlatformError.PlatformError, ClientRequest.ClientRequest>
|
|
358
|
+
>(
|
|
359
|
+
(args) => isClientRequest(args[0]),
|
|
360
|
+
(self, path, options) => Effect.map(internalBody.file(path, options), (body) => setBody(self, body))
|
|
361
|
+
)
|
|
362
|
+
|
|
319
363
|
/** @internal */
|
|
320
364
|
export const schemaBody = <I, A>(schema: Schema.Schema<I, A>): {
|
|
321
365
|
(body: A): (self: ClientRequest.ClientRequest) => ClientRequest.ClientRequest
|
|
@@ -369,3 +413,19 @@ export const streamBody = dual<
|
|
|
369
413
|
(self, body, { contentLength, contentType = "application/octet-stream" } = {}) =>
|
|
370
414
|
setBody(self, internalBody.stream(body, contentType, contentLength))
|
|
371
415
|
)
|
|
416
|
+
|
|
417
|
+
/** @internal */
|
|
418
|
+
export const resolveBody = (
|
|
419
|
+
self: ClientRequest.ClientRequest
|
|
420
|
+
): Effect.Effect<never, Error.RequestError, ClientRequest.ClientRequest.NonEffectBody> =>
|
|
421
|
+
self.body._tag === "Effect"
|
|
422
|
+
? Effect.map(
|
|
423
|
+
Effect.mapError(self.body.effect, (error) =>
|
|
424
|
+
internalError.requestError({
|
|
425
|
+
reason: "Encode",
|
|
426
|
+
request: self,
|
|
427
|
+
error
|
|
428
|
+
})),
|
|
429
|
+
(body) => setBody(self, body) as ClientRequest.ClientRequest.NonEffectBody
|
|
430
|
+
)
|
|
431
|
+
: Effect.succeed(self as ClientRequest.ClientRequest.NonEffectBody)
|
|
@@ -2,9 +2,9 @@ import * as Effect from "@effect/io/Effect"
|
|
|
2
2
|
import type * as Error from "@effect/platform/Http/ClientError"
|
|
3
3
|
import type * as ClientRequest from "@effect/platform/Http/ClientRequest"
|
|
4
4
|
import type * as ClientResponse from "@effect/platform/Http/ClientResponse"
|
|
5
|
-
import type * as FormData from "@effect/platform/Http/FormData"
|
|
6
5
|
import * as Headers from "@effect/platform/Http/Headers"
|
|
7
6
|
import * as IncomingMessage from "@effect/platform/Http/IncomingMessage"
|
|
7
|
+
import * as UrlParams from "@effect/platform/Http/UrlParams"
|
|
8
8
|
import * as internalError from "@effect/platform/internal/http/clientError"
|
|
9
9
|
import * as Stream from "@effect/stream/Stream"
|
|
10
10
|
|
|
@@ -18,13 +18,16 @@ export const fromWeb = (
|
|
|
18
18
|
): ClientResponse.ClientResponse => new ClientResponseImpl(request, source)
|
|
19
19
|
|
|
20
20
|
class ClientResponseImpl implements ClientResponse.ClientResponse {
|
|
21
|
-
readonly [IncomingMessage.TypeId]: IncomingMessage.TypeId
|
|
22
|
-
readonly [TypeId]: ClientResponse.TypeId
|
|
21
|
+
readonly [IncomingMessage.TypeId]: IncomingMessage.TypeId
|
|
22
|
+
readonly [TypeId]: ClientResponse.TypeId
|
|
23
23
|
|
|
24
24
|
constructor(
|
|
25
25
|
private readonly request: ClientRequest.ClientRequest,
|
|
26
26
|
private readonly source: globalThis.Response
|
|
27
|
-
) {
|
|
27
|
+
) {
|
|
28
|
+
this[IncomingMessage.TypeId] = IncomingMessage.TypeId
|
|
29
|
+
this[TypeId] = TypeId
|
|
30
|
+
}
|
|
28
31
|
|
|
29
32
|
get status(): number {
|
|
30
33
|
return this.source.status
|
|
@@ -77,6 +80,20 @@ class ClientResponseImpl implements ClientResponse.ClientResponse {
|
|
|
77
80
|
})
|
|
78
81
|
}
|
|
79
82
|
|
|
83
|
+
get urlParams(): Effect.Effect<never, Error.ResponseError, UrlParams.UrlParams> {
|
|
84
|
+
return Effect.flatMap(this.text, (_) =>
|
|
85
|
+
Effect.try({
|
|
86
|
+
try: () => UrlParams.fromInput(new URLSearchParams(_)),
|
|
87
|
+
catch: (_) =>
|
|
88
|
+
internalError.responseError({
|
|
89
|
+
request: this.request,
|
|
90
|
+
response: this,
|
|
91
|
+
reason: "Decode",
|
|
92
|
+
error: _
|
|
93
|
+
})
|
|
94
|
+
}))
|
|
95
|
+
}
|
|
96
|
+
|
|
80
97
|
get formData(): Effect.Effect<never, Error.ResponseError, FormData> {
|
|
81
98
|
return Effect.tryPromise({
|
|
82
99
|
try: () => this.source.formData(),
|
|
@@ -90,15 +107,6 @@ class ClientResponseImpl implements ClientResponse.ClientResponse {
|
|
|
90
107
|
})
|
|
91
108
|
}
|
|
92
109
|
|
|
93
|
-
get formDataStream(): Stream.Stream<never, Error.ResponseError, FormData.Part> {
|
|
94
|
-
return Stream.fail(internalError.responseError({
|
|
95
|
-
request: this.request,
|
|
96
|
-
response: this,
|
|
97
|
-
reason: "Decode",
|
|
98
|
-
error: "not implemented"
|
|
99
|
-
}))
|
|
100
|
-
}
|
|
101
|
-
|
|
102
110
|
get arrayBuffer(): Effect.Effect<never, Error.ResponseError, ArrayBuffer> {
|
|
103
111
|
return Effect.tryPromise({
|
|
104
112
|
try: () => this.source.arrayBuffer(),
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import * as Chunk from "@effect/data/Chunk"
|
|
2
|
+
import * as Data from "@effect/data/Data"
|
|
3
|
+
import { dual, pipe } from "@effect/data/Function"
|
|
4
|
+
import { globalValue } from "@effect/data/Global"
|
|
5
|
+
import * as Option from "@effect/data/Option"
|
|
6
|
+
import * as Predicate from "@effect/data/Predicate"
|
|
7
|
+
import * as ReadonlyArray from "@effect/data/ReadonlyArray"
|
|
8
|
+
import * as Effect from "@effect/io/Effect"
|
|
9
|
+
import * as FiberRef from "@effect/io/FiberRef"
|
|
10
|
+
import * as FileSystem from "@effect/platform/FileSystem"
|
|
11
|
+
import type * as FormData from "@effect/platform/Http/FormData"
|
|
12
|
+
import type * as ParseResult from "@effect/schema/ParseResult"
|
|
13
|
+
import * as Schema from "@effect/schema/Schema"
|
|
14
|
+
|
|
15
|
+
/** @internal */
|
|
16
|
+
export const TypeId: FormData.TypeId = Symbol.for("@effect/platform/Http/FormData") as FormData.TypeId
|
|
17
|
+
|
|
18
|
+
/** @internal */
|
|
19
|
+
export const ErrorTypeId: FormData.ErrorTypeId = Symbol.for(
|
|
20
|
+
"@effect/platform/Http/FormData/FormDataError"
|
|
21
|
+
) as FormData.ErrorTypeId
|
|
22
|
+
|
|
23
|
+
/** @internal */
|
|
24
|
+
export const FormDataError = (reason: FormData.FormDataError["reason"], error: unknown): FormData.FormDataError =>
|
|
25
|
+
Data.struct({
|
|
26
|
+
[ErrorTypeId]: ErrorTypeId,
|
|
27
|
+
_tag: "FormDataError",
|
|
28
|
+
reason,
|
|
29
|
+
error
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
/** @internal */
|
|
33
|
+
export const maxFieldSize: FiberRef.FiberRef<FileSystem.Size> = globalValue(
|
|
34
|
+
"@effect/platform/Http/FormData/maxFieldSize",
|
|
35
|
+
() => FiberRef.unsafeMake(FileSystem.Size(1024 * 1024))
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
/** @internal */
|
|
39
|
+
export const withMaxFieldSize = dual<
|
|
40
|
+
(size: FileSystem.SizeInput) => <R, E, A>(effect: Effect.Effect<R, E, A>) => Effect.Effect<R, E, A>,
|
|
41
|
+
<R, E, A>(effect: Effect.Effect<R, E, A>, size: FileSystem.SizeInput) => Effect.Effect<R, E, A>
|
|
42
|
+
>(2, (effect, size) => Effect.locally(effect, maxFieldSize, FileSystem.Size(size)))
|
|
43
|
+
|
|
44
|
+
/** @internal */
|
|
45
|
+
export const maxFileSize: FiberRef.FiberRef<Option.Option<FileSystem.Size>> = globalValue(
|
|
46
|
+
"@effect/platform/Http/FormData/maxFileSize",
|
|
47
|
+
() => FiberRef.unsafeMake(Option.none<FileSystem.Size>())
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
/** @internal */
|
|
51
|
+
export const withMaxFileSize = dual<
|
|
52
|
+
(size: Option.Option<FileSystem.SizeInput>) => <R, E, A>(effect: Effect.Effect<R, E, A>) => Effect.Effect<R, E, A>,
|
|
53
|
+
<R, E, A>(effect: Effect.Effect<R, E, A>, size: Option.Option<FileSystem.SizeInput>) => Effect.Effect<R, E, A>
|
|
54
|
+
>(2, (effect, size) => Effect.locally(effect, maxFileSize, Option.map(size, FileSystem.Size)))
|
|
55
|
+
|
|
56
|
+
/** @internal */
|
|
57
|
+
export const fieldMimeTypes: FiberRef.FiberRef<Chunk.Chunk<string>> = globalValue(
|
|
58
|
+
"@effect/platform/Http/FormData/fieldMimeTypes",
|
|
59
|
+
() => FiberRef.unsafeMake(Chunk.make("application/json"))
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @since 1.0.0
|
|
64
|
+
* @category fiber refs
|
|
65
|
+
*/
|
|
66
|
+
export const withFieldMimeTypes = dual<
|
|
67
|
+
(mimeTypes: ReadonlyArray<string>) => <R, E, A>(effect: Effect.Effect<R, E, A>) => Effect.Effect<R, E, A>,
|
|
68
|
+
<R, E, A>(effect: Effect.Effect<R, E, A>, mimeTypes: ReadonlyArray<string>) => Effect.Effect<R, E, A>
|
|
69
|
+
>(2, (effect, mimeTypes) => Effect.locally(effect, fieldMimeTypes, Chunk.fromIterable(mimeTypes)))
|
|
70
|
+
|
|
71
|
+
/** @internal */
|
|
72
|
+
export const toRecord = (formData: globalThis.FormData): Record<string, Array<globalThis.File> | string> =>
|
|
73
|
+
ReadonlyArray.reduce(
|
|
74
|
+
formData.entries(),
|
|
75
|
+
{} as Record<string, Array<globalThis.File> | string>,
|
|
76
|
+
(acc, [key, value]) => {
|
|
77
|
+
if (Predicate.isString(value)) {
|
|
78
|
+
acc[key] = value
|
|
79
|
+
} else {
|
|
80
|
+
const existing = acc[key]
|
|
81
|
+
if (Array.isArray(existing)) {
|
|
82
|
+
existing.push(value)
|
|
83
|
+
} else {
|
|
84
|
+
acc[key] = [value]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return acc
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
/** @internal */
|
|
91
|
+
export const filesSchema: Schema.Schema<ReadonlyArray<File>, ReadonlyArray<File>> = Schema.array(
|
|
92
|
+
pipe(
|
|
93
|
+
Schema.instanceOf(Blob),
|
|
94
|
+
Schema.filter(
|
|
95
|
+
(blob): blob is File => "name" in blob
|
|
96
|
+
)
|
|
97
|
+
) as any as Schema.Schema<File, File>
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
/** @internal */
|
|
101
|
+
export const schemaRecord = <I extends Readonly<Record<string, string | ReadonlyArray<globalThis.File>>>, A>(
|
|
102
|
+
schema: Schema.Schema<I, A>
|
|
103
|
+
) => {
|
|
104
|
+
const parse = Schema.parse(schema)
|
|
105
|
+
return (formData: globalThis.FormData) => parse(toRecord(formData))
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** @internal */
|
|
109
|
+
export const schemaJson = <I, A>(schema: Schema.Schema<I, A>): {
|
|
110
|
+
(
|
|
111
|
+
field: string
|
|
112
|
+
): (formData: globalThis.FormData) => Effect.Effect<never, FormData.FormDataError | ParseResult.ParseError, A>
|
|
113
|
+
(
|
|
114
|
+
formData: globalThis.FormData,
|
|
115
|
+
field: string
|
|
116
|
+
): Effect.Effect<never, FormData.FormDataError | ParseResult.ParseError, A>
|
|
117
|
+
} => {
|
|
118
|
+
const parse = Schema.parse(schema)
|
|
119
|
+
return dual<
|
|
120
|
+
(
|
|
121
|
+
field: string
|
|
122
|
+
) => (formData: globalThis.FormData) => Effect.Effect<never, FormData.FormDataError | ParseResult.ParseError, A>,
|
|
123
|
+
(
|
|
124
|
+
formData: globalThis.FormData,
|
|
125
|
+
field: string
|
|
126
|
+
) => Effect.Effect<never, FormData.FormDataError | ParseResult.ParseError, A>
|
|
127
|
+
>(2, (formData, field) =>
|
|
128
|
+
pipe(
|
|
129
|
+
Effect.succeed(formData.get(field)),
|
|
130
|
+
Effect.filterOrFail(
|
|
131
|
+
(field) => Predicate.isString(field),
|
|
132
|
+
() => FormDataError("Parse", `schemaJson: field was not a string`)
|
|
133
|
+
),
|
|
134
|
+
Effect.tryMap({
|
|
135
|
+
try: (field) => JSON.parse(field as string),
|
|
136
|
+
catch: (error) => FormDataError("Parse", `schemaJson: field was not valid json: ${error}`)
|
|
137
|
+
}),
|
|
138
|
+
Effect.flatMap(parse)
|
|
139
|
+
))
|
|
140
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { dual } from "@effect/data/Function"
|
|
2
|
+
import * as Effect from "@effect/io/Effect"
|
|
3
|
+
import type * as App from "@effect/platform/Http/App"
|
|
4
|
+
import * as Headers from "@effect/platform/Http/Headers"
|
|
5
|
+
import type * as Middleware from "@effect/platform/Http/Middleware"
|
|
6
|
+
import * as ServerRequest from "@effect/platform/Http/ServerRequest"
|
|
7
|
+
|
|
8
|
+
/** @internal */
|
|
9
|
+
export const make = <M extends Middleware.Middleware>(middleware: M): M => middleware
|
|
10
|
+
|
|
11
|
+
/** @internal */
|
|
12
|
+
export const logger = make((httpApp) =>
|
|
13
|
+
Effect.withLogSpan(
|
|
14
|
+
Effect.onExit(
|
|
15
|
+
httpApp,
|
|
16
|
+
(exit) =>
|
|
17
|
+
Effect.flatMap(
|
|
18
|
+
ServerRequest.ServerRequest,
|
|
19
|
+
(request) =>
|
|
20
|
+
Effect.annotateLogs(Effect.log("", exit._tag === "Failure" ? exit.cause : undefined), {
|
|
21
|
+
"http.method": request.method,
|
|
22
|
+
"http.url": request.url,
|
|
23
|
+
"http.status": exit._tag === "Success" ? exit.value.status : 500
|
|
24
|
+
})
|
|
25
|
+
)
|
|
26
|
+
),
|
|
27
|
+
"http.span"
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
/** @internal */
|
|
32
|
+
export const tracer = make((httpApp) =>
|
|
33
|
+
Effect.flatMap(
|
|
34
|
+
ServerRequest.ServerRequest,
|
|
35
|
+
(request) =>
|
|
36
|
+
Effect.withSpan(
|
|
37
|
+
Effect.tap(
|
|
38
|
+
httpApp,
|
|
39
|
+
(response) => Effect.annotateCurrentSpan("http.status", response.status)
|
|
40
|
+
),
|
|
41
|
+
`http ${request.method}`,
|
|
42
|
+
{ attributes: { "http.method": request.method, "http.url": request.url } }
|
|
43
|
+
)
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
/** @internal */
|
|
48
|
+
export const xForwardedHeaders = make((httpApp) =>
|
|
49
|
+
Effect.flatMap(ServerRequest.ServerRequest, (request) => {
|
|
50
|
+
const forwardedHost = Headers.get(request.headers, "x-forwarded-host")
|
|
51
|
+
return forwardedHost._tag === "Some"
|
|
52
|
+
? Effect.updateService(httpApp, ServerRequest.ServerRequest, (_) =>
|
|
53
|
+
_.replaceHeaders(Headers.set(request.headers, "host", forwardedHost.value)))
|
|
54
|
+
: httpApp
|
|
55
|
+
})
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
/** @internal */
|
|
59
|
+
export const compose = dual<
|
|
60
|
+
<B extends App.Default<any, any>, C extends App.Default<any, any>>(
|
|
61
|
+
that: (b: B) => C
|
|
62
|
+
) => <A extends App.Default<any, any>>(
|
|
63
|
+
self: (a: A) => B
|
|
64
|
+
) => (a: A) => C,
|
|
65
|
+
<A extends App.Default<any, any>, B extends App.Default<any, any>, C extends App.Default<any, any>>(
|
|
66
|
+
self: (a: A) => B,
|
|
67
|
+
that: (b: B) => C
|
|
68
|
+
) => (a: A) => C
|
|
69
|
+
>(2, (self, that) => (inApp) => that(self(inApp)))
|
|
70
|
+
|
|
71
|
+
/** @internal */
|
|
72
|
+
export const loggerTracer = compose(tracer, logger)
|