@effect/platform 0.64.1 → 0.65.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/FetchHttpClient/package.json +6 -0
- package/README.md +173 -195
- package/dist/cjs/FetchHttpClient.js +32 -0
- package/dist/cjs/FetchHttpClient.js.map +1 -0
- package/dist/cjs/HttpApiClient.js +1 -1
- package/dist/cjs/HttpApiClient.js.map +1 -1
- package/dist/cjs/HttpClient.js +5 -36
- package/dist/cjs/HttpClient.js.map +1 -1
- package/dist/cjs/HttpClientRequest.js +11 -11
- package/dist/cjs/HttpClientRequest.js.map +1 -1
- package/dist/cjs/HttpClientResponse.js +2 -61
- package/dist/cjs/HttpClientResponse.js.map +1 -1
- package/dist/cjs/HttpIncomingMessage.js +2 -29
- package/dist/cjs/HttpIncomingMessage.js.map +1 -1
- package/dist/cjs/Runtime.js +1 -1
- package/dist/cjs/Runtime.js.map +1 -1
- package/dist/cjs/Socket.js +42 -53
- package/dist/cjs/Socket.js.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/internal/fetchHttpClient.js +52 -0
- package/dist/cjs/internal/fetchHttpClient.js.map +1 -0
- package/dist/cjs/internal/httpClient.js +82 -71
- package/dist/cjs/internal/httpClient.js.map +1 -1
- package/dist/cjs/internal/httpClientRequest.js +13 -13
- package/dist/cjs/internal/httpClientRequest.js.map +1 -1
- package/dist/cjs/internal/httpClientResponse.js +1 -33
- package/dist/cjs/internal/httpClientResponse.js.map +1 -1
- package/dist/cjs/internal/worker.js +21 -29
- package/dist/cjs/internal/worker.js.map +1 -1
- package/dist/dts/FetchHttpClient.d.ts +27 -0
- package/dist/dts/FetchHttpClient.d.ts.map +1 -0
- package/dist/dts/HttpApiClient.d.ts +2 -2
- package/dist/dts/HttpClient.d.ts +53 -61
- package/dist/dts/HttpClient.d.ts.map +1 -1
- package/dist/dts/HttpClientRequest.d.ts +11 -11
- package/dist/dts/HttpClientRequest.d.ts.map +1 -1
- package/dist/dts/HttpClientResponse.d.ts +4 -90
- package/dist/dts/HttpClientResponse.d.ts.map +1 -1
- package/dist/dts/HttpIncomingMessage.d.ts +0 -16
- package/dist/dts/HttpIncomingMessage.d.ts.map +1 -1
- package/dist/dts/HttpServer.d.ts +1 -1
- package/dist/dts/Socket.d.ts +3 -3
- package/dist/dts/Socket.d.ts.map +1 -1
- package/dist/dts/index.d.ts +4 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/fetchHttpClient.d.ts +2 -0
- package/dist/dts/internal/fetchHttpClient.d.ts.map +1 -0
- package/dist/esm/FetchHttpClient.js +21 -0
- package/dist/esm/FetchHttpClient.js.map +1 -0
- package/dist/esm/HttpApiClient.js +1 -1
- package/dist/esm/HttpApiClient.js.map +1 -1
- package/dist/esm/HttpClient.js +4 -35
- package/dist/esm/HttpClient.js.map +1 -1
- package/dist/esm/HttpClientRequest.js +10 -10
- package/dist/esm/HttpClientRequest.js.map +1 -1
- package/dist/esm/HttpClientResponse.js +1 -63
- package/dist/esm/HttpClientResponse.js.map +1 -1
- package/dist/esm/HttpIncomingMessage.js +0 -24
- package/dist/esm/HttpIncomingMessage.js.map +1 -1
- package/dist/esm/Runtime.js +1 -1
- package/dist/esm/Runtime.js.map +1 -1
- package/dist/esm/Socket.js +42 -53
- package/dist/esm/Socket.js.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/fetchHttpClient.js +44 -0
- package/dist/esm/internal/fetchHttpClient.js.map +1 -0
- package/dist/esm/internal/httpClient.js +79 -69
- package/dist/esm/internal/httpClient.js.map +1 -1
- package/dist/esm/internal/httpClientRequest.js +11 -11
- package/dist/esm/internal/httpClientRequest.js.map +1 -1
- package/dist/esm/internal/httpClientResponse.js +0 -24
- package/dist/esm/internal/httpClientResponse.js.map +1 -1
- package/dist/esm/internal/worker.js +21 -29
- package/dist/esm/internal/worker.js.map +1 -1
- package/package.json +11 -3
- package/src/FetchHttpClient.ts +25 -0
- package/src/HttpApiClient.ts +5 -5
- package/src/HttpClient.ts +79 -85
- package/src/HttpClientRequest.ts +21 -21
- package/src/HttpClientResponse.ts +4 -162
- package/src/HttpIncomingMessage.ts +0 -43
- package/src/HttpServer.ts +1 -1
- package/src/Runtime.ts +1 -1
- package/src/Socket.ts +42 -58
- package/src/index.ts +5 -0
- package/src/internal/fetchHttpClient.ts +53 -0
- package/src/internal/httpClient.ts +149 -125
- package/src/internal/httpClientRequest.ts +12 -12
- package/src/internal/httpClientResponse.ts +6 -96
- package/src/internal/worker.ts +40 -55
package/src/HttpServer.ts
CHANGED
|
@@ -201,5 +201,5 @@ export const withLogAddress: <A, E, R>(layer: Layer.Layer<A, E, R>) => Layer.Lay
|
|
|
201
201
|
* @since 1.0.0
|
|
202
202
|
* @category layers
|
|
203
203
|
*/
|
|
204
|
-
export const layerTestClient: Layer.Layer<Client.HttpClient.
|
|
204
|
+
export const layerTestClient: Layer.Layer<Client.HttpClient.Service, never, Client.HttpClient.Service | HttpServer> =
|
|
205
205
|
internal.layerTestClient
|
package/src/Runtime.ts
CHANGED
|
@@ -63,7 +63,7 @@ const addPrettyLogger = (refs: FiberRefs.FiberRefs, fiberId: FiberId.Runtime) =>
|
|
|
63
63
|
fiberRef: FiberRef.currentLoggers,
|
|
64
64
|
value: loggers.pipe(
|
|
65
65
|
HashSet.remove(Logger.defaultLogger),
|
|
66
|
-
HashSet.add(Logger.
|
|
66
|
+
HashSet.add(Logger.prettyLoggerDefault)
|
|
67
67
|
)
|
|
68
68
|
})
|
|
69
69
|
}
|
package/src/Socket.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @since 1.0.0
|
|
3
3
|
*/
|
|
4
4
|
import * as Channel from "effect/Channel"
|
|
5
|
-
import * as Chunk from "effect/Chunk"
|
|
5
|
+
import type * as Chunk from "effect/Chunk"
|
|
6
6
|
import * as Context from "effect/Context"
|
|
7
7
|
import * as Deferred from "effect/Deferred"
|
|
8
8
|
import type { DurationInput } from "effect/Duration"
|
|
@@ -14,6 +14,7 @@ import * as FiberSet from "effect/FiberSet"
|
|
|
14
14
|
import { dual } from "effect/Function"
|
|
15
15
|
import { globalValue } from "effect/GlobalValue"
|
|
16
16
|
import * as Layer from "effect/Layer"
|
|
17
|
+
import * as Mailbox from "effect/Mailbox"
|
|
17
18
|
import * as Predicate from "effect/Predicate"
|
|
18
19
|
import * as Queue from "effect/Queue"
|
|
19
20
|
import * as Scope from "effect/Scope"
|
|
@@ -52,11 +53,11 @@ export const Socket: Context.Tag<Socket, Socket> = Context.GenericTag<Socket>(
|
|
|
52
53
|
*/
|
|
53
54
|
export interface Socket {
|
|
54
55
|
readonly [TypeId]: TypeId
|
|
55
|
-
readonly run: <_, E, R>(
|
|
56
|
-
handler: (_: Uint8Array) => Effect.Effect<_, E, R>
|
|
56
|
+
readonly run: <_, E = never, R = never>(
|
|
57
|
+
handler: (_: Uint8Array) => Effect.Effect<_, E, R> | void
|
|
57
58
|
) => Effect.Effect<void, SocketError | E, R>
|
|
58
|
-
readonly runRaw: <_, E, R>(
|
|
59
|
-
handler: (_: string | Uint8Array) => Effect.Effect<_, E, R>
|
|
59
|
+
readonly runRaw: <_, E = never, R = never>(
|
|
60
|
+
handler: (_: string | Uint8Array) => Effect.Effect<_, E, R> | void
|
|
60
61
|
) => Effect.Effect<void, SocketError | E, R>
|
|
61
62
|
readonly writer: Effect.Effect<
|
|
62
63
|
(chunk: Uint8Array | string | CloseEvent) => Effect.Effect<boolean>,
|
|
@@ -190,27 +191,25 @@ export const toChannelMap = <IE, A>(
|
|
|
190
191
|
> =>
|
|
191
192
|
Effect.scope.pipe(
|
|
192
193
|
Effect.bindTo("scope"),
|
|
193
|
-
Effect.
|
|
194
|
-
Effect.bind("semaphore", () => Effect.makeSemaphore(0)),
|
|
194
|
+
Effect.bind("mailbox", () => Mailbox.make<A, SocketError | IE>()),
|
|
195
195
|
Effect.bind("writeScope", ({ scope }) => Scope.fork(scope, ExecutionStrategy.sequential)),
|
|
196
196
|
Effect.bind("write", ({ writeScope }) => Scope.extend(self.writer, writeScope)),
|
|
197
|
-
Effect.bind("deferred", () => Deferred.make<void, SocketError | IE>()),
|
|
198
197
|
Effect.let(
|
|
199
198
|
"input",
|
|
200
199
|
(
|
|
201
|
-
{
|
|
200
|
+
{ mailbox, write, writeScope }
|
|
202
201
|
): AsyncProducer.AsyncInputProducer<IE, Chunk.Chunk<Uint8Array | string | CloseEvent>, unknown> => ({
|
|
203
202
|
awaitRead: () => Effect.void,
|
|
204
203
|
emit(chunk) {
|
|
205
204
|
return Effect.catchAllCause(
|
|
206
205
|
Effect.forEach(chunk, write, { discard: true }),
|
|
207
|
-
(cause) =>
|
|
206
|
+
(cause) => mailbox.failCause(cause)
|
|
208
207
|
)
|
|
209
208
|
},
|
|
210
209
|
error(error) {
|
|
211
210
|
return Effect.zipRight(
|
|
212
211
|
Scope.close(writeScope, Exit.void),
|
|
213
|
-
|
|
212
|
+
mailbox.failCause(error)
|
|
214
213
|
)
|
|
215
214
|
},
|
|
216
215
|
done() {
|
|
@@ -218,35 +217,16 @@ export const toChannelMap = <IE, A>(
|
|
|
218
217
|
}
|
|
219
218
|
})
|
|
220
219
|
),
|
|
221
|
-
Effect.tap(({
|
|
220
|
+
Effect.tap(({ mailbox, scope }) =>
|
|
222
221
|
self.runRaw((data) => {
|
|
223
|
-
|
|
224
|
-
return semaphore.release(1)
|
|
222
|
+
mailbox.unsafeOffer(f(data))
|
|
225
223
|
}).pipe(
|
|
226
|
-
|
|
227
|
-
Effect.raceFirst(Deferred.await(deferred)),
|
|
228
|
-
Effect.ensuring(Effect.suspend(() => {
|
|
229
|
-
state.finished = true
|
|
230
|
-
return semaphore.release(1)
|
|
231
|
-
})),
|
|
224
|
+
Mailbox.into(mailbox),
|
|
232
225
|
Effect.forkIn(scope),
|
|
233
226
|
Effect.interruptible
|
|
234
227
|
)
|
|
235
228
|
),
|
|
236
|
-
Effect.map(({
|
|
237
|
-
const loop: Channel.Channel<Chunk.Chunk<A>, unknown, SocketError | IE, unknown, void, unknown> = Channel.flatMap(
|
|
238
|
-
semaphore.take(1),
|
|
239
|
-
(_) => {
|
|
240
|
-
if (state.buffer.length === 0) {
|
|
241
|
-
return state.finished ? Deferred.await(deferred) : loop
|
|
242
|
-
}
|
|
243
|
-
const chunk = Chunk.unsafeFromArray(state.buffer)
|
|
244
|
-
state.buffer = []
|
|
245
|
-
return Channel.zipRight(Channel.write(chunk), state.finished ? Deferred.await(deferred) : loop)
|
|
246
|
-
}
|
|
247
|
-
)
|
|
248
|
-
return Channel.embedInput(loop, input)
|
|
249
|
-
}),
|
|
229
|
+
Effect.map(({ input, mailbox }) => Channel.embedInput(Mailbox.toChannel(mailbox), input)),
|
|
250
230
|
Channel.unwrapScoped
|
|
251
231
|
)
|
|
252
232
|
|
|
@@ -395,14 +375,7 @@ export const makeWebSocket = (url: string | Effect.Effect<string>, options?: {
|
|
|
395
375
|
(typeof url === "string" ? Effect.succeed(url) : url).pipe(
|
|
396
376
|
Effect.flatMap((url) => Effect.map(WebSocketConstructor, (f) => f(url)))
|
|
397
377
|
),
|
|
398
|
-
(ws) =>
|
|
399
|
-
Effect.sync(() => {
|
|
400
|
-
ws.onclose = null
|
|
401
|
-
ws.onerror = null
|
|
402
|
-
ws.onmessage = null
|
|
403
|
-
ws.onopen = null
|
|
404
|
-
return ws.close()
|
|
405
|
-
})
|
|
378
|
+
(ws) => Effect.sync(() => ws.close())
|
|
406
379
|
),
|
|
407
380
|
options
|
|
408
381
|
)
|
|
@@ -424,7 +397,7 @@ export const fromWebSocket = <R>(
|
|
|
424
397
|
(sendQueue) => {
|
|
425
398
|
const acquireContext = fiber.getFiberRef(FiberRef.currentContext) as Context.Context<R>
|
|
426
399
|
const closeCodeIsError = options?.closeCodeIsError ?? defaultCloseCodeIsError
|
|
427
|
-
const runRaw = <_, E, R>(handler: (_: string | Uint8Array) => Effect.Effect<_, E, R>) =>
|
|
400
|
+
const runRaw = <_, E, R>(handler: (_: string | Uint8Array) => Effect.Effect<_, E, R> | void) =>
|
|
428
401
|
acquire.pipe(
|
|
429
402
|
Effect.bindTo("ws"),
|
|
430
403
|
Effect.bind("fiberSet", () => FiberSet.make<any, E | SocketError>()),
|
|
@@ -433,16 +406,29 @@ export const fromWebSocket = <R>(
|
|
|
433
406
|
Effect.tap(({ fiberSet, run, ws }) => {
|
|
434
407
|
let open = false
|
|
435
408
|
|
|
436
|
-
|
|
437
|
-
|
|
409
|
+
function onMessage(event: MessageEvent) {
|
|
410
|
+
const result = handler(
|
|
438
411
|
typeof event.data === "string"
|
|
439
412
|
? event.data
|
|
440
413
|
: event.data instanceof Uint8Array
|
|
441
414
|
? event.data
|
|
442
415
|
: new Uint8Array(event.data)
|
|
443
|
-
)
|
|
416
|
+
)
|
|
417
|
+
if (Effect.isEffect(result)) {
|
|
418
|
+
run(result)
|
|
419
|
+
}
|
|
444
420
|
}
|
|
445
|
-
|
|
421
|
+
function onError(cause: Event) {
|
|
422
|
+
ws.removeEventListener("message", onMessage)
|
|
423
|
+
ws.removeEventListener("close", onClose)
|
|
424
|
+
Deferred.unsafeDone(
|
|
425
|
+
fiberSet.deferred,
|
|
426
|
+
Effect.fail(new SocketGenericError({ reason: open ? "Read" : "Open", cause }))
|
|
427
|
+
)
|
|
428
|
+
}
|
|
429
|
+
function onClose(event: globalThis.CloseEvent) {
|
|
430
|
+
ws.removeEventListener("message", onMessage)
|
|
431
|
+
ws.removeEventListener("error", onError)
|
|
446
432
|
Deferred.unsafeDone(
|
|
447
433
|
fiberSet.deferred,
|
|
448
434
|
Effect.fail(
|
|
@@ -454,19 +440,17 @@ export const fromWebSocket = <R>(
|
|
|
454
440
|
)
|
|
455
441
|
)
|
|
456
442
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
)
|
|
462
|
-
}
|
|
443
|
+
|
|
444
|
+
ws.addEventListener("close", onClose, { once: true })
|
|
445
|
+
ws.addEventListener("error", onError, { once: true })
|
|
446
|
+
ws.addEventListener("message", onMessage)
|
|
463
447
|
|
|
464
448
|
if (ws.readyState !== 1) {
|
|
465
449
|
const openDeferred = Deferred.unsafeMake<void>(fiber.id())
|
|
466
|
-
ws.
|
|
450
|
+
ws.addEventListener("open", () => {
|
|
467
451
|
open = true
|
|
468
452
|
Deferred.unsafeDone(openDeferred, Effect.void)
|
|
469
|
-
}
|
|
453
|
+
}, { once: true })
|
|
470
454
|
return Deferred.await(openDeferred).pipe(
|
|
471
455
|
Effect.timeoutFail({
|
|
472
456
|
duration: options?.openTimeout ?? 10000,
|
|
@@ -514,7 +498,7 @@ export const fromWebSocket = <R>(
|
|
|
514
498
|
)
|
|
515
499
|
|
|
516
500
|
const encoder = new TextEncoder()
|
|
517
|
-
const run = <_, E, R>(handler: (_: Uint8Array) => Effect.Effect<_, E, R>) =>
|
|
501
|
+
const run = <_, E, R>(handler: (_: Uint8Array) => Effect.Effect<_, E, R> | void) =>
|
|
518
502
|
runRaw((data) =>
|
|
519
503
|
typeof data === "string"
|
|
520
504
|
? handler(encoder.encode(data))
|
|
@@ -600,7 +584,7 @@ export const fromTransformStream = <R>(acquire: Effect.Effect<InputTransformStre
|
|
|
600
584
|
(sendQueue) => {
|
|
601
585
|
const acquireContext = fiber.getFiberRef(FiberRef.currentContext) as Context.Context<R>
|
|
602
586
|
const closeCodeIsError = options?.closeCodeIsError ?? defaultCloseCodeIsError
|
|
603
|
-
const runRaw = <_, E, R>(handler: (_: string | Uint8Array) => Effect.Effect<_, E, R>) =>
|
|
587
|
+
const runRaw = <_, E, R>(handler: (_: string | Uint8Array) => Effect.Effect<_, E, R> | void) =>
|
|
604
588
|
acquire.pipe(
|
|
605
589
|
Effect.bindTo("stream"),
|
|
606
590
|
Effect.bind("reader", ({ stream }) =>
|
|
@@ -681,7 +665,7 @@ export const fromTransformStream = <R>(acquire: Effect.Effect<InputTransformStre
|
|
|
681
665
|
)
|
|
682
666
|
|
|
683
667
|
const encoder = new TextEncoder()
|
|
684
|
-
const run = <_, E, R>(handler: (_: Uint8Array) => Effect.Effect<_, E, R>) =>
|
|
668
|
+
const run = <_, E, R>(handler: (_: Uint8Array) => Effect.Effect<_, E, R> | void) =>
|
|
685
669
|
runRaw((data) =>
|
|
686
670
|
typeof data === "string"
|
|
687
671
|
? handler(encoder.encode(data))
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect"
|
|
2
|
+
import * as FiberRef from "effect/FiberRef"
|
|
3
|
+
import * as Stream from "effect/Stream"
|
|
4
|
+
import type * as Client from "../HttpClient.js"
|
|
5
|
+
import * as Error from "../HttpClientError.js"
|
|
6
|
+
import * as client from "./httpClient.js"
|
|
7
|
+
import * as internalResponse from "./httpClientResponse.js"
|
|
8
|
+
|
|
9
|
+
/** @internal */
|
|
10
|
+
export const fetchTagKey = "@effect/platform/FetchHttpClient/Fetch"
|
|
11
|
+
/** @internal */
|
|
12
|
+
export const requestInitTagKey = "@effect/platform/FetchHttpClient/FetchOptions"
|
|
13
|
+
|
|
14
|
+
const fetch: Client.HttpClient.Service = client.makeService((request, url, signal, fiber) => {
|
|
15
|
+
const context = fiber.getFiberRef(FiberRef.currentContext)
|
|
16
|
+
const fetch: typeof globalThis.fetch = context.unsafeMap.get(fetchTagKey) ?? globalThis.fetch
|
|
17
|
+
const options: RequestInit = context.unsafeMap.get(requestInitTagKey) ?? {}
|
|
18
|
+
const headers = new globalThis.Headers(request.headers)
|
|
19
|
+
const send = (body: BodyInit | undefined) =>
|
|
20
|
+
Effect.map(
|
|
21
|
+
Effect.tryPromise({
|
|
22
|
+
try: () =>
|
|
23
|
+
fetch(url, {
|
|
24
|
+
...options,
|
|
25
|
+
method: request.method,
|
|
26
|
+
headers,
|
|
27
|
+
body,
|
|
28
|
+
duplex: request.body._tag === "Stream" ? "half" : undefined,
|
|
29
|
+
signal
|
|
30
|
+
} as any),
|
|
31
|
+
catch: (cause) =>
|
|
32
|
+
new Error.RequestError({
|
|
33
|
+
request,
|
|
34
|
+
reason: "Transport",
|
|
35
|
+
cause
|
|
36
|
+
})
|
|
37
|
+
}),
|
|
38
|
+
(response) => internalResponse.fromWeb(request, response)
|
|
39
|
+
)
|
|
40
|
+
switch (request.body._tag) {
|
|
41
|
+
case "Raw":
|
|
42
|
+
case "Uint8Array":
|
|
43
|
+
return send(request.body.body as any)
|
|
44
|
+
case "FormData":
|
|
45
|
+
return send(request.body.formData)
|
|
46
|
+
case "Stream":
|
|
47
|
+
return Effect.flatMap(Stream.toReadableStreamEffect(request.body.stream), send)
|
|
48
|
+
}
|
|
49
|
+
return send(undefined)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
/** @internal */
|
|
53
|
+
export const layer = client.layerMergedContext(Effect.succeed(fetch))
|