@effect/platform-node-shared 4.0.0-beta.1 → 4.0.0-beta.100
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/README.md +3 -3
- package/dist/NodeChildProcessSpawner.d.ts +19 -5
- package/dist/NodeChildProcessSpawner.d.ts.map +1 -1
- package/dist/NodeChildProcessSpawner.js +105 -118
- package/dist/NodeChildProcessSpawner.js.map +1 -1
- package/dist/NodeClusterSocket.d.ts +10 -4
- package/dist/NodeClusterSocket.d.ts.map +1 -1
- package/dist/NodeClusterSocket.js +22 -8
- package/dist/NodeClusterSocket.js.map +1 -1
- package/dist/NodeCrypto.d.ts +27 -0
- package/dist/NodeCrypto.d.ts.map +1 -0
- package/dist/NodeCrypto.js +55 -0
- package/dist/NodeCrypto.js.map +1 -0
- package/dist/NodeFileSystem.d.ts +5 -2
- package/dist/NodeFileSystem.d.ts.map +1 -1
- package/dist/NodeFileSystem.js +44 -28
- package/dist/NodeFileSystem.js.map +1 -1
- package/dist/NodePath.d.ts +15 -6
- package/dist/NodePath.d.ts.map +1 -1
- package/dist/NodePath.js +23 -7
- package/dist/NodePath.js.map +1 -1
- package/dist/NodeRuntime.d.ts +26 -7
- package/dist/NodeRuntime.d.ts.map +1 -1
- package/dist/NodeRuntime.js +8 -8
- package/dist/NodeRuntime.js.map +1 -1
- package/dist/NodeSink.d.ts +33 -4
- package/dist/NodeSink.d.ts.map +1 -1
- package/dist/NodeSink.js +31 -4
- package/dist/NodeSink.js.map +1 -1
- package/dist/NodeSocket.d.ts +43 -12
- package/dist/NodeSocket.d.ts.map +1 -1
- package/dist/NodeSocket.js +41 -17
- package/dist/NodeSocket.js.map +1 -1
- package/dist/NodeSocketServer.d.ts +25 -8
- package/dist/NodeSocketServer.d.ts.map +1 -1
- package/dist/NodeSocketServer.js +29 -12
- package/dist/NodeSocketServer.js.map +1 -1
- package/dist/NodeStdio.d.ts +6 -5
- package/dist/NodeStdio.d.ts.map +1 -1
- package/dist/NodeStdio.js +26 -10
- package/dist/NodeStdio.js.map +1 -1
- package/dist/NodeStream.d.ts +76 -20
- package/dist/NodeStream.d.ts.map +1 -1
- package/dist/NodeStream.js +74 -25
- package/dist/NodeStream.js.map +1 -1
- package/dist/NodeTerminal.d.ts +9 -2
- package/dist/NodeTerminal.d.ts.map +1 -1
- package/dist/NodeTerminal.js +13 -3
- package/dist/NodeTerminal.js.map +1 -1
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/utils.js +1 -1
- package/dist/internal/utils.js.map +1 -1
- package/package.json +9 -9
- package/src/NodeChildProcessSpawner.ts +157 -148
- package/src/NodeClusterSocket.ts +22 -8
- package/src/NodeCrypto.ts +60 -0
- package/src/NodeFileSystem.ts +58 -30
- package/src/NodePath.ts +23 -7
- package/src/NodeRuntime.ts +28 -13
- package/src/NodeSink.ts +40 -4
- package/src/NodeSocket.ts +51 -20
- package/src/NodeSocketServer.ts +39 -13
- package/src/NodeStdio.ts +42 -24
- package/src/NodeStream.ts +97 -33
- package/src/NodeTerminal.ts +22 -4
- package/src/index.ts +65 -0
- package/src/internal/utils.ts +4 -4
package/src/NodeStdio.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Shared Node.js implementation of the Effect `Stdio` service.
|
|
3
|
+
*
|
|
4
|
+
* `NodeStdio` provides {@link Stdio.Stdio} from the current Node process. The
|
|
5
|
+
* exported {@link layer} reads command-line arguments from `process.argv`,
|
|
6
|
+
* consumes input from `process.stdin`, and writes normal and error output to
|
|
7
|
+
* `process.stdout` and `process.stderr`. Standard input remains open, and
|
|
8
|
+
* standard output and error output are not ended unless requested.
|
|
9
|
+
*
|
|
10
|
+
* @since 4.0.0
|
|
3
11
|
*/
|
|
12
|
+
import * as Effect from "effect/Effect"
|
|
4
13
|
import * as Layer from "effect/Layer"
|
|
5
14
|
import { systemError } from "effect/PlatformError"
|
|
6
15
|
import * as Stdio from "effect/Stdio"
|
|
@@ -8,39 +17,48 @@ import { fromWritable } from "./NodeSink.ts"
|
|
|
8
17
|
import { fromReadable } from "./NodeStream.ts"
|
|
9
18
|
|
|
10
19
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
20
|
+
* Provides `Stdio` from `process.argv`, `process.stdin`, `process.stdout`,
|
|
21
|
+
* and `process.stderr`; stdin remains open and stdout/stderr are not ended by
|
|
22
|
+
* default.
|
|
23
|
+
*
|
|
24
|
+
* @category layers
|
|
25
|
+
* @since 4.0.0
|
|
13
26
|
*/
|
|
14
27
|
export const layer: Layer.Layer<Stdio.Stdio> = Layer.succeed(
|
|
15
28
|
Stdio.Stdio,
|
|
16
29
|
Stdio.make({
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
args: Effect.sync(() => process.argv.slice(2)),
|
|
31
|
+
stdout: (options) =>
|
|
32
|
+
fromWritable({
|
|
33
|
+
evaluate: () => process.stdout,
|
|
34
|
+
onError: (cause) =>
|
|
35
|
+
systemError({
|
|
36
|
+
module: "Stdio",
|
|
37
|
+
method: "stdout",
|
|
38
|
+
_tag: "Unknown",
|
|
39
|
+
cause
|
|
40
|
+
}),
|
|
41
|
+
endOnDone: options?.endOnDone ?? false
|
|
42
|
+
}),
|
|
43
|
+
stderr: (options) =>
|
|
44
|
+
fromWritable({
|
|
45
|
+
evaluate: () => process.stderr,
|
|
46
|
+
onError: (cause) =>
|
|
47
|
+
systemError({
|
|
48
|
+
module: "Stdio",
|
|
49
|
+
method: "stderr",
|
|
50
|
+
_tag: "Unknown",
|
|
51
|
+
cause
|
|
52
|
+
}),
|
|
53
|
+
endOnDone: options?.endOnDone ?? false
|
|
54
|
+
}),
|
|
37
55
|
stdin: fromReadable({
|
|
38
56
|
evaluate: () => process.stdin,
|
|
39
57
|
onError: (cause) =>
|
|
40
58
|
systemError({
|
|
41
59
|
module: "Stdio",
|
|
42
60
|
method: "stdin",
|
|
43
|
-
|
|
61
|
+
_tag: "Unknown",
|
|
44
62
|
cause
|
|
45
63
|
}),
|
|
46
64
|
closeOnDone: false
|
package/src/NodeStream.ts
CHANGED
|
@@ -1,26 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Adapters between Node streams and Effect streams, channels, and readables.
|
|
3
|
+
*
|
|
4
|
+
* This module is the stream boundary for Node APIs. It wraps `Readable` and
|
|
5
|
+
* `Duplex` values as Effect `Stream`s and `Channel`s, pipes Effect streams
|
|
6
|
+
* through Node duplex streams, exposes an Effect `Stream` back to Node as a
|
|
7
|
+
* `Readable`, and collects readable payloads into strings, array buffers, or
|
|
8
|
+
* `Uint8Array`s with optional byte limits.
|
|
9
|
+
*
|
|
10
|
+
* @since 4.0.0
|
|
3
11
|
*/
|
|
4
12
|
import * as Arr from "effect/Array"
|
|
5
13
|
import * as Cause from "effect/Cause"
|
|
6
14
|
import * as Channel from "effect/Channel"
|
|
15
|
+
import * as Context from "effect/Context"
|
|
7
16
|
import * as Effect from "effect/Effect"
|
|
8
17
|
import * as Exit from "effect/Exit"
|
|
9
18
|
import * as Fiber from "effect/Fiber"
|
|
10
19
|
import type { SizeInput } from "effect/FileSystem"
|
|
11
20
|
import { dual, type LazyArg } from "effect/Function"
|
|
21
|
+
import * as Latch from "effect/Latch"
|
|
12
22
|
import * as MutableRef from "effect/MutableRef"
|
|
13
23
|
import * as Pull from "effect/Pull"
|
|
14
24
|
import * as Scope from "effect/Scope"
|
|
15
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
16
25
|
import * as Stream from "effect/Stream"
|
|
17
26
|
import type { Duplex } from "node:stream"
|
|
18
27
|
import { Readable } from "node:stream"
|
|
19
28
|
import { pullIntoWritable } from "./NodeSink.ts"
|
|
20
29
|
|
|
21
30
|
/**
|
|
31
|
+
* Converts a Node readable stream into an Effect `Stream`, reading chunks with
|
|
32
|
+
* an optional chunk size, mapping stream errors with `onError`, and destroying
|
|
33
|
+
* the readable on completion unless `closeOnDone` is `false`.
|
|
34
|
+
*
|
|
22
35
|
* @category constructors
|
|
23
|
-
* @since
|
|
36
|
+
* @since 4.0.0
|
|
24
37
|
*/
|
|
25
38
|
export const fromReadable = <A = Uint8Array, E = Cause.UnknownError>(options: {
|
|
26
39
|
readonly evaluate: LazyArg<Readable | NodeJS.ReadableStream>
|
|
@@ -31,8 +44,12 @@ export const fromReadable = <A = Uint8Array, E = Cause.UnknownError>(options: {
|
|
|
31
44
|
}): Stream.Stream<A, E> => Stream.fromChannel(fromReadableChannel<A, E>(options))
|
|
32
45
|
|
|
33
46
|
/**
|
|
47
|
+
* Creates a `Channel` that pulls chunks from a Node readable stream, mapping
|
|
48
|
+
* errors with `onError` and destroying the readable on completion unless
|
|
49
|
+
* `closeOnDone` is `false`.
|
|
50
|
+
*
|
|
34
51
|
* @category constructors
|
|
35
|
-
* @since
|
|
52
|
+
* @since 4.0.0
|
|
36
53
|
*/
|
|
37
54
|
export const fromReadableChannel = <A = Uint8Array, E = Cause.UnknownError>(options: {
|
|
38
55
|
readonly evaluate: LazyArg<Readable | NodeJS.ReadableStream>
|
|
@@ -51,8 +68,12 @@ export const fromReadableChannel = <A = Uint8Array, E = Cause.UnknownError>(opti
|
|
|
51
68
|
)
|
|
52
69
|
|
|
53
70
|
/**
|
|
71
|
+
* Creates a `Channel` over a Node `Duplex`, writing upstream chunks with
|
|
72
|
+
* backpressure while emitting chunks read from the duplex and optionally ending
|
|
73
|
+
* the writable side when upstream completes.
|
|
74
|
+
*
|
|
54
75
|
* @category constructors
|
|
55
|
-
* @since
|
|
76
|
+
* @since 4.0.0
|
|
56
77
|
*/
|
|
57
78
|
export const fromDuplex = <IE, I = Uint8Array, O = Uint8Array, E = Cause.UnknownError>(
|
|
58
79
|
options: {
|
|
@@ -94,13 +115,19 @@ export const fromDuplex = <IE, I = Uint8Array, O = Uint8Array, E = Cause.Unknown
|
|
|
94
115
|
})
|
|
95
116
|
|
|
96
117
|
/**
|
|
118
|
+
* Pipes an Effect `Stream` through a Node `Duplex`, writing the stream's
|
|
119
|
+
* chunks to the duplex and emitting chunks read back from it.
|
|
120
|
+
*
|
|
97
121
|
* @category combinators
|
|
98
|
-
* @since
|
|
122
|
+
* @since 4.0.0
|
|
99
123
|
*/
|
|
100
124
|
export const pipeThroughDuplex: {
|
|
101
125
|
/**
|
|
126
|
+
* Pipes an Effect `Stream` through a Node `Duplex`, writing the stream's
|
|
127
|
+
* chunks to the duplex and emitting chunks read back from it.
|
|
128
|
+
*
|
|
102
129
|
* @category combinators
|
|
103
|
-
* @since
|
|
130
|
+
* @since 4.0.0
|
|
104
131
|
*/
|
|
105
132
|
<B = Uint8Array, E2 = Cause.UnknownError>(
|
|
106
133
|
options: {
|
|
@@ -113,8 +140,11 @@ export const pipeThroughDuplex: {
|
|
|
113
140
|
}
|
|
114
141
|
): <R, E, A>(self: Stream.Stream<A, E, R>) => Stream.Stream<B, E2 | E, R>
|
|
115
142
|
/**
|
|
143
|
+
* Pipes an Effect `Stream` through a Node `Duplex`, writing the stream's
|
|
144
|
+
* chunks to the duplex and emitting chunks read back from it.
|
|
145
|
+
*
|
|
116
146
|
* @category combinators
|
|
117
|
-
* @since
|
|
147
|
+
* @since 4.0.0
|
|
118
148
|
*/
|
|
119
149
|
<R, E, A, B = Uint8Array, E2 = Cause.UnknownError>(
|
|
120
150
|
self: Stream.Stream<A, E, R>,
|
|
@@ -144,18 +174,27 @@ export const pipeThroughDuplex: {
|
|
|
144
174
|
))
|
|
145
175
|
|
|
146
176
|
/**
|
|
177
|
+
* Pipes a stream of strings or bytes through a Node `Duplex` using default
|
|
178
|
+
* options and `Cause.UnknownError` for stream failures.
|
|
179
|
+
*
|
|
147
180
|
* @category combinators
|
|
148
|
-
* @since
|
|
181
|
+
* @since 4.0.0
|
|
149
182
|
*/
|
|
150
183
|
export const pipeThroughSimple: {
|
|
151
184
|
/**
|
|
185
|
+
* Pipes a stream of strings or bytes through a Node `Duplex` using default
|
|
186
|
+
* options and `Cause.UnknownError` for stream failures.
|
|
187
|
+
*
|
|
152
188
|
* @category combinators
|
|
153
|
-
* @since
|
|
189
|
+
* @since 4.0.0
|
|
154
190
|
*/
|
|
155
191
|
(duplex: LazyArg<Duplex>): <R, E>(self: Stream.Stream<string | Uint8Array, E, R>) => Stream.Stream<Uint8Array, E | Cause.UnknownError, R>
|
|
156
192
|
/**
|
|
193
|
+
* Pipes a stream of strings or bytes through a Node `Duplex` using default
|
|
194
|
+
* options and `Cause.UnknownError` for stream failures.
|
|
195
|
+
*
|
|
157
196
|
* @category combinators
|
|
158
|
-
* @since
|
|
197
|
+
* @since 4.0.0
|
|
159
198
|
*/
|
|
160
199
|
<R, E>(self: Stream.Stream<string | Uint8Array, E, R>, duplex: LazyArg<Duplex>): Stream.Stream<Uint8Array, Cause.UnknownError | E, R>
|
|
161
200
|
} = dual(2, <R, E>(
|
|
@@ -164,28 +203,39 @@ export const pipeThroughSimple: {
|
|
|
164
203
|
): Stream.Stream<Uint8Array, Cause.UnknownError | E, R> => pipeThroughDuplex(self, { evaluate: duplex }))
|
|
165
204
|
|
|
166
205
|
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
206
|
+
* Converts an Effect `Stream` into a Node `Readable`, using the caller's
|
|
207
|
+
* Effect context to run the stream and destroying the readable if the stream
|
|
208
|
+
* fails.
|
|
209
|
+
*
|
|
210
|
+
* @category converting
|
|
211
|
+
* @since 4.0.0
|
|
169
212
|
*/
|
|
170
213
|
export const toReadable = <E, R>(stream: Stream.Stream<string | Uint8Array, E, R>): Effect.Effect<Readable, never, R> =>
|
|
171
214
|
Effect.map(
|
|
172
|
-
Effect.
|
|
215
|
+
Effect.context<R>(),
|
|
173
216
|
(context) => new StreamAdapter(context, stream)
|
|
174
217
|
)
|
|
175
218
|
|
|
176
219
|
/**
|
|
177
|
-
*
|
|
178
|
-
*
|
|
220
|
+
* Converts a service-free Effect `Stream` into a Node `Readable` using an
|
|
221
|
+
* empty Effect context.
|
|
222
|
+
*
|
|
223
|
+
* @category converting
|
|
224
|
+
* @since 4.0.0
|
|
179
225
|
*/
|
|
180
226
|
export const toReadableNever = <E>(stream: Stream.Stream<string | Uint8Array, E, never>): Readable =>
|
|
181
227
|
new StreamAdapter(
|
|
182
|
-
|
|
228
|
+
Context.empty(),
|
|
183
229
|
stream
|
|
184
230
|
)
|
|
185
231
|
|
|
186
232
|
/**
|
|
187
|
-
*
|
|
188
|
-
*
|
|
233
|
+
* Consumes a Node readable stream into a string using the selected encoding,
|
|
234
|
+
* failing through `onError` on stream errors or when `maxBytes` is exceeded
|
|
235
|
+
* and destroying the stream on interruption or failure.
|
|
236
|
+
*
|
|
237
|
+
* @category converting
|
|
238
|
+
* @since 4.0.0
|
|
189
239
|
*/
|
|
190
240
|
export const toString = <E = Cause.UnknownError>(
|
|
191
241
|
readable: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
@@ -233,8 +283,12 @@ export const toString = <E = Cause.UnknownError>(
|
|
|
233
283
|
}
|
|
234
284
|
|
|
235
285
|
/**
|
|
236
|
-
*
|
|
237
|
-
*
|
|
286
|
+
* Consumes a Node readable stream into an `ArrayBuffer`, failing through
|
|
287
|
+
* `onError` on stream errors or when `maxBytes` is exceeded and destroying the
|
|
288
|
+
* stream on interruption or failure.
|
|
289
|
+
*
|
|
290
|
+
* @category converting
|
|
291
|
+
* @since 4.0.0
|
|
238
292
|
*/
|
|
239
293
|
export const toArrayBuffer = <E = Cause.UnknownError>(
|
|
240
294
|
readable: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
@@ -247,7 +301,7 @@ export const toArrayBuffer = <E = Cause.UnknownError>(
|
|
|
247
301
|
const onError = options?.onError ?? defaultOnError
|
|
248
302
|
return Effect.callback((resume) => {
|
|
249
303
|
const stream = readable() as Readable
|
|
250
|
-
|
|
304
|
+
const buffers: Array<Uint8Array> = []
|
|
251
305
|
let bytes = 0
|
|
252
306
|
stream.once("error", (err) => {
|
|
253
307
|
if ("closed" in stream && !stream.closed) {
|
|
@@ -256,13 +310,16 @@ export const toArrayBuffer = <E = Cause.UnknownError>(
|
|
|
256
310
|
resume(Effect.fail(onError(err) as E))
|
|
257
311
|
})
|
|
258
312
|
stream.once("end", () => {
|
|
259
|
-
|
|
260
|
-
|
|
313
|
+
const buffer = buffers.length === 1 ? buffers[0] : Buffer.concat(buffers)
|
|
314
|
+
if (buffer.byteOffset === 0 && buffer.buffer.byteLength === buffer.byteLength) {
|
|
315
|
+
return resume(Effect.succeed(buffer.buffer as ArrayBuffer))
|
|
261
316
|
}
|
|
262
|
-
resume(
|
|
317
|
+
resume(
|
|
318
|
+
Effect.succeed(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength) as ArrayBuffer)
|
|
319
|
+
)
|
|
263
320
|
})
|
|
264
321
|
stream.on("data", (chunk) => {
|
|
265
|
-
|
|
322
|
+
buffers.push(chunk)
|
|
266
323
|
bytes += chunk.length
|
|
267
324
|
if (maxBytesNumber && bytes > maxBytesNumber) {
|
|
268
325
|
resume(Effect.fail(onError(new Error("maxBytes exceeded")) as E))
|
|
@@ -277,8 +334,11 @@ export const toArrayBuffer = <E = Cause.UnknownError>(
|
|
|
277
334
|
}
|
|
278
335
|
|
|
279
336
|
/**
|
|
280
|
-
*
|
|
281
|
-
*
|
|
337
|
+
* Consumes a Node readable stream into a `Uint8Array`, using the same error
|
|
338
|
+
* mapping and `maxBytes` handling as `toArrayBuffer`.
|
|
339
|
+
*
|
|
340
|
+
* @category converting
|
|
341
|
+
* @since 4.0.0
|
|
282
342
|
*/
|
|
283
343
|
export const toUint8Array = <E = Cause.UnknownError>(
|
|
284
344
|
readable: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
@@ -301,9 +361,10 @@ const readableToPullUnsafe = <A, E>(options: {
|
|
|
301
361
|
readonly closeOnDone?: boolean | undefined
|
|
302
362
|
}) => {
|
|
303
363
|
const readable = options.readable as Readable
|
|
364
|
+
|
|
304
365
|
const closeOnDone = options.closeOnDone ?? true
|
|
305
366
|
const exit = options.exit ?? MutableRef.make(undefined)
|
|
306
|
-
const latch =
|
|
367
|
+
const latch = Latch.makeUnsafe(false)
|
|
307
368
|
function onReadable() {
|
|
308
369
|
latch.openUnsafe()
|
|
309
370
|
}
|
|
@@ -325,6 +386,9 @@ const readableToPullUnsafe = <A, E>(options: {
|
|
|
325
386
|
if (exit.current) {
|
|
326
387
|
return exit.current
|
|
327
388
|
}
|
|
389
|
+
if (readable.readableEnded) {
|
|
390
|
+
return Effect.fail(Cause.Done())
|
|
391
|
+
}
|
|
328
392
|
latch.closeUnsafe()
|
|
329
393
|
return Effect.flatMap(latch.await, loop)
|
|
330
394
|
}
|
|
@@ -354,15 +418,15 @@ const readableToPullUnsafe = <A, E>(options: {
|
|
|
354
418
|
}
|
|
355
419
|
|
|
356
420
|
class StreamAdapter<E, R> extends Readable {
|
|
357
|
-
private readonly readLatch:
|
|
421
|
+
private readonly readLatch: Latch.Latch
|
|
358
422
|
private fiber: Fiber.Fiber<void, E> | undefined = undefined
|
|
359
423
|
|
|
360
424
|
constructor(
|
|
361
|
-
context:
|
|
425
|
+
context: Context.Context<R>,
|
|
362
426
|
stream: Stream.Stream<Uint8Array | string, E, R>
|
|
363
427
|
) {
|
|
364
428
|
super({})
|
|
365
|
-
this.readLatch =
|
|
429
|
+
this.readLatch = Latch.makeUnsafe(false)
|
|
366
430
|
this.fiber = Stream.runForEachArray(stream, (chunk) =>
|
|
367
431
|
this.readLatch.whenOpen(Effect.sync(() => {
|
|
368
432
|
this.readLatch.closeUnsafe()
|
|
@@ -376,7 +440,7 @@ class StreamAdapter<E, R> extends Readable {
|
|
|
376
440
|
}
|
|
377
441
|
}))).pipe(
|
|
378
442
|
this.readLatch.whenOpen,
|
|
379
|
-
Effect.
|
|
443
|
+
Effect.provideContext(context),
|
|
380
444
|
Effect.runFork
|
|
381
445
|
)
|
|
382
446
|
this.fiber.addObserver((exit) => {
|
package/src/NodeTerminal.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Shared Node.js implementation of Effect's `Terminal` service.
|
|
3
|
+
*
|
|
4
|
+
* `NodeTerminal` adapts Node's `readline` APIs plus the current process
|
|
5
|
+
* `stdin` and `stdout` streams into {@link Terminal.Terminal}. The service can
|
|
6
|
+
* display output, read a line, stream key input, and read terminal dimensions.
|
|
7
|
+
* `make` manages readline and TTY raw mode in a scope, while `layer` provides
|
|
8
|
+
* the default service that ends key input on Ctrl+C or Ctrl+D.
|
|
9
|
+
*
|
|
10
|
+
* @since 4.0.0
|
|
3
11
|
*/
|
|
4
12
|
import type * as Cause from "effect/Cause"
|
|
5
13
|
import * as Effect from "effect/Effect"
|
|
6
14
|
import * as Layer from "effect/Layer"
|
|
15
|
+
import * as Option from "effect/Option"
|
|
7
16
|
import { badArgument, type PlatformError } from "effect/PlatformError"
|
|
8
17
|
import * as Predicate from "effect/Predicate"
|
|
9
18
|
import * as Queue from "effect/Queue"
|
|
@@ -13,8 +22,12 @@ import * as Terminal from "effect/Terminal"
|
|
|
13
22
|
import * as readline from "node:readline"
|
|
14
23
|
|
|
15
24
|
/**
|
|
16
|
-
*
|
|
25
|
+
* Creates a scoped process-backed `Terminal` using Node `readline`, enabling
|
|
26
|
+
* TTY raw mode while in scope and using the supplied predicate to decide when
|
|
27
|
+
* key input should end.
|
|
28
|
+
*
|
|
17
29
|
* @category constructors
|
|
30
|
+
* @since 4.0.0
|
|
18
31
|
*/
|
|
19
32
|
export const make: (
|
|
20
33
|
shouldQuit?: (input: Terminal.UserInput) => boolean
|
|
@@ -46,13 +59,14 @@ export const make: (
|
|
|
46
59
|
})
|
|
47
60
|
|
|
48
61
|
const columns = Effect.sync(() => stdout.columns ?? 0)
|
|
62
|
+
const rows = Effect.sync(() => stdout.rows ?? 0)
|
|
49
63
|
|
|
50
64
|
const readInput = Effect.gen(function*() {
|
|
51
65
|
yield* RcRef.get(rlRef)
|
|
52
66
|
const queue = yield* Queue.make<Terminal.UserInput, Cause.Done>()
|
|
53
67
|
const handleKeypress = (s: string | undefined, k: readline.Key) => {
|
|
54
68
|
const userInput = {
|
|
55
|
-
input: s,
|
|
69
|
+
input: Option.fromUndefinedOr(s),
|
|
56
70
|
key: { name: k.name ?? "", ctrl: !!k.ctrl, meta: !!k.meta, shift: !!k.shift }
|
|
57
71
|
}
|
|
58
72
|
Queue.offerUnsafe(queue, userInput)
|
|
@@ -93,6 +107,7 @@ export const make: (
|
|
|
93
107
|
|
|
94
108
|
return Terminal.make({
|
|
95
109
|
columns,
|
|
110
|
+
rows,
|
|
96
111
|
readInput,
|
|
97
112
|
readLine,
|
|
98
113
|
display
|
|
@@ -101,8 +116,11 @@ export const make: (
|
|
|
101
116
|
)
|
|
102
117
|
|
|
103
118
|
/**
|
|
104
|
-
*
|
|
119
|
+
* Provides the default process-backed `Terminal` service, ending key input on
|
|
120
|
+
* Ctrl+C or Ctrl+D.
|
|
121
|
+
*
|
|
105
122
|
* @category layers
|
|
123
|
+
* @since 4.0.0
|
|
106
124
|
*/
|
|
107
125
|
export const layer: Layer.Layer<Terminal.Terminal> = Layer.effect(Terminal.Terminal, make(defaultShouldQuit))
|
|
108
126
|
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 4.0.0
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// @barrel: Auto-generated exports. Do not edit manually.
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @since 4.0.0
|
|
9
|
+
*/
|
|
10
|
+
export * as NodeChildProcessSpawner from "./NodeChildProcessSpawner.ts"
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @since 4.0.0
|
|
14
|
+
*/
|
|
15
|
+
export * as NodeClusterSocket from "./NodeClusterSocket.ts"
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @since 1.0.0
|
|
19
|
+
*/
|
|
20
|
+
export * as NodeCrypto from "./NodeCrypto.ts"
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @since 4.0.0
|
|
24
|
+
*/
|
|
25
|
+
export * as NodeFileSystem from "./NodeFileSystem.ts"
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @since 4.0.0
|
|
29
|
+
*/
|
|
30
|
+
export * as NodePath from "./NodePath.ts"
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @since 4.0.0
|
|
34
|
+
*/
|
|
35
|
+
export * as NodeRuntime from "./NodeRuntime.ts"
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @since 4.0.0
|
|
39
|
+
*/
|
|
40
|
+
export * as NodeSink from "./NodeSink.ts"
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @since 4.0.0
|
|
44
|
+
*/
|
|
45
|
+
export * as NodeSocket from "./NodeSocket.ts"
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @since 4.0.0
|
|
49
|
+
*/
|
|
50
|
+
export * as NodeSocketServer from "./NodeSocketServer.ts"
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @since 4.0.0
|
|
54
|
+
*/
|
|
55
|
+
export * as NodeStdio from "./NodeStdio.ts"
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @since 4.0.0
|
|
59
|
+
*/
|
|
60
|
+
export * as NodeStream from "./NodeStream.ts"
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @since 4.0.0
|
|
64
|
+
*/
|
|
65
|
+
export * as NodeTerminal from "./NodeTerminal.ts"
|
package/src/internal/utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SystemError,
|
|
1
|
+
import type { SystemError, SystemErrorTag } from "effect/PlatformError"
|
|
2
2
|
import * as PlatformError from "effect/PlatformError"
|
|
3
3
|
import type { PathLike } from "node:fs"
|
|
4
4
|
|
|
@@ -6,9 +6,9 @@ import type { PathLike } from "node:fs"
|
|
|
6
6
|
export const handleErrnoException = (module: SystemError["module"], method: string) =>
|
|
7
7
|
(
|
|
8
8
|
err: NodeJS.ErrnoException,
|
|
9
|
-
[path]: [path: PathLike | number, ...args: Array<any>]
|
|
9
|
+
[path]: [path: PathLike | number | string | readonly string[], ...args: Array<any>]
|
|
10
10
|
): PlatformError.PlatformError => {
|
|
11
|
-
let reason:
|
|
11
|
+
let reason: SystemErrorTag = "Unknown"
|
|
12
12
|
|
|
13
13
|
switch (err.code) {
|
|
14
14
|
case "ENOENT":
|
|
@@ -41,7 +41,7 @@ export const handleErrnoException = (module: SystemError["module"], method: stri
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
return PlatformError.systemError({
|
|
44
|
-
|
|
44
|
+
_tag: reason,
|
|
45
45
|
module,
|
|
46
46
|
method,
|
|
47
47
|
pathOrDescriptor: path as string | number,
|