@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.
- package/Command.d.ts +3 -2
- package/Command.d.ts.map +1 -1
- package/Command.js.map +1 -1
- package/FileSystem.d.ts +16 -9
- package/FileSystem.d.ts.map +1 -1
- 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 +8 -2
- package/Http/Client.d.ts.map +1 -1
- package/Http/Client.js +10 -4
- 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/command.js +9 -2
- package/internal/command.js.map +1 -1
- package/internal/fileSystem.js +15 -11
- 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 +41 -27
- 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/Command.mjs.map +1 -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 +6 -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/command.mjs +9 -2
- package/mjs/internal/command.mjs.map +1 -1
- package/mjs/internal/fileSystem.mjs +15 -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 +37 -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/Command.ts +3 -2
- package/src/FileSystem.ts +20 -25
- package/src/Http/App.ts +19 -0
- package/src/Http/Body.ts +41 -14
- package/src/Http/Client.ts +13 -2
- 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/command.ts +9 -2
- package/src/internal/fileSystem.ts +10 -7
- package/src/internal/http/body.ts +65 -39
- package/src/internal/http/client.ts +96 -76
- 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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as Context from "@effect/data/Context"
|
|
2
2
|
import { dual } from "@effect/data/Function"
|
|
3
|
+
import { pipeArguments } from "@effect/data/Pipeable"
|
|
3
4
|
import type * as Predicate from "@effect/data/Predicate"
|
|
4
5
|
import * as Effect from "@effect/io/Effect"
|
|
5
6
|
import * as Layer from "@effect/io/Layer"
|
|
@@ -8,6 +9,7 @@ import type * as Body from "@effect/platform/Http/Body"
|
|
|
8
9
|
import type * as Client from "@effect/platform/Http/Client"
|
|
9
10
|
import type * as Error from "@effect/platform/Http/ClientError"
|
|
10
11
|
import type * as ClientRequest from "@effect/platform/Http/ClientRequest"
|
|
12
|
+
import type * as ClientResponse from "@effect/platform/Http/ClientResponse"
|
|
11
13
|
import * as Method from "@effect/platform/Http/Method"
|
|
12
14
|
import * as UrlParams from "@effect/platform/Http/UrlParams"
|
|
13
15
|
import * as internalBody from "@effect/platform/internal/http/body"
|
|
@@ -21,65 +23,84 @@ import * as Stream from "@effect/stream/Stream"
|
|
|
21
23
|
/** @internal */
|
|
22
24
|
export const tag = Context.Tag<Client.Client.Default>("@effect/platform/Http/Client")
|
|
23
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
|
+
|
|
39
|
+
/** @internal */
|
|
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
|
+
}
|
|
53
|
+
|
|
24
54
|
/** @internal */
|
|
25
55
|
export const fetch = (
|
|
26
56
|
options: RequestInit = {}
|
|
27
57
|
): Client.Client.Default =>
|
|
28
|
-
(request) =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
request,
|
|
66
|
-
error
|
|
67
|
-
})),
|
|
68
|
-
(body) => send(body)
|
|
69
|
-
) :
|
|
70
|
-
send(convertBody(request.body))
|
|
71
|
-
}
|
|
72
|
-
return send(undefined)
|
|
73
|
-
})
|
|
58
|
+
make((request) =>
|
|
59
|
+
Effect.flatMap(
|
|
60
|
+
UrlParams.makeUrl(request.url, request.urlParams, (_) =>
|
|
61
|
+
internalError.requestError({
|
|
62
|
+
request,
|
|
63
|
+
reason: "InvalidUrl",
|
|
64
|
+
error: _
|
|
65
|
+
})),
|
|
66
|
+
(url) =>
|
|
67
|
+
Effect.suspend(() => {
|
|
68
|
+
const headers = new Headers([...request.headers] as any)
|
|
69
|
+
const send = (body: BodyInit | undefined) =>
|
|
70
|
+
Effect.map(
|
|
71
|
+
Effect.tryPromise({
|
|
72
|
+
try: (signal) =>
|
|
73
|
+
globalThis.fetch(url, {
|
|
74
|
+
...options,
|
|
75
|
+
method: request.method,
|
|
76
|
+
headers,
|
|
77
|
+
body,
|
|
78
|
+
signal
|
|
79
|
+
}),
|
|
80
|
+
catch: (_) =>
|
|
81
|
+
internalError.requestError({
|
|
82
|
+
request,
|
|
83
|
+
reason: "Transport",
|
|
84
|
+
error: _
|
|
85
|
+
})
|
|
86
|
+
}),
|
|
87
|
+
(_) => internalResponse.fromWeb(request, _)
|
|
88
|
+
)
|
|
89
|
+
if (Method.hasBody(request.method)) {
|
|
90
|
+
return send(convertBody(request.body))
|
|
91
|
+
}
|
|
92
|
+
return send(undefined)
|
|
93
|
+
})
|
|
94
|
+
)
|
|
74
95
|
)
|
|
75
96
|
|
|
76
|
-
const convertBody = (body:
|
|
97
|
+
const convertBody = (body: Body.NonEffect): BodyInit | undefined => {
|
|
77
98
|
switch (body._tag) {
|
|
78
99
|
case "Empty":
|
|
79
100
|
return undefined
|
|
80
101
|
case "Raw":
|
|
81
102
|
return body.body as any
|
|
82
|
-
case "
|
|
103
|
+
case "Uint8Array":
|
|
83
104
|
return body.body
|
|
84
105
|
case "FormData":
|
|
85
106
|
return body.formData
|
|
@@ -93,7 +114,7 @@ export const fetchOk = (
|
|
|
93
114
|
): Client.Client.Default => filterStatusOk(fetch(options))
|
|
94
115
|
|
|
95
116
|
/** @internal */
|
|
96
|
-
export const
|
|
117
|
+
export const layer = Layer.succeed(tag, fetch())
|
|
97
118
|
|
|
98
119
|
/** @internal */
|
|
99
120
|
export const catchTag: {
|
|
@@ -115,7 +136,7 @@ export const catchTag: {
|
|
|
115
136
|
tag: K,
|
|
116
137
|
f: (e: Extract<E, { _tag: K }>) => Effect.Effect<R1, E1, A1>
|
|
117
138
|
): Client.Client<R1 | R, E1 | Exclude<E, { _tag: K }>, A1 | A> =>
|
|
118
|
-
|
|
139
|
+
setProto((request) => Effect.catchTag(self(request), tag, f))
|
|
119
140
|
)
|
|
120
141
|
|
|
121
142
|
/** @internal */
|
|
@@ -225,8 +246,7 @@ export const catchTags: {
|
|
|
225
246
|
) => Effect.Effect<any, any, infer A> ? A
|
|
226
247
|
: never
|
|
227
248
|
}[keyof Cases]
|
|
228
|
-
> =>
|
|
229
|
-
(request) => Effect.catchTags(self(request), cases)
|
|
249
|
+
> => setProto((request) => Effect.catchTags(self(request), cases))
|
|
230
250
|
)
|
|
231
251
|
|
|
232
252
|
/** @internal */
|
|
@@ -243,8 +263,7 @@ export const catchAll: {
|
|
|
243
263
|
<R, E, A, R2, E2, A2>(
|
|
244
264
|
self: Client.Client<R, E, A>,
|
|
245
265
|
f: (e: E) => Effect.Effect<R2, E2, A2>
|
|
246
|
-
): Client.Client<R | R2, E2, A2 | A> =>
|
|
247
|
-
(request) => Effect.catchAll(self(request), f)
|
|
266
|
+
): Client.Client<R | R2, E2, A2 | A> => setProto((request) => Effect.catchAll(self(request), f))
|
|
248
267
|
)
|
|
249
268
|
|
|
250
269
|
/** @internal */
|
|
@@ -257,7 +276,7 @@ export const filterOrElse = dual<
|
|
|
257
276
|
f: Predicate.Predicate<A>,
|
|
258
277
|
orElse: (a: A) => Effect.Effect<R2, E2, B>
|
|
259
278
|
) => Client.Client<R2 | R, E2 | E, A | B>
|
|
260
|
-
>(3, (self, f, orElse) => (request) => Effect.filterOrElse(self(request), f, orElse))
|
|
279
|
+
>(3, (self, f, orElse) => setProto((request) => Effect.filterOrElse(self(request), f, orElse)))
|
|
261
280
|
|
|
262
281
|
/** @internal */
|
|
263
282
|
export const filterOrFail = dual<
|
|
@@ -269,7 +288,7 @@ export const filterOrFail = dual<
|
|
|
269
288
|
f: Predicate.Predicate<A>,
|
|
270
289
|
orFailWith: (a: A) => E2
|
|
271
290
|
) => Client.Client<R, E2 | E, A>
|
|
272
|
-
>(3, (self, f, orFailWith) => (request) => Effect.filterOrFail(self(request), f, orFailWith))
|
|
291
|
+
>(3, (self, f, orFailWith) => setProto((request) => Effect.filterOrFail(self(request), f, orFailWith)))
|
|
273
292
|
|
|
274
293
|
/** @internal */
|
|
275
294
|
export const filterStatus = dual<
|
|
@@ -282,17 +301,19 @@ export const filterStatus = dual<
|
|
|
282
301
|
) => Client.Client.WithResponse<R, E | Error.ResponseError>
|
|
283
302
|
>(
|
|
284
303
|
2,
|
|
285
|
-
(self, f) =>
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
304
|
+
(self, f) =>
|
|
305
|
+
setProto((request) =>
|
|
306
|
+
Effect.filterOrFail(
|
|
307
|
+
self(request),
|
|
308
|
+
(response) => f(response.status),
|
|
309
|
+
(response) =>
|
|
310
|
+
internalError.responseError({
|
|
311
|
+
request,
|
|
312
|
+
response,
|
|
313
|
+
reason: "StatusCode",
|
|
314
|
+
error: "non 2xx status code"
|
|
315
|
+
})
|
|
316
|
+
)
|
|
296
317
|
)
|
|
297
318
|
)
|
|
298
319
|
|
|
@@ -310,7 +331,7 @@ export const map = dual<
|
|
|
310
331
|
self: Client.Client<R, E, A>,
|
|
311
332
|
f: (a: A) => B
|
|
312
333
|
) => Client.Client<R, E, B>
|
|
313
|
-
>(2, (self, f) => (request) => Effect.map(self(request), f))
|
|
334
|
+
>(2, (self, f) => setProto((request) => Effect.map(self(request), f)))
|
|
314
335
|
|
|
315
336
|
/** @internal */
|
|
316
337
|
export const mapEffect = dual<
|
|
@@ -321,7 +342,7 @@ export const mapEffect = dual<
|
|
|
321
342
|
self: Client.Client<R, E, A>,
|
|
322
343
|
f: (a: A) => Effect.Effect<R2, E2, B>
|
|
323
344
|
) => Client.Client<R | R2, E | E2, B>
|
|
324
|
-
>(2, (self, f) => (request) => Effect.flatMap(self(request), f))
|
|
345
|
+
>(2, (self, f) => setProto((request) => Effect.flatMap(self(request), f)))
|
|
325
346
|
|
|
326
347
|
/** @internal */
|
|
327
348
|
export const mapRequest = dual<
|
|
@@ -332,7 +353,7 @@ export const mapRequest = dual<
|
|
|
332
353
|
self: Client.Client<R, E, A>,
|
|
333
354
|
f: (a: ClientRequest.ClientRequest) => ClientRequest.ClientRequest
|
|
334
355
|
) => Client.Client<R, E, A>
|
|
335
|
-
>(2, (self, f) => (request) => self(f(request)))
|
|
356
|
+
>(2, (self, f) => setProto((request) => self(f(request))))
|
|
336
357
|
|
|
337
358
|
/** @internal */
|
|
338
359
|
export const mapRequestEffect = dual<
|
|
@@ -343,7 +364,7 @@ export const mapRequestEffect = dual<
|
|
|
343
364
|
self: Client.Client<R, E, A>,
|
|
344
365
|
f: (a: ClientRequest.ClientRequest) => Effect.Effect<R2, E2, ClientRequest.ClientRequest>
|
|
345
366
|
) => Client.Client<R | R2, E | E2, A>
|
|
346
|
-
>(2, (self, f) => (request) => Effect.flatMap(f(request), self))
|
|
367
|
+
>(2, (self, f) => setProto((request) => Effect.flatMap(f(request), self)))
|
|
347
368
|
|
|
348
369
|
/** @internal */
|
|
349
370
|
export const retry: {
|
|
@@ -359,8 +380,7 @@ export const retry: {
|
|
|
359
380
|
<R, E extends E0, E0, A, R1, B>(
|
|
360
381
|
self: Client.Client<R, E, A>,
|
|
361
382
|
policy: Schedule.Schedule<R1, E0, B>
|
|
362
|
-
): Client.Client<R | R1, E, A> =>
|
|
363
|
-
(request) => Effect.retry(self(request), policy)
|
|
383
|
+
): Client.Client<R | R1, E, A> => setProto((request) => Effect.retry(self(request), policy))
|
|
364
384
|
)
|
|
365
385
|
|
|
366
386
|
/** @internal */
|
|
@@ -394,7 +414,7 @@ export const schemaFunction = dual<
|
|
|
394
414
|
(body) =>
|
|
395
415
|
self(internalRequest.setBody(
|
|
396
416
|
request,
|
|
397
|
-
internalBody.
|
|
417
|
+
internalBody.uint8Array(body, "application/json")
|
|
398
418
|
))
|
|
399
419
|
)
|
|
400
420
|
})
|
|
@@ -408,7 +428,7 @@ export const tap = dual<
|
|
|
408
428
|
self: Client.Client<R, E, A>,
|
|
409
429
|
f: (a: A) => Effect.Effect<R2, E2, _>
|
|
410
430
|
) => Client.Client<R | R2, E | E2, A>
|
|
411
|
-
>(2, (self, f) => (request) => Effect.tap(self(request), f))
|
|
431
|
+
>(2, (self, f) => setProto((request) => Effect.tap(self(request), f)))
|
|
412
432
|
|
|
413
433
|
/** @internal */
|
|
414
434
|
export const tapRequest = dual<
|
|
@@ -419,4 +439,4 @@ export const tapRequest = dual<
|
|
|
419
439
|
self: Client.Client<R, E, A>,
|
|
420
440
|
f: (a: ClientRequest.ClientRequest) => Effect.Effect<R2, E2, _>
|
|
421
441
|
) => Client.Client<R | R2, E | E2, A>
|
|
422
|
-
>(2, (self, f) => (request) => Effect.zipRight(f(request), self(request)))
|
|
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
|
+
}
|