@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
package/src/internal/stream.ts
CHANGED
|
@@ -1,77 +1,42 @@
|
|
|
1
1
|
import type { SizeInput } from "@effect/platform/FileSystem"
|
|
2
|
+
import type { Cause } from "effect"
|
|
3
|
+
import * as Channel from "effect/Channel"
|
|
4
|
+
import type * as AsyncInput from "effect/ChannelSingleProducerAsyncInput"
|
|
5
|
+
import * as Chunk from "effect/Chunk"
|
|
2
6
|
import * as Effect from "effect/Effect"
|
|
7
|
+
import * as Either from "effect/Either"
|
|
8
|
+
import * as Exit from "effect/Exit"
|
|
3
9
|
import type { LazyArg } from "effect/Function"
|
|
4
|
-
import { pipe } from "effect/Function"
|
|
5
|
-
import * as
|
|
10
|
+
import { dual, pipe } from "effect/Function"
|
|
11
|
+
import * as Queue from "effect/Queue"
|
|
6
12
|
import * as Stream from "effect/Stream"
|
|
7
|
-
import type { Readable } from "node:stream"
|
|
8
|
-
import type
|
|
13
|
+
import type { Duplex, Readable, Writable } from "node:stream"
|
|
14
|
+
import { type PlatformError, SystemError } from "../Error"
|
|
15
|
+
import type { FromReadableOptions, FromWritableOptions } from "../Stream"
|
|
9
16
|
|
|
10
17
|
/** @internal */
|
|
11
|
-
export const fromReadable = <E, A>(
|
|
12
|
-
evaluate: LazyArg<Readable>,
|
|
18
|
+
export const fromReadable = <E, A = Uint8Array>(
|
|
19
|
+
evaluate: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
13
20
|
onError: (error: unknown) => E,
|
|
14
21
|
{ chunkSize }: FromReadableOptions = {}
|
|
15
22
|
): Stream.Stream<never, E, A> =>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Effect.sync(() => {
|
|
19
|
-
stream.removeAllListeners()
|
|
20
|
-
|
|
21
|
-
if (!stream.closed) {
|
|
22
|
-
stream.destroy()
|
|
23
|
-
}
|
|
24
|
-
})),
|
|
25
|
-
Effect.map((stream) =>
|
|
26
|
-
Stream.async<never, E, Readable>((emit) => {
|
|
27
|
-
stream.once("error", (err) => {
|
|
28
|
-
emit.fail(onError(err))
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
// The 'close' event is emitted after a process has ended and the stdio
|
|
32
|
-
// streams of a child process have been closed. This is distinct from
|
|
33
|
-
// the 'exit' event, since multiple processes might share the same
|
|
34
|
-
// stdio streams. The 'close' event will always emit after 'exit' was
|
|
35
|
-
// already emitted, or 'error' if the child failed to spawn.
|
|
36
|
-
stream.once("close", () => {
|
|
37
|
-
emit.end()
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
stream.on("readable", () => {
|
|
41
|
-
emit.single(stream)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
if (stream.readable) {
|
|
45
|
-
emit.single(stream)
|
|
46
|
-
}
|
|
47
|
-
}, 1)
|
|
48
|
-
),
|
|
49
|
-
Stream.unwrapScoped,
|
|
50
|
-
Stream.flatMap((_) => Stream.repeatEffectOption(readChunk<A>(_, chunkSize)))
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
const readChunk = <A>(
|
|
54
|
-
stream: Readable,
|
|
55
|
-
size: SizeInput | undefined
|
|
56
|
-
): Effect.Effect<never, Option.Option<never>, A> =>
|
|
57
|
-
pipe(
|
|
58
|
-
Effect.sync(() => (size ? stream.read(Number(size)) : stream.read()) as A | null),
|
|
59
|
-
Effect.flatMap((_) => (_ ? Effect.succeed(_) : Effect.fail(Option.none())))
|
|
23
|
+
Stream.fromChannel(
|
|
24
|
+
readChannel<E, A>(evaluate, onError, chunkSize ? Number(chunkSize) : undefined)
|
|
60
25
|
)
|
|
61
26
|
|
|
62
27
|
/** @internal */
|
|
63
28
|
export const toString = <E>(
|
|
29
|
+
readable: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
64
30
|
options: {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
maxBytes?: SizeInput
|
|
31
|
+
readonly onFailure: (error: unknown) => E
|
|
32
|
+
readonly encoding?: BufferEncoding
|
|
33
|
+
readonly maxBytes?: SizeInput
|
|
69
34
|
}
|
|
70
35
|
): Effect.Effect<never, E, string> => {
|
|
71
36
|
const maxBytesNumber = options.maxBytes ? Number(options.maxBytes) : undefined
|
|
72
37
|
return Effect.acquireUseRelease(
|
|
73
38
|
Effect.sync(() => {
|
|
74
|
-
const stream =
|
|
39
|
+
const stream = readable()
|
|
75
40
|
stream.setEncoding(options.encoding ?? "utf8")
|
|
76
41
|
return stream
|
|
77
42
|
}),
|
|
@@ -96,7 +61,7 @@ export const toString = <E>(
|
|
|
96
61
|
(stream) =>
|
|
97
62
|
Effect.sync(() => {
|
|
98
63
|
stream.removeAllListeners()
|
|
99
|
-
if (!stream.closed) {
|
|
64
|
+
if ("closed" in stream && !stream.closed) {
|
|
100
65
|
stream.destroy()
|
|
101
66
|
}
|
|
102
67
|
})
|
|
@@ -105,15 +70,15 @@ export const toString = <E>(
|
|
|
105
70
|
|
|
106
71
|
/** @internal */
|
|
107
72
|
export const toUint8Array = <E>(
|
|
73
|
+
readable: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
108
74
|
options: {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
maxBytes?: SizeInput
|
|
75
|
+
readonly onFailure: (error: unknown) => E
|
|
76
|
+
readonly maxBytes?: SizeInput
|
|
112
77
|
}
|
|
113
78
|
): Effect.Effect<never, E, Uint8Array> => {
|
|
114
79
|
const maxBytesNumber = options.maxBytes ? Number(options.maxBytes) : undefined
|
|
115
80
|
return Effect.acquireUseRelease(
|
|
116
|
-
Effect.sync(
|
|
81
|
+
Effect.sync(readable),
|
|
117
82
|
(stream) =>
|
|
118
83
|
Effect.async((resume) => {
|
|
119
84
|
let buffer = Buffer.alloc(0)
|
|
@@ -135,9 +100,225 @@ export const toUint8Array = <E>(
|
|
|
135
100
|
(stream) =>
|
|
136
101
|
Effect.sync(() => {
|
|
137
102
|
stream.removeAllListeners()
|
|
138
|
-
if (!stream.closed) {
|
|
103
|
+
if ("closed" in stream && !stream.closed) {
|
|
139
104
|
stream.destroy()
|
|
140
105
|
}
|
|
141
106
|
})
|
|
142
107
|
)
|
|
143
108
|
}
|
|
109
|
+
|
|
110
|
+
/** @internal */
|
|
111
|
+
export const fromDuplex = <IE, E, I = Uint8Array | string, O = Uint8Array>(
|
|
112
|
+
evaluate: LazyArg<Duplex>,
|
|
113
|
+
onError: (error: unknown) => E,
|
|
114
|
+
options: FromReadableOptions & FromWritableOptions = {}
|
|
115
|
+
): Channel.Channel<never, IE, Chunk.Chunk<I>, unknown, IE | E, Chunk.Chunk<O>, void> =>
|
|
116
|
+
Channel.acquireUseRelease(
|
|
117
|
+
Effect.tap(
|
|
118
|
+
Effect.zip(
|
|
119
|
+
Effect.sync(evaluate),
|
|
120
|
+
Queue.unbounded<Either.Either<Exit.Exit<IE | E, void>, void>>()
|
|
121
|
+
),
|
|
122
|
+
([duplex, queue]) => readableOffer(duplex, queue, onError)
|
|
123
|
+
),
|
|
124
|
+
([duplex, queue]) =>
|
|
125
|
+
Channel.embedInput(
|
|
126
|
+
readableTake(duplex, queue, options.chunkSize ? Number(options.chunkSize) : undefined),
|
|
127
|
+
writeInput(
|
|
128
|
+
duplex,
|
|
129
|
+
(cause) => Queue.offer(queue, Either.left(Exit.failCause(cause))),
|
|
130
|
+
options
|
|
131
|
+
)
|
|
132
|
+
),
|
|
133
|
+
([duplex, queue]) =>
|
|
134
|
+
Effect.zipRight(
|
|
135
|
+
Effect.sync(() => {
|
|
136
|
+
duplex.removeAllListeners()
|
|
137
|
+
if (!duplex.closed) {
|
|
138
|
+
duplex.destroy()
|
|
139
|
+
}
|
|
140
|
+
}),
|
|
141
|
+
Queue.shutdown(queue)
|
|
142
|
+
)
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
/** @internal */
|
|
146
|
+
export const pipeThroughDuplex = dual<
|
|
147
|
+
<E2, B = Uint8Array>(
|
|
148
|
+
duplex: LazyArg<Duplex>,
|
|
149
|
+
onError: (error: unknown) => E2,
|
|
150
|
+
options?: FromReadableOptions & FromWritableOptions
|
|
151
|
+
) => <R, E, A>(self: Stream.Stream<R, E, A>) => Stream.Stream<R, E | E2, B>,
|
|
152
|
+
<R, E, A, E2, B = Uint8Array>(
|
|
153
|
+
self: Stream.Stream<R, E, A>,
|
|
154
|
+
duplex: LazyArg<Duplex>,
|
|
155
|
+
onError: (error: unknown) => E2,
|
|
156
|
+
options?: FromReadableOptions & FromWritableOptions
|
|
157
|
+
) => Stream.Stream<R, E | E2, B>
|
|
158
|
+
>(
|
|
159
|
+
(args) => Stream.StreamTypeId in args[0],
|
|
160
|
+
(self, duplex, onError, options) =>
|
|
161
|
+
Stream.pipeThroughChannelOrFail(
|
|
162
|
+
self,
|
|
163
|
+
fromDuplex(duplex, onError, options)
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
/** @internal */
|
|
168
|
+
export const pipeThroughSimple = dual<
|
|
169
|
+
(
|
|
170
|
+
duplex: LazyArg<Duplex>
|
|
171
|
+
) => <R, E>(self: Stream.Stream<R, E, string | Uint8Array>) => Stream.Stream<R, E | PlatformError, Uint8Array>,
|
|
172
|
+
<R, E>(
|
|
173
|
+
self: Stream.Stream<R, E, string | Uint8Array>,
|
|
174
|
+
duplex: LazyArg<Duplex>
|
|
175
|
+
) => Stream.Stream<R, E | PlatformError, Uint8Array>
|
|
176
|
+
>(
|
|
177
|
+
2,
|
|
178
|
+
(self, duplex) =>
|
|
179
|
+
Stream.pipeThroughChannelOrFail(
|
|
180
|
+
self,
|
|
181
|
+
fromDuplex(duplex, (error) =>
|
|
182
|
+
SystemError({
|
|
183
|
+
module: "Stream",
|
|
184
|
+
method: "pipeThroughSimple",
|
|
185
|
+
pathOrDescriptor: "",
|
|
186
|
+
reason: "Unknown",
|
|
187
|
+
message: String(error)
|
|
188
|
+
}))
|
|
189
|
+
)
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
const readChannel = <E, A = Uint8Array>(
|
|
193
|
+
evaluate: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
194
|
+
onError: (error: unknown) => E,
|
|
195
|
+
chunkSize: number | undefined
|
|
196
|
+
): Channel.Channel<never, unknown, unknown, unknown, E, Chunk.Chunk<A>, void> =>
|
|
197
|
+
Channel.acquireUseRelease(
|
|
198
|
+
Effect.tap(
|
|
199
|
+
Effect.zip(
|
|
200
|
+
Effect.sync(evaluate),
|
|
201
|
+
Queue.unbounded<Either.Either<Exit.Exit<E, void>, void>>()
|
|
202
|
+
),
|
|
203
|
+
([readable, queue]) => readableOffer(readable, queue, onError)
|
|
204
|
+
),
|
|
205
|
+
([readable, queue]) => readableTake(readable, queue, chunkSize),
|
|
206
|
+
([readable, queue]) =>
|
|
207
|
+
Effect.zipRight(
|
|
208
|
+
Effect.sync(() => {
|
|
209
|
+
readable.removeAllListeners()
|
|
210
|
+
if ("closed" in readable && !readable.closed) {
|
|
211
|
+
readable.destroy()
|
|
212
|
+
}
|
|
213
|
+
}),
|
|
214
|
+
Queue.shutdown(queue)
|
|
215
|
+
)
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
/** @internal */
|
|
219
|
+
export const writeInput = <IE, A>(
|
|
220
|
+
writable: Writable | NodeJS.WritableStream,
|
|
221
|
+
onFailure: (cause: Cause.Cause<IE>) => Effect.Effect<never, never, void>,
|
|
222
|
+
{ encoding, endOnDone = true }: FromWritableOptions,
|
|
223
|
+
onDone = Effect.unit
|
|
224
|
+
): AsyncInput.AsyncInputProducer<IE, Chunk.Chunk<A>, unknown> => {
|
|
225
|
+
const write = writeEffect(writable, encoding)
|
|
226
|
+
const close = endOnDone
|
|
227
|
+
? Effect.async<never, never, void>((resume) => {
|
|
228
|
+
if ("closed" in writable && writable.closed) {
|
|
229
|
+
resume(Effect.unit)
|
|
230
|
+
} else {
|
|
231
|
+
writable.once("finish", () => resume(Effect.unit))
|
|
232
|
+
writable.end()
|
|
233
|
+
}
|
|
234
|
+
})
|
|
235
|
+
: Effect.unit
|
|
236
|
+
return {
|
|
237
|
+
awaitRead: () => Effect.unit,
|
|
238
|
+
emit: write,
|
|
239
|
+
error: (cause) => Effect.zipRight(close, onFailure(cause)),
|
|
240
|
+
done: (_) => Effect.zipRight(close, onDone)
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** @internal */
|
|
245
|
+
export const writeEffect = <A>(
|
|
246
|
+
writable: Writable | NodeJS.WritableStream,
|
|
247
|
+
encoding?: BufferEncoding
|
|
248
|
+
) =>
|
|
249
|
+
(chunk: Chunk.Chunk<A>) =>
|
|
250
|
+
chunk.length === 0 ?
|
|
251
|
+
Effect.unit :
|
|
252
|
+
Effect.async<never, never, void>((resume) => {
|
|
253
|
+
const iterator = chunk[Symbol.iterator]()
|
|
254
|
+
let next = iterator.next()
|
|
255
|
+
function loop() {
|
|
256
|
+
const item = next
|
|
257
|
+
next = iterator.next()
|
|
258
|
+
const success = writable.write(item.value, encoding as any)
|
|
259
|
+
if (next.done) {
|
|
260
|
+
resume(Effect.unit)
|
|
261
|
+
} else if (success) {
|
|
262
|
+
loop()
|
|
263
|
+
} else {
|
|
264
|
+
writable.once("drain", loop)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
loop()
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
const readableOffer = <E>(
|
|
271
|
+
readable: Readable | NodeJS.ReadableStream,
|
|
272
|
+
queue: Queue.Queue<Either.Either<Exit.Exit<E, void>, void>>,
|
|
273
|
+
onError: (error: unknown) => E
|
|
274
|
+
) =>
|
|
275
|
+
Effect.sync(() => {
|
|
276
|
+
readable.on("readable", () => {
|
|
277
|
+
const size = queue.unsafeSize()
|
|
278
|
+
if (size._tag === "Some" && size.value <= 0) {
|
|
279
|
+
queue.unsafeOffer(Either.right(void 0))
|
|
280
|
+
}
|
|
281
|
+
})
|
|
282
|
+
readable.on("error", (err) => {
|
|
283
|
+
queue.unsafeOffer(Either.left(Exit.fail(onError(err))))
|
|
284
|
+
})
|
|
285
|
+
readable.on("end", () => {
|
|
286
|
+
queue.unsafeOffer(Either.left(Exit.unit))
|
|
287
|
+
})
|
|
288
|
+
if (readable.readable) {
|
|
289
|
+
queue.unsafeOffer(Either.right(void 0))
|
|
290
|
+
}
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
const readableTake = <E, A>(
|
|
294
|
+
readable: Readable | NodeJS.ReadableStream,
|
|
295
|
+
queue: Queue.Queue<Either.Either<Exit.Exit<E, void>, void>>,
|
|
296
|
+
chunkSize: number | undefined
|
|
297
|
+
) => {
|
|
298
|
+
const read = readChunkChannel<A>(readable, chunkSize)
|
|
299
|
+
const loop: Channel.Channel<never, unknown, unknown, unknown, E, Chunk.Chunk<A>, void> = pipe(
|
|
300
|
+
Channel.fromEffect(Queue.take(queue)),
|
|
301
|
+
Channel.flatMap(Either.match({
|
|
302
|
+
onLeft: Channel.fromEffect,
|
|
303
|
+
onRight: (_) => Channel.flatMap(read, () => loop)
|
|
304
|
+
}))
|
|
305
|
+
)
|
|
306
|
+
return loop
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const readChunkChannel = <A>(
|
|
310
|
+
readable: Readable | NodeJS.ReadableStream,
|
|
311
|
+
chunkSize: number | undefined
|
|
312
|
+
) =>
|
|
313
|
+
Channel.flatMap(
|
|
314
|
+
Channel.sync(() => {
|
|
315
|
+
const arr: Array<A> = []
|
|
316
|
+
let chunk = readable.read(chunkSize)
|
|
317
|
+
while (chunk !== null) {
|
|
318
|
+
arr.push(chunk)
|
|
319
|
+
chunk = readable.read(chunkSize)
|
|
320
|
+
}
|
|
321
|
+
return Chunk.unsafeFromArray(arr)
|
|
322
|
+
}),
|
|
323
|
+
Channel.write
|
|
324
|
+
)
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import * as Effect from 'effect/Effect';
|
|
2
|
-
import { pipe } from 'effect/Function';
|
|
3
|
-
import * as Sink from 'effect/Sink';
|
|
4
|
-
|
|
5
|
-
/** @internal */
|
|
6
|
-
const fromWritable = (evaluate, onError, {
|
|
7
|
-
encoding,
|
|
8
|
-
endOnClose = true
|
|
9
|
-
} = {}) => endOnClose ? makeSinkWithRelease(evaluate, onError, encoding) : makeSink(evaluate, onError, encoding);
|
|
10
|
-
const makeSink = (stream, onError, encoding) => pipe(Effect.sync(stream), Effect.map(stream => Sink.forEach(write(stream, onError, encoding))), Sink.unwrap);
|
|
11
|
-
const makeSinkWithRelease = (stream, onError, encoding) => pipe(Effect.acquireRelease(Effect.sync(stream), endWritable), Effect.map(stream => Sink.forEach(write(stream, onError, encoding))), Sink.unwrapScoped);
|
|
12
|
-
const endWritable = stream => Effect.async(resume => {
|
|
13
|
-
if (stream.closed) {
|
|
14
|
-
resume(Effect.unit);
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
stream.end(() => resume(Effect.unit));
|
|
18
|
-
});
|
|
19
|
-
const write = (stream, onError, encoding) => _ => Effect.async(resume => {
|
|
20
|
-
const cb = err => {
|
|
21
|
-
if (err) {
|
|
22
|
-
resume(Effect.fail(onError(err)));
|
|
23
|
-
} else {
|
|
24
|
-
resume(Effect.unit);
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
if (encoding) {
|
|
28
|
-
stream.write(_, encoding, cb);
|
|
29
|
-
} else {
|
|
30
|
-
stream.write(_, cb);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
export { fromWritable as f };
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var Effect = require('effect/Effect');
|
|
4
|
-
var Function = require('effect/Function');
|
|
5
|
-
var Sink = require('effect/Sink');
|
|
6
|
-
|
|
7
|
-
function _interopNamespace(e) {
|
|
8
|
-
if (e && e.__esModule) return e;
|
|
9
|
-
var n = Object.create(null);
|
|
10
|
-
if (e) {
|
|
11
|
-
Object.keys(e).forEach(function (k) {
|
|
12
|
-
if (k !== 'default') {
|
|
13
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
-
enumerable: true,
|
|
16
|
-
get: function () { return e[k]; }
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
n["default"] = e;
|
|
22
|
-
return Object.freeze(n);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
var Effect__namespace = /*#__PURE__*/_interopNamespace(Effect);
|
|
26
|
-
var Sink__namespace = /*#__PURE__*/_interopNamespace(Sink);
|
|
27
|
-
|
|
28
|
-
/** @internal */
|
|
29
|
-
const fromWritable = (evaluate, onError, {
|
|
30
|
-
encoding,
|
|
31
|
-
endOnClose = true
|
|
32
|
-
} = {}) => endOnClose ? makeSinkWithRelease(evaluate, onError, encoding) : makeSink(evaluate, onError, encoding);
|
|
33
|
-
const makeSink = (stream, onError, encoding) => Function.pipe(Effect__namespace.sync(stream), Effect__namespace.map(stream => Sink__namespace.forEach(write(stream, onError, encoding))), Sink__namespace.unwrap);
|
|
34
|
-
const makeSinkWithRelease = (stream, onError, encoding) => Function.pipe(Effect__namespace.acquireRelease(Effect__namespace.sync(stream), endWritable), Effect__namespace.map(stream => Sink__namespace.forEach(write(stream, onError, encoding))), Sink__namespace.unwrapScoped);
|
|
35
|
-
const endWritable = stream => Effect__namespace.async(resume => {
|
|
36
|
-
if (stream.closed) {
|
|
37
|
-
resume(Effect__namespace.unit);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
stream.end(() => resume(Effect__namespace.unit));
|
|
41
|
-
});
|
|
42
|
-
const write = (stream, onError, encoding) => _ => Effect__namespace.async(resume => {
|
|
43
|
-
const cb = err => {
|
|
44
|
-
if (err) {
|
|
45
|
-
resume(Effect__namespace.fail(onError(err)));
|
|
46
|
-
} else {
|
|
47
|
-
resume(Effect__namespace.unit);
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
if (encoding) {
|
|
51
|
-
stream.write(_, encoding, cb);
|
|
52
|
-
} else {
|
|
53
|
-
stream.write(_, cb);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
exports.fromWritable = fromWritable;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var Effect = require('effect/Effect');
|
|
4
|
-
var Function = require('effect/Function');
|
|
5
|
-
var Sink = require('effect/Sink');
|
|
6
|
-
|
|
7
|
-
function _interopNamespace(e) {
|
|
8
|
-
if (e && e.__esModule) return e;
|
|
9
|
-
var n = Object.create(null);
|
|
10
|
-
if (e) {
|
|
11
|
-
Object.keys(e).forEach(function (k) {
|
|
12
|
-
if (k !== 'default') {
|
|
13
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
-
enumerable: true,
|
|
16
|
-
get: function () { return e[k]; }
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
n["default"] = e;
|
|
22
|
-
return Object.freeze(n);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
var Effect__namespace = /*#__PURE__*/_interopNamespace(Effect);
|
|
26
|
-
var Sink__namespace = /*#__PURE__*/_interopNamespace(Sink);
|
|
27
|
-
|
|
28
|
-
/** @internal */
|
|
29
|
-
const fromWritable = (evaluate, onError, {
|
|
30
|
-
encoding,
|
|
31
|
-
endOnClose = true
|
|
32
|
-
} = {}) => endOnClose ? makeSinkWithRelease(evaluate, onError, encoding) : makeSink(evaluate, onError, encoding);
|
|
33
|
-
const makeSink = (stream, onError, encoding) => Function.pipe(Effect__namespace.sync(stream), Effect__namespace.map(stream => Sink__namespace.forEach(write(stream, onError, encoding))), Sink__namespace.unwrap);
|
|
34
|
-
const makeSinkWithRelease = (stream, onError, encoding) => Function.pipe(Effect__namespace.acquireRelease(Effect__namespace.sync(stream), endWritable), Effect__namespace.map(stream => Sink__namespace.forEach(write(stream, onError, encoding))), Sink__namespace.unwrapScoped);
|
|
35
|
-
const endWritable = stream => Effect__namespace.async(resume => {
|
|
36
|
-
if (stream.closed) {
|
|
37
|
-
resume(Effect__namespace.unit);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
stream.end(() => resume(Effect__namespace.unit));
|
|
41
|
-
});
|
|
42
|
-
const write = (stream, onError, encoding) => _ => Effect__namespace.async(resume => {
|
|
43
|
-
const cb = err => {
|
|
44
|
-
if (err) {
|
|
45
|
-
resume(Effect__namespace.fail(onError(err)));
|
|
46
|
-
} else {
|
|
47
|
-
resume(Effect__namespace.unit);
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
if (encoding) {
|
|
51
|
-
stream.write(_, encoding, cb);
|
|
52
|
-
} else {
|
|
53
|
-
stream.write(_, cb);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
exports.fromWritable = fromWritable;
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var Effect = require('effect/Effect');
|
|
4
|
-
var Function = require('effect/Function');
|
|
5
|
-
var Option = require('effect/Option');
|
|
6
|
-
var Stream = require('effect/Stream');
|
|
7
|
-
|
|
8
|
-
function _interopNamespace(e) {
|
|
9
|
-
if (e && e.__esModule) return e;
|
|
10
|
-
var n = Object.create(null);
|
|
11
|
-
if (e) {
|
|
12
|
-
Object.keys(e).forEach(function (k) {
|
|
13
|
-
if (k !== 'default') {
|
|
14
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
get: function () { return e[k]; }
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
n["default"] = e;
|
|
23
|
-
return Object.freeze(n);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
var Effect__namespace = /*#__PURE__*/_interopNamespace(Effect);
|
|
27
|
-
var Option__namespace = /*#__PURE__*/_interopNamespace(Option);
|
|
28
|
-
var Stream__namespace = /*#__PURE__*/_interopNamespace(Stream);
|
|
29
|
-
|
|
30
|
-
/** @internal */
|
|
31
|
-
const fromReadable = (evaluate, onError, {
|
|
32
|
-
chunkSize
|
|
33
|
-
} = {}) => Function.pipe(Effect__namespace.acquireRelease(Effect__namespace.sync(evaluate), stream => Effect__namespace.sync(() => {
|
|
34
|
-
stream.removeAllListeners();
|
|
35
|
-
if (!stream.closed) {
|
|
36
|
-
stream.destroy();
|
|
37
|
-
}
|
|
38
|
-
})), Effect__namespace.map(stream => Stream__namespace.async(emit => {
|
|
39
|
-
stream.once("error", err => {
|
|
40
|
-
emit.fail(onError(err));
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// The 'close' event is emitted after a process has ended and the stdio
|
|
44
|
-
// streams of a child process have been closed. This is distinct from
|
|
45
|
-
// the 'exit' event, since multiple processes might share the same
|
|
46
|
-
// stdio streams. The 'close' event will always emit after 'exit' was
|
|
47
|
-
// already emitted, or 'error' if the child failed to spawn.
|
|
48
|
-
stream.once("close", () => {
|
|
49
|
-
emit.end();
|
|
50
|
-
});
|
|
51
|
-
stream.on("readable", () => {
|
|
52
|
-
emit.single(stream);
|
|
53
|
-
});
|
|
54
|
-
if (stream.readable) {
|
|
55
|
-
emit.single(stream);
|
|
56
|
-
}
|
|
57
|
-
}, 1)), Stream__namespace.unwrapScoped, Stream__namespace.flatMap(_ => Stream__namespace.repeatEffectOption(readChunk(_, chunkSize))));
|
|
58
|
-
const readChunk = (stream, size) => Function.pipe(Effect__namespace.sync(() => size ? stream.read(Number(size)) : stream.read()), Effect__namespace.flatMap(_ => _ ? Effect__namespace.succeed(_) : Effect__namespace.fail(Option__namespace.none())));
|
|
59
|
-
|
|
60
|
-
/** @internal */
|
|
61
|
-
const toString = options => {
|
|
62
|
-
const maxBytesNumber = options.maxBytes ? Number(options.maxBytes) : undefined;
|
|
63
|
-
return Effect__namespace.acquireUseRelease(Effect__namespace.sync(() => {
|
|
64
|
-
const stream = options.readable();
|
|
65
|
-
stream.setEncoding(options.encoding ?? "utf8");
|
|
66
|
-
return stream;
|
|
67
|
-
}), stream => Effect__namespace.async(resume => {
|
|
68
|
-
let string = "";
|
|
69
|
-
let bytes = 0;
|
|
70
|
-
stream.once("error", err => {
|
|
71
|
-
resume(Effect__namespace.fail(options.onFailure(err)));
|
|
72
|
-
});
|
|
73
|
-
stream.once("end", () => {
|
|
74
|
-
resume(Effect__namespace.succeed(string));
|
|
75
|
-
});
|
|
76
|
-
stream.on("data", chunk => {
|
|
77
|
-
string += chunk;
|
|
78
|
-
bytes += Buffer.byteLength(chunk);
|
|
79
|
-
if (maxBytesNumber && bytes > maxBytesNumber) {
|
|
80
|
-
resume(Effect__namespace.fail(options.onFailure(new Error("maxBytes exceeded"))));
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}), stream => Effect__namespace.sync(() => {
|
|
84
|
-
stream.removeAllListeners();
|
|
85
|
-
if (!stream.closed) {
|
|
86
|
-
stream.destroy();
|
|
87
|
-
}
|
|
88
|
-
}));
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
/** @internal */
|
|
92
|
-
const toUint8Array = options => {
|
|
93
|
-
const maxBytesNumber = options.maxBytes ? Number(options.maxBytes) : undefined;
|
|
94
|
-
return Effect__namespace.acquireUseRelease(Effect__namespace.sync(options.readable), stream => Effect__namespace.async(resume => {
|
|
95
|
-
let buffer = Buffer.alloc(0);
|
|
96
|
-
let bytes = 0;
|
|
97
|
-
stream.once("error", err => {
|
|
98
|
-
resume(Effect__namespace.fail(options.onFailure(err)));
|
|
99
|
-
});
|
|
100
|
-
stream.once("end", () => {
|
|
101
|
-
resume(Effect__namespace.succeed(buffer));
|
|
102
|
-
});
|
|
103
|
-
stream.on("data", chunk => {
|
|
104
|
-
buffer = Buffer.concat([buffer, chunk]);
|
|
105
|
-
bytes += chunk.length;
|
|
106
|
-
if (maxBytesNumber && bytes > maxBytesNumber) {
|
|
107
|
-
resume(Effect__namespace.fail(options.onFailure(new Error("maxBytes exceeded"))));
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}), stream => Effect__namespace.sync(() => {
|
|
111
|
-
stream.removeAllListeners();
|
|
112
|
-
if (!stream.closed) {
|
|
113
|
-
stream.destroy();
|
|
114
|
-
}
|
|
115
|
-
}));
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
exports.fromReadable = fromReadable;
|
|
119
|
-
exports.toString = toString;
|
|
120
|
-
exports.toUint8Array = toUint8Array;
|