@effect/platform-node 0.22.0 → 0.23.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/CommandExecutor/dist/effect-platform-node-CommandExecutor.cjs.dev.js +8 -2
- package/CommandExecutor/dist/effect-platform-node-CommandExecutor.cjs.prod.js +8 -2
- package/CommandExecutor/dist/effect-platform-node-CommandExecutor.esm.js +8 -2
- package/Http/FormData/dist/effect-platform-node-Http-FormData.cjs.dev.js +8 -3
- package/Http/FormData/dist/effect-platform-node-Http-FormData.cjs.prod.js +8 -3
- package/Http/FormData/dist/effect-platform-node-Http-FormData.esm.js +8 -3
- package/Http/NodeClient/dist/effect-platform-node-Http-NodeClient.cjs.dev.js +11 -4
- package/Http/NodeClient/dist/effect-platform-node-Http-NodeClient.cjs.prod.js +11 -4
- package/Http/NodeClient/dist/effect-platform-node-Http-NodeClient.esm.js +11 -4
- package/Http/Server/dist/effect-platform-node-Http-Server.cjs.dev.js +13 -8
- package/Http/Server/dist/effect-platform-node-Http-Server.cjs.prod.js +13 -8
- package/Http/Server/dist/effect-platform-node-Http-Server.esm.js +13 -8
- package/HttpClient/dist/effect-platform-node-HttpClient.cjs.dev.js +11 -4
- package/HttpClient/dist/effect-platform-node-HttpClient.cjs.prod.js +11 -4
- package/HttpClient/dist/effect-platform-node-HttpClient.esm.js +11 -4
- package/HttpServer/dist/effect-platform-node-HttpServer.cjs.dev.js +12 -7
- package/HttpServer/dist/effect-platform-node-HttpServer.cjs.prod.js +12 -7
- package/HttpServer/dist/effect-platform-node-HttpServer.esm.js +12 -7
- package/NodeContext/dist/effect-platform-node-NodeContext.cjs.dev.js +8 -2
- package/NodeContext/dist/effect-platform-node-NodeContext.cjs.prod.js +8 -2
- package/NodeContext/dist/effect-platform-node-NodeContext.esm.js +8 -2
- package/Sink/dist/effect-platform-node-Sink.cjs.dev.js +11 -8
- package/Sink/dist/effect-platform-node-Sink.cjs.prod.js +11 -8
- package/Sink/dist/effect-platform-node-Sink.esm.js +11 -8
- package/Stream/dist/effect-platform-node-Stream.cjs.dev.js +33 -2
- package/Stream/dist/effect-platform-node-Stream.cjs.mjs +3 -0
- package/Stream/dist/effect-platform-node-Stream.cjs.prod.js +33 -2
- package/Stream/dist/effect-platform-node-Stream.esm.js +31 -3
- package/dist/{FormData-15af6672.cjs.dev.js → FormData-1b197f9f.cjs.dev.js} +1 -1
- package/dist/{FormData-5ea8a8b6.esm.js → FormData-9c8077af.esm.js} +1 -1
- package/dist/{FormData-d91e8016.cjs.prod.js → FormData-b4b59ecb.cjs.prod.js} +1 -1
- package/dist/{NodeClient-cd56cae8.esm.js → NodeClient-1b5f7152.esm.js} +2 -2
- package/dist/{NodeClient-ebd71893.cjs.dev.js → NodeClient-433f41ed.cjs.dev.js} +2 -2
- package/dist/{NodeClient-3432a6a8.cjs.prod.js → NodeClient-8d8ff956.cjs.prod.js} +2 -2
- package/dist/{Server-5dbcee7b.cjs.prod.js → Server-2dd836bc.cjs.prod.js} +3 -3
- package/dist/{Server-5f055bfd.cjs.dev.js → Server-66eb964d.cjs.dev.js} +3 -3
- package/dist/{Server-c08c825c.esm.js → Server-913d7080.esm.js} +3 -3
- package/dist/declarations/src/Sink.d.ts +2 -9
- package/dist/declarations/src/Sink.d.ts.map +1 -1
- package/dist/declarations/src/Stream.d.ts +42 -11
- package/dist/declarations/src/Stream.d.ts.map +1 -1
- package/dist/{formData-ecf6742b.cjs.prod.js → formData-2d4168a3.cjs.prod.js} +1 -2
- package/dist/{formData-632b1146.cjs.dev.js → formData-5d873a90.cjs.dev.js} +1 -2
- package/dist/{formData-dd75bbe1.esm.js → formData-b50a3c9f.esm.js} +1 -2
- package/dist/{incomingMessage-f56be93e.cjs.prod.js → incomingMessage-4526b216.cjs.prod.js} +2 -4
- package/dist/{incomingMessage-11c9bea6.esm.js → incomingMessage-a56317f6.esm.js} +2 -4
- package/dist/{incomingMessage-86bcf94d.cjs.dev.js → incomingMessage-ac1817d4.cjs.dev.js} +2 -4
- package/dist/sink-3a150604.cjs.dev.js +48 -0
- package/dist/sink-570c8582.cjs.prod.js +48 -0
- package/dist/sink-5dfcc09e.esm.js +23 -0
- package/dist/stream-1667e8bf.cjs.prod.js +209 -0
- package/dist/stream-8bbecb96.cjs.dev.js +209 -0
- package/dist/stream-faaffb40.esm.js +175 -0
- package/package.json +5 -3
- package/src/Sink.ts +3 -11
- package/src/Stream.ts +59 -13
- package/src/internal/http/formData.ts +1 -2
- package/src/internal/http/incomingMessage.ts +2 -4
- package/src/internal/http/nodeClient.ts +1 -1
- package/src/internal/http/server.ts +3 -1
- package/src/internal/sink.ts +42 -47
- package/src/internal/stream.ts +242 -61
- package/dist/sink-bd7ef408.esm.js +0 -34
- package/dist/sink-da49e187.cjs.prod.js +0 -57
- package/dist/sink-daf9e0e5.cjs.dev.js +0 -57
- package/dist/stream-1456ece0.cjs.dev.js +0 -120
- package/dist/stream-860139d3.esm.js +0 -94
- package/dist/stream-ef8b6a66.cjs.prod.js +0 -120
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import * as Channel from 'effect/Channel';
|
|
2
|
+
import * as Chunk from 'effect/Chunk';
|
|
3
|
+
import * as Effect from 'effect/Effect';
|
|
4
|
+
import * as Either from 'effect/Either';
|
|
5
|
+
import * as Exit from 'effect/Exit';
|
|
6
|
+
import { dual, pipe } from 'effect/Function';
|
|
7
|
+
import * as Queue from 'effect/Queue';
|
|
8
|
+
import * as Stream from 'effect/Stream';
|
|
9
|
+
import { SystemError } from '@effect/platform/Error';
|
|
10
|
+
|
|
11
|
+
/** @internal */
|
|
12
|
+
const fromReadable = (evaluate, onError, {
|
|
13
|
+
chunkSize
|
|
14
|
+
} = {}) => Stream.fromChannel(readChannel(evaluate, onError, chunkSize ? Number(chunkSize) : undefined));
|
|
15
|
+
|
|
16
|
+
/** @internal */
|
|
17
|
+
const toString = (readable, options) => {
|
|
18
|
+
const maxBytesNumber = options.maxBytes ? Number(options.maxBytes) : undefined;
|
|
19
|
+
return Effect.acquireUseRelease(Effect.sync(() => {
|
|
20
|
+
const stream = readable();
|
|
21
|
+
stream.setEncoding(options.encoding ?? "utf8");
|
|
22
|
+
return stream;
|
|
23
|
+
}), stream => Effect.async(resume => {
|
|
24
|
+
let string = "";
|
|
25
|
+
let bytes = 0;
|
|
26
|
+
stream.once("error", err => {
|
|
27
|
+
resume(Effect.fail(options.onFailure(err)));
|
|
28
|
+
});
|
|
29
|
+
stream.once("end", () => {
|
|
30
|
+
resume(Effect.succeed(string));
|
|
31
|
+
});
|
|
32
|
+
stream.on("data", chunk => {
|
|
33
|
+
string += chunk;
|
|
34
|
+
bytes += Buffer.byteLength(chunk);
|
|
35
|
+
if (maxBytesNumber && bytes > maxBytesNumber) {
|
|
36
|
+
resume(Effect.fail(options.onFailure(new Error("maxBytes exceeded"))));
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}), stream => Effect.sync(() => {
|
|
40
|
+
stream.removeAllListeners();
|
|
41
|
+
if ("closed" in stream && !stream.closed) {
|
|
42
|
+
stream.destroy();
|
|
43
|
+
}
|
|
44
|
+
}));
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/** @internal */
|
|
48
|
+
const toUint8Array = (readable, options) => {
|
|
49
|
+
const maxBytesNumber = options.maxBytes ? Number(options.maxBytes) : undefined;
|
|
50
|
+
return Effect.acquireUseRelease(Effect.sync(readable), stream => Effect.async(resume => {
|
|
51
|
+
let buffer = Buffer.alloc(0);
|
|
52
|
+
let bytes = 0;
|
|
53
|
+
stream.once("error", err => {
|
|
54
|
+
resume(Effect.fail(options.onFailure(err)));
|
|
55
|
+
});
|
|
56
|
+
stream.once("end", () => {
|
|
57
|
+
resume(Effect.succeed(buffer));
|
|
58
|
+
});
|
|
59
|
+
stream.on("data", chunk => {
|
|
60
|
+
buffer = Buffer.concat([buffer, chunk]);
|
|
61
|
+
bytes += chunk.length;
|
|
62
|
+
if (maxBytesNumber && bytes > maxBytesNumber) {
|
|
63
|
+
resume(Effect.fail(options.onFailure(new Error("maxBytes exceeded"))));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}), stream => Effect.sync(() => {
|
|
67
|
+
stream.removeAllListeners();
|
|
68
|
+
if ("closed" in stream && !stream.closed) {
|
|
69
|
+
stream.destroy();
|
|
70
|
+
}
|
|
71
|
+
}));
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/** @internal */
|
|
75
|
+
const fromDuplex = (evaluate, onError, options = {}) => Channel.acquireUseRelease(Effect.tap(Effect.zip(Effect.sync(evaluate), Queue.unbounded()), ([duplex, queue]) => readableOffer(duplex, queue, onError)), ([duplex, queue]) => Channel.embedInput(readableTake(duplex, queue, options.chunkSize ? Number(options.chunkSize) : undefined), writeInput(duplex, cause => Queue.offer(queue, Either.left(Exit.failCause(cause))), options)), ([duplex, queue]) => Effect.zipRight(Effect.sync(() => {
|
|
76
|
+
duplex.removeAllListeners();
|
|
77
|
+
if (!duplex.closed) {
|
|
78
|
+
duplex.destroy();
|
|
79
|
+
}
|
|
80
|
+
}), Queue.shutdown(queue)));
|
|
81
|
+
|
|
82
|
+
/** @internal */
|
|
83
|
+
const pipeThroughDuplex = /*#__PURE__*/dual(args => Stream.StreamTypeId in args[0], (self, duplex, onError, options) => Stream.pipeThroughChannelOrFail(self, fromDuplex(duplex, onError, options)));
|
|
84
|
+
|
|
85
|
+
/** @internal */
|
|
86
|
+
const pipeThroughSimple = /*#__PURE__*/dual(2, (self, duplex) => Stream.pipeThroughChannelOrFail(self, fromDuplex(duplex, error => SystemError({
|
|
87
|
+
module: "Stream",
|
|
88
|
+
method: "pipeThroughSimple",
|
|
89
|
+
pathOrDescriptor: "",
|
|
90
|
+
reason: "Unknown",
|
|
91
|
+
message: String(error)
|
|
92
|
+
}))));
|
|
93
|
+
const readChannel = (evaluate, onError, chunkSize) => Channel.acquireUseRelease(Effect.tap(Effect.zip(Effect.sync(evaluate), Queue.unbounded()), ([readable, queue]) => readableOffer(readable, queue, onError)), ([readable, queue]) => readableTake(readable, queue, chunkSize), ([readable, queue]) => Effect.zipRight(Effect.sync(() => {
|
|
94
|
+
readable.removeAllListeners();
|
|
95
|
+
if ("closed" in readable && !readable.closed) {
|
|
96
|
+
readable.destroy();
|
|
97
|
+
}
|
|
98
|
+
}), Queue.shutdown(queue)));
|
|
99
|
+
|
|
100
|
+
/** @internal */
|
|
101
|
+
const writeInput = (writable, onFailure, {
|
|
102
|
+
encoding,
|
|
103
|
+
endOnDone = true
|
|
104
|
+
}, onDone = Effect.unit) => {
|
|
105
|
+
const write = writeEffect(writable, encoding);
|
|
106
|
+
const close = endOnDone ? Effect.async(resume => {
|
|
107
|
+
if ("closed" in writable && writable.closed) {
|
|
108
|
+
resume(Effect.unit);
|
|
109
|
+
} else {
|
|
110
|
+
writable.once("finish", () => resume(Effect.unit));
|
|
111
|
+
writable.end();
|
|
112
|
+
}
|
|
113
|
+
}) : Effect.unit;
|
|
114
|
+
return {
|
|
115
|
+
awaitRead: () => Effect.unit,
|
|
116
|
+
emit: write,
|
|
117
|
+
error: cause => Effect.zipRight(close, onFailure(cause)),
|
|
118
|
+
done: _ => Effect.zipRight(close, onDone)
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/** @internal */
|
|
123
|
+
const writeEffect = (writable, encoding) => chunk => chunk.length === 0 ? Effect.unit : Effect.async(resume => {
|
|
124
|
+
const iterator = chunk[Symbol.iterator]();
|
|
125
|
+
let next = iterator.next();
|
|
126
|
+
function loop() {
|
|
127
|
+
const item = next;
|
|
128
|
+
next = iterator.next();
|
|
129
|
+
const success = writable.write(item.value, encoding);
|
|
130
|
+
if (next.done) {
|
|
131
|
+
resume(Effect.unit);
|
|
132
|
+
} else if (success) {
|
|
133
|
+
loop();
|
|
134
|
+
} else {
|
|
135
|
+
writable.once("drain", loop);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
loop();
|
|
139
|
+
});
|
|
140
|
+
const readableOffer = (readable, queue, onError) => Effect.sync(() => {
|
|
141
|
+
readable.on("readable", () => {
|
|
142
|
+
const size = queue.unsafeSize();
|
|
143
|
+
if (size._tag === "Some" && size.value <= 0) {
|
|
144
|
+
queue.unsafeOffer(Either.right(void 0));
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
readable.on("error", err => {
|
|
148
|
+
queue.unsafeOffer(Either.left(Exit.fail(onError(err))));
|
|
149
|
+
});
|
|
150
|
+
readable.on("end", () => {
|
|
151
|
+
queue.unsafeOffer(Either.left(Exit.unit));
|
|
152
|
+
});
|
|
153
|
+
if (readable.readable) {
|
|
154
|
+
queue.unsafeOffer(Either.right(void 0));
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
const readableTake = (readable, queue, chunkSize) => {
|
|
158
|
+
const read = readChunkChannel(readable, chunkSize);
|
|
159
|
+
const loop = pipe(Channel.fromEffect(Queue.take(queue)), Channel.flatMap(Either.match({
|
|
160
|
+
onLeft: Channel.fromEffect,
|
|
161
|
+
onRight: _ => Channel.flatMap(read, () => loop)
|
|
162
|
+
})));
|
|
163
|
+
return loop;
|
|
164
|
+
};
|
|
165
|
+
const readChunkChannel = (readable, chunkSize) => Channel.flatMap(Channel.sync(() => {
|
|
166
|
+
const arr = [];
|
|
167
|
+
let chunk = readable.read(chunkSize);
|
|
168
|
+
while (chunk !== null) {
|
|
169
|
+
arr.push(chunk);
|
|
170
|
+
chunk = readable.read(chunkSize);
|
|
171
|
+
}
|
|
172
|
+
return Chunk.unsafeFromArray(arr);
|
|
173
|
+
}), Channel.write);
|
|
174
|
+
|
|
175
|
+
export { fromDuplex as a, pipeThroughSimple as b, toUint8Array as c, fromReadable as f, pipeThroughDuplex as p, toString as t, writeInput as w };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect/platform-node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Unified interfaces for common platform-specific services",
|
|
5
5
|
"main": "dist/effect-platform-node.cjs.js",
|
|
6
6
|
"module": "dist/effect-platform-node.esm.js",
|
|
@@ -36,7 +36,9 @@
|
|
|
36
36
|
"@effect/schema": "^0.43.0",
|
|
37
37
|
"@types/busboy": "^1.5.1",
|
|
38
38
|
"@types/mime": "^3.0.2",
|
|
39
|
-
"
|
|
39
|
+
"@types/tar": "^6.1.6",
|
|
40
|
+
"effect": "2.0.0-next.48",
|
|
41
|
+
"tar": "^6.2.0"
|
|
40
42
|
},
|
|
41
43
|
"peerDependencies": {
|
|
42
44
|
"effect": "2.0.0-next.48"
|
|
@@ -44,7 +46,7 @@
|
|
|
44
46
|
"dependencies": {
|
|
45
47
|
"busboy": "^1.6.0",
|
|
46
48
|
"mime": "^3.0.0",
|
|
47
|
-
"@effect/platform": "^0.
|
|
49
|
+
"@effect/platform": "^0.22.0"
|
|
48
50
|
},
|
|
49
51
|
"files": [
|
|
50
52
|
"src",
|
package/src/Sink.ts
CHANGED
|
@@ -6,22 +6,14 @@ import type { LazyArg } from "effect/Function"
|
|
|
6
6
|
import type { Sink } from "effect/Sink"
|
|
7
7
|
import type { Writable } from "stream"
|
|
8
8
|
import * as internal from "./internal/sink"
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @category model
|
|
12
|
-
* @since 1.0.0
|
|
13
|
-
*/
|
|
14
|
-
export interface FromWritableOptions {
|
|
15
|
-
readonly endOnClose?: boolean
|
|
16
|
-
readonly encoding?: BufferEncoding
|
|
17
|
-
}
|
|
9
|
+
import type { FromWritableOptions } from "./Stream"
|
|
18
10
|
|
|
19
11
|
/**
|
|
20
12
|
* @category constructor
|
|
21
13
|
* @since 1.0.0
|
|
22
14
|
*/
|
|
23
|
-
export const fromWritable: <E, A>(
|
|
24
|
-
evaluate: LazyArg<Writable>,
|
|
15
|
+
export const fromWritable: <E, A = string | Uint8Array>(
|
|
16
|
+
evaluate: LazyArg<Writable | NodeJS.WritableStream>,
|
|
25
17
|
onError: (error: unknown) => E,
|
|
26
18
|
options?: FromWritableOptions
|
|
27
19
|
) => Sink<never, E, A, never, void> = internal.fromWritable
|
package/src/Stream.ts
CHANGED
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
* @since 1.0.0
|
|
3
3
|
*/
|
|
4
4
|
import type { SizeInput } from "@effect/platform/FileSystem"
|
|
5
|
+
import type { Channel } from "effect/Channel"
|
|
6
|
+
import type { Chunk } from "effect/Chunk"
|
|
5
7
|
import type { Effect } from "effect/Effect"
|
|
6
8
|
import type { LazyArg } from "effect/Function"
|
|
7
9
|
import type { Stream } from "effect/Stream"
|
|
8
|
-
import type { Readable } from "stream"
|
|
10
|
+
import type { Duplex, Readable } from "stream"
|
|
11
|
+
import type { PlatformError } from "./Error"
|
|
9
12
|
import * as internal from "./internal/stream"
|
|
10
13
|
|
|
11
14
|
/**
|
|
@@ -17,26 +20,72 @@ export interface FromReadableOptions {
|
|
|
17
20
|
readonly chunkSize?: SizeInput
|
|
18
21
|
}
|
|
19
22
|
|
|
23
|
+
/**
|
|
24
|
+
* @category model
|
|
25
|
+
* @since 1.0.0
|
|
26
|
+
*/
|
|
27
|
+
export interface FromWritableOptions {
|
|
28
|
+
readonly endOnDone?: boolean
|
|
29
|
+
readonly encoding?: BufferEncoding
|
|
30
|
+
}
|
|
31
|
+
|
|
20
32
|
/**
|
|
21
33
|
* @category constructors
|
|
22
34
|
* @since 1.0.0
|
|
23
35
|
*/
|
|
24
|
-
export const fromReadable: <E, A>(
|
|
25
|
-
evaluate: LazyArg<Readable>,
|
|
36
|
+
export const fromReadable: <E, A = Uint8Array>(
|
|
37
|
+
evaluate: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
26
38
|
onError: (error: unknown) => E,
|
|
27
|
-
|
|
39
|
+
{ chunkSize }?: FromReadableOptions
|
|
28
40
|
) => Stream<never, E, A> = internal.fromReadable
|
|
29
41
|
|
|
42
|
+
/**
|
|
43
|
+
* @category constructors
|
|
44
|
+
* @since 1.0.0
|
|
45
|
+
*/
|
|
46
|
+
export const fromDuplex: <IE, E, I = Uint8Array, O = Uint8Array>(
|
|
47
|
+
evaluate: LazyArg<Duplex>,
|
|
48
|
+
onError: (error: unknown) => E,
|
|
49
|
+
options?: FromReadableOptions & FromWritableOptions
|
|
50
|
+
) => Channel<never, IE, Chunk<I>, unknown, IE | E, Chunk<O>, void> = internal.fromDuplex
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @category combinators
|
|
54
|
+
* @since 1.0.0
|
|
55
|
+
*/
|
|
56
|
+
export const pipeThroughDuplex: {
|
|
57
|
+
<E2, B = Uint8Array>(
|
|
58
|
+
duplex: LazyArg<Duplex>,
|
|
59
|
+
onError: (error: unknown) => E2,
|
|
60
|
+
options?: FromReadableOptions & FromWritableOptions
|
|
61
|
+
): <R, E, A>(self: Stream<R, E, A>) => Stream<R, E2 | E, B>
|
|
62
|
+
<R, E, A, E2, B = Uint8Array>(
|
|
63
|
+
self: Stream<R, E, A>,
|
|
64
|
+
duplex: LazyArg<Duplex>,
|
|
65
|
+
onError: (error: unknown) => E2,
|
|
66
|
+
options?: FromReadableOptions & FromWritableOptions
|
|
67
|
+
): Stream<R, E | E2, B>
|
|
68
|
+
} = internal.pipeThroughDuplex
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @category combinators
|
|
72
|
+
* @since 1.0.0
|
|
73
|
+
*/
|
|
74
|
+
export const pipeThroughSimple: {
|
|
75
|
+
(duplex: LazyArg<Duplex>): <R, E>(self: Stream<R, E, string | Uint8Array>) => Stream<R, E | PlatformError, Uint8Array>
|
|
76
|
+
<R, E>(self: Stream<R, E, string | Uint8Array>, duplex: LazyArg<Duplex>): Stream<R, PlatformError | E, Uint8Array>
|
|
77
|
+
} = internal.pipeThroughSimple
|
|
78
|
+
|
|
30
79
|
/**
|
|
31
80
|
* @since 1.0.0
|
|
32
81
|
* @category conversions
|
|
33
82
|
*/
|
|
34
83
|
export const toString: <E>(
|
|
84
|
+
readable: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
35
85
|
options: {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
maxBytes?: SizeInput
|
|
86
|
+
readonly onFailure: (error: unknown) => E
|
|
87
|
+
readonly encoding?: BufferEncoding | undefined
|
|
88
|
+
readonly maxBytes?: SizeInput | undefined
|
|
40
89
|
}
|
|
41
90
|
) => Effect<never, E, string> = internal.toString
|
|
42
91
|
|
|
@@ -45,9 +94,6 @@ export const toString: <E>(
|
|
|
45
94
|
* @category conversions
|
|
46
95
|
*/
|
|
47
96
|
export const toUint8Array: <E>(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
onFailure: (error: unknown) => E
|
|
51
|
-
maxBytes?: SizeInput
|
|
52
|
-
}
|
|
97
|
+
readable: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
98
|
+
options: { readonly onFailure: (error: unknown) => E; readonly maxBytes?: SizeInput | undefined }
|
|
53
99
|
) => Effect<never, E, Uint8Array> = internal.toUint8Array
|
|
@@ -88,8 +88,7 @@ export const stream = (
|
|
|
88
88
|
(part) =>
|
|
89
89
|
part._tag === "File" && Chunk.some(fieldMimeTypes, (_) => part.contentType.includes(_)) ?
|
|
90
90
|
Effect.map(
|
|
91
|
-
NodeStream.toString({
|
|
92
|
-
readable: () => part.source,
|
|
91
|
+
NodeStream.toString(() => part.source, {
|
|
93
92
|
onFailure: (error) => FormData.FormDataError("InternalError", error)
|
|
94
93
|
}),
|
|
95
94
|
(content) => new FieldImpl(part.key, part.contentType, content)
|
|
@@ -37,8 +37,7 @@ export class IncomingMessageImpl<E> implements IncomingMessage.IncomingMessage<E
|
|
|
37
37
|
Effect.flatMap(
|
|
38
38
|
FiberRef.get(IncomingMessage.maxBodySize),
|
|
39
39
|
(maxBodySize) =>
|
|
40
|
-
NodeStream.toString({
|
|
41
|
-
readable: () => this.source,
|
|
40
|
+
NodeStream.toString(() => this.source, {
|
|
42
41
|
onFailure: this.onError,
|
|
43
42
|
maxBytes: Option.getOrUndefined(maxBodySize)
|
|
44
43
|
})
|
|
@@ -73,8 +72,7 @@ export class IncomingMessageImpl<E> implements IncomingMessage.IncomingMessage<E
|
|
|
73
72
|
return Effect.flatMap(
|
|
74
73
|
FiberRef.get(IncomingMessage.maxBodySize),
|
|
75
74
|
(maxBodySize) =>
|
|
76
|
-
NodeStream.toUint8Array({
|
|
77
|
-
readable: () => this.source,
|
|
75
|
+
NodeStream.toUint8Array(() => this.source, {
|
|
78
76
|
onFailure: this.onError,
|
|
79
77
|
maxBytes: Option.getOrUndefined(maxBodySize)
|
|
80
78
|
})
|
|
@@ -54,7 +54,7 @@ export const makeAgentLayer = (options?: Https.AgentOptions): Layer.Layer<never,
|
|
|
54
54
|
export const agentLayer = makeAgentLayer()
|
|
55
55
|
|
|
56
56
|
const fromAgent = (agent: NodeClient.HttpAgent): Client.Client.Default =>
|
|
57
|
-
Client.
|
|
57
|
+
Client.makeDefault((request) =>
|
|
58
58
|
Effect.flatMap(
|
|
59
59
|
UrlParams.makeUrl(request.url, request.urlParams, (_) =>
|
|
60
60
|
Error.RequestError({
|
|
@@ -79,7 +79,9 @@ export const make = (
|
|
|
79
79
|
port: address.port
|
|
80
80
|
},
|
|
81
81
|
serve: (httpApp, middleware) => {
|
|
82
|
-
const handledApp = middleware
|
|
82
|
+
const handledApp = middleware
|
|
83
|
+
? middleware(App.withDefaultMiddleware(respond(httpApp)))
|
|
84
|
+
: App.withDefaultMiddleware(respond(httpApp))
|
|
83
85
|
return Effect.flatMap(Effect.all([Effect.runtime(), Effect.fiberId]), ([runtime, fiberId]) => {
|
|
84
86
|
const runFork = Runtime.runFork(runtime)
|
|
85
87
|
function handler(nodeRequest: Http.IncomingMessage, nodeResponse: Http.ServerResponse) {
|
package/src/internal/sink.ts
CHANGED
|
@@ -1,61 +1,56 @@
|
|
|
1
|
+
import * as Channel from "effect/Channel"
|
|
2
|
+
import type * as Chunk from "effect/Chunk"
|
|
3
|
+
import * as Deferred from "effect/Deferred"
|
|
1
4
|
import * as Effect from "effect/Effect"
|
|
2
5
|
import type { LazyArg } from "effect/Function"
|
|
3
|
-
import { pipe } from "effect/Function"
|
|
4
6
|
import * as Sink from "effect/Sink"
|
|
5
7
|
import type { Writable } from "node:stream"
|
|
6
|
-
import type { FromWritableOptions } from "../
|
|
8
|
+
import type { FromWritableOptions } from "../Stream"
|
|
9
|
+
import { writeInput } from "./stream"
|
|
7
10
|
|
|
8
11
|
/** @internal */
|
|
9
|
-
export const fromWritable = <E, A>(
|
|
10
|
-
evaluate: LazyArg<Writable>,
|
|
12
|
+
export const fromWritable = <E, A = Uint8Array | string>(
|
|
13
|
+
evaluate: LazyArg<Writable | NodeJS.WritableStream>,
|
|
11
14
|
onError: (error: unknown) => E,
|
|
12
|
-
|
|
15
|
+
options: FromWritableOptions = {}
|
|
13
16
|
): Sink.Sink<never, E, A, never, void> =>
|
|
14
|
-
|
|
15
|
-
makeSinkWithRelease<E, A>(evaluate, onError, encoding) :
|
|
16
|
-
makeSink<E, A>(evaluate, onError, encoding)
|
|
17
|
+
Sink.suspend(() => Sink.fromChannel(writeChannel(evaluate(), onError, options)))
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const writeChannel = <IE, OE, A>(
|
|
20
|
+
writable: Writable | NodeJS.WritableStream,
|
|
21
|
+
onError: (error: unknown) => OE,
|
|
22
|
+
options: FromWritableOptions = {}
|
|
23
|
+
): Channel.Channel<never, IE, Chunk.Chunk<A>, unknown, IE | OE, Chunk.Chunk<never>, void> =>
|
|
24
|
+
Channel.flatMap(
|
|
25
|
+
Deferred.make<IE, void>(),
|
|
26
|
+
(deferred) => {
|
|
27
|
+
const input = writeInput<IE, A>(
|
|
28
|
+
writable,
|
|
29
|
+
(_) => Deferred.failCause(deferred, _),
|
|
30
|
+
options,
|
|
31
|
+
Deferred.complete(deferred, Effect.unit)
|
|
32
|
+
)
|
|
33
|
+
return Channel.embedInput(
|
|
34
|
+
writableOutput(writable, deferred, onError),
|
|
35
|
+
input
|
|
36
|
+
)
|
|
37
|
+
}
|
|
23
38
|
)
|
|
24
39
|
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
40
|
+
const writableOutput = <IE, E>(
|
|
41
|
+
writable: Writable | NodeJS.WritableStream,
|
|
42
|
+
deferred: Deferred.Deferred<IE, void>,
|
|
43
|
+
onError: (error: unknown) => E
|
|
29
44
|
) =>
|
|
30
|
-
|
|
31
|
-
Effect.
|
|
32
|
-
|
|
33
|
-
Sink.unwrapScoped
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
const endWritable = (stream: Writable) =>
|
|
37
|
-
Effect.async<never, never, void>((resume) => {
|
|
38
|
-
if (stream.closed) {
|
|
39
|
-
resume(Effect.unit)
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
stream.end(() => resume(Effect.unit))
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
const write = <E, A>(stream: Writable, onError: (error: unknown) => E, encoding?: BufferEncoding) => (_: A) =>
|
|
47
|
-
Effect.async<never, E, void>((resume) => {
|
|
48
|
-
const cb = (err?: Error | null) => {
|
|
49
|
-
if (err) {
|
|
45
|
+
Effect.raceFirst(
|
|
46
|
+
Effect.async<never, E, never>((resume) => {
|
|
47
|
+
function handleError(err: unknown) {
|
|
50
48
|
resume(Effect.fail(onError(err)))
|
|
51
|
-
} else {
|
|
52
|
-
resume(Effect.unit)
|
|
53
49
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
})
|
|
50
|
+
writable.on("error", handleError)
|
|
51
|
+
return Effect.sync(() => {
|
|
52
|
+
writable.off("error", handleError)
|
|
53
|
+
})
|
|
54
|
+
}),
|
|
55
|
+
Deferred.await(deferred)
|
|
56
|
+
)
|