@effect/platform-node-shared 0.57.0 → 4.0.0-beta.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/README.md +3 -3
- package/dist/NodeChildProcessSpawner.d.ts +37 -0
- package/dist/NodeChildProcessSpawner.d.ts.map +1 -0
- package/dist/NodeChildProcessSpawner.js +567 -0
- package/dist/NodeChildProcessSpawner.js.map +1 -0
- package/dist/{dts/NodeClusterSocket.d.ts → NodeClusterSocket.d.ts} +4 -7
- package/dist/NodeClusterSocket.d.ts.map +1 -0
- package/dist/{esm/NodeClusterSocket.js → NodeClusterSocket.js} +9 -10
- package/dist/NodeClusterSocket.js.map +1 -0
- package/dist/NodeFileSystem.d.ts +8 -0
- package/dist/NodeFileSystem.d.ts.map +1 -0
- package/dist/{esm/internal/fileSystem.js → NodeFileSystem.js} +125 -96
- package/dist/NodeFileSystem.js.map +1 -0
- package/dist/NodePath.d.ts +18 -0
- package/dist/NodePath.d.ts.map +1 -0
- package/dist/NodePath.js +56 -0
- package/dist/NodePath.js.map +1 -0
- package/dist/NodeRuntime.d.ts +28 -0
- package/dist/NodeRuntime.d.ts.map +1 -0
- package/dist/{esm/internal/runtime.js → NodeRuntime.js} +8 -8
- package/dist/NodeRuntime.js.map +1 -0
- package/dist/NodeSink.d.ts +40 -0
- package/dist/NodeSink.d.ts.map +1 -0
- package/dist/NodeSink.js +50 -0
- package/dist/NodeSink.js.map +1 -0
- package/dist/{dts/NodeSocket.d.ts → NodeSocket.d.ts} +10 -10
- package/dist/NodeSocket.d.ts.map +1 -0
- package/dist/{esm/NodeSocket.js → NodeSocket.js} +51 -39
- package/dist/NodeSocket.js.map +1 -0
- package/dist/{dts/NodeSocketServer.d.ts → NodeSocketServer.d.ts} +8 -10
- package/dist/NodeSocketServer.d.ts.map +1 -0
- package/dist/NodeSocketServer.js +192 -0
- package/dist/NodeSocketServer.js.map +1 -0
- package/dist/NodeStdio.d.ts +11 -0
- package/dist/NodeStdio.d.ts.map +1 -0
- package/dist/NodeStdio.js +43 -0
- package/dist/NodeStdio.js.map +1 -0
- package/dist/NodeStream.d.ts +127 -0
- package/dist/NodeStream.d.ts.map +1 -0
- package/dist/NodeStream.js +249 -0
- package/dist/NodeStream.js.map +1 -0
- package/dist/NodeTerminal.d.ts +15 -0
- package/dist/NodeTerminal.d.ts.map +1 -0
- package/dist/{esm/internal/terminal.js → NodeTerminal.js} +28 -21
- package/dist/NodeTerminal.js.map +1 -0
- package/dist/internal/utils.d.ts +2 -0
- package/dist/internal/utils.d.ts.map +1 -0
- package/dist/{esm/internal/error.js → internal/utils.js} +4 -5
- package/dist/internal/utils.js.map +1 -0
- package/package.json +53 -124
- package/src/NodeChildProcessSpawner.ts +713 -0
- package/src/NodeClusterSocket.ts +12 -13
- package/src/NodeFileSystem.ts +632 -5
- package/src/NodePath.ts +48 -9
- package/src/NodeRuntime.ts +53 -4
- package/src/NodeSink.ts +65 -62
- package/src/NodeSocket.ts +65 -49
- package/src/NodeSocketServer.ts +108 -88
- package/src/NodeStdio.ts +49 -0
- package/src/NodeStream.ts +324 -83
- package/src/NodeTerminal.ts +100 -9
- package/src/internal/{error.ts → utils.ts} +6 -7
- package/NodeClusterSocket/package.json +0 -6
- package/NodeCommandExecutor/package.json +0 -6
- package/NodeFileSystem/ParcelWatcher/package.json +0 -6
- package/NodeFileSystem/package.json +0 -6
- package/NodeKeyValueStore/package.json +0 -6
- package/NodeMultipart/package.json +0 -6
- package/NodePath/package.json +0 -6
- package/NodeRuntime/package.json +0 -6
- package/NodeSink/package.json +0 -6
- package/NodeSocket/package.json +0 -6
- package/NodeSocketServer/package.json +0 -6
- package/NodeStream/package.json +0 -6
- package/NodeTerminal/package.json +0 -6
- package/dist/cjs/NodeClusterSocket.js +0 -50
- package/dist/cjs/NodeClusterSocket.js.map +0 -1
- package/dist/cjs/NodeCommandExecutor.js +0 -14
- package/dist/cjs/NodeCommandExecutor.js.map +0 -1
- package/dist/cjs/NodeFileSystem/ParcelWatcher.js +0 -20
- package/dist/cjs/NodeFileSystem/ParcelWatcher.js.map +0 -1
- package/dist/cjs/NodeFileSystem.js +0 -18
- package/dist/cjs/NodeFileSystem.js.map +0 -1
- package/dist/cjs/NodeKeyValueStore.js +0 -18
- package/dist/cjs/NodeKeyValueStore.js.map +0 -1
- package/dist/cjs/NodeMultipart.js +0 -24
- package/dist/cjs/NodeMultipart.js.map +0 -1
- package/dist/cjs/NodePath.js +0 -28
- package/dist/cjs/NodePath.js.map +0 -1
- package/dist/cjs/NodeRuntime.js +0 -14
- package/dist/cjs/NodeRuntime.js.map +0 -1
- package/dist/cjs/NodeSink.js +0 -50
- package/dist/cjs/NodeSink.js.map +0 -1
- package/dist/cjs/NodeSocket.js +0 -153
- package/dist/cjs/NodeSocket.js.map +0 -1
- package/dist/cjs/NodeSocketServer.js +0 -178
- package/dist/cjs/NodeSocketServer.js.map +0 -1
- package/dist/cjs/NodeStream.js +0 -76
- package/dist/cjs/NodeStream.js.map +0 -1
- package/dist/cjs/NodeTerminal.js +0 -19
- package/dist/cjs/NodeTerminal.js.map +0 -1
- package/dist/cjs/internal/commandExecutor.js +0 -153
- package/dist/cjs/internal/commandExecutor.js.map +0 -1
- package/dist/cjs/internal/error.js +0 -45
- package/dist/cjs/internal/error.js.map +0 -1
- package/dist/cjs/internal/fileSystem/parcelWatcher.js +0 -68
- package/dist/cjs/internal/fileSystem/parcelWatcher.js.map +0 -1
- package/dist/cjs/internal/fileSystem.js +0 -400
- package/dist/cjs/internal/fileSystem.js.map +0 -1
- package/dist/cjs/internal/multipart.js +0 -147
- package/dist/cjs/internal/multipart.js.map +0 -1
- package/dist/cjs/internal/path.js +0 -53
- package/dist/cjs/internal/path.js.map +0 -1
- package/dist/cjs/internal/runtime.js +0 -37
- package/dist/cjs/internal/runtime.js.map +0 -1
- package/dist/cjs/internal/sink.js +0 -28
- package/dist/cjs/internal/sink.js.map +0 -1
- package/dist/cjs/internal/stream.js +0 -233
- package/dist/cjs/internal/stream.js.map +0 -1
- package/dist/cjs/internal/terminal.js +0 -86
- package/dist/cjs/internal/terminal.js.map +0 -1
- package/dist/dts/NodeClusterSocket.d.ts.map +0 -1
- package/dist/dts/NodeCommandExecutor.d.ts +0 -12
- package/dist/dts/NodeCommandExecutor.d.ts.map +0 -1
- package/dist/dts/NodeFileSystem/ParcelWatcher.d.ts +0 -13
- package/dist/dts/NodeFileSystem/ParcelWatcher.d.ts.map +0 -1
- package/dist/dts/NodeFileSystem.d.ts +0 -11
- package/dist/dts/NodeFileSystem.d.ts.map +0 -1
- package/dist/dts/NodeKeyValueStore.d.ts +0 -12
- package/dist/dts/NodeKeyValueStore.d.ts.map +0 -1
- package/dist/dts/NodeMultipart.d.ts +0 -27
- package/dist/dts/NodeMultipart.d.ts.map +0 -1
- package/dist/dts/NodePath.d.ts +0 -21
- package/dist/dts/NodePath.d.ts.map +0 -1
- package/dist/dts/NodeRuntime.d.ts +0 -10
- package/dist/dts/NodeRuntime.d.ts.map +0 -1
- package/dist/dts/NodeSink.d.ts +0 -36
- package/dist/dts/NodeSink.d.ts.map +0 -1
- package/dist/dts/NodeSocket.d.ts.map +0 -1
- package/dist/dts/NodeSocketServer.d.ts.map +0 -1
- package/dist/dts/NodeStream.d.ts +0 -119
- package/dist/dts/NodeStream.d.ts.map +0 -1
- package/dist/dts/NodeTerminal.d.ts +0 -18
- package/dist/dts/NodeTerminal.d.ts.map +0 -1
- package/dist/dts/internal/commandExecutor.d.ts +0 -2
- package/dist/dts/internal/commandExecutor.d.ts.map +0 -1
- package/dist/dts/internal/error.d.ts +0 -2
- package/dist/dts/internal/error.d.ts.map +0 -1
- package/dist/dts/internal/fileSystem/parcelWatcher.d.ts +0 -4
- package/dist/dts/internal/fileSystem/parcelWatcher.d.ts.map +0 -1
- package/dist/dts/internal/fileSystem.d.ts +0 -2
- package/dist/dts/internal/fileSystem.d.ts.map +0 -1
- package/dist/dts/internal/multipart.d.ts +0 -2
- package/dist/dts/internal/multipart.d.ts.map +0 -1
- package/dist/dts/internal/path.d.ts +0 -2
- package/dist/dts/internal/path.d.ts.map +0 -1
- package/dist/dts/internal/runtime.d.ts +0 -2
- package/dist/dts/internal/runtime.d.ts.map +0 -1
- package/dist/dts/internal/sink.d.ts +0 -2
- package/dist/dts/internal/sink.d.ts.map +0 -1
- package/dist/dts/internal/stream.d.ts +0 -2
- package/dist/dts/internal/stream.d.ts.map +0 -1
- package/dist/dts/internal/terminal.d.ts +0 -2
- package/dist/dts/internal/terminal.d.ts.map +0 -1
- package/dist/esm/NodeClusterSocket.js.map +0 -1
- package/dist/esm/NodeCommandExecutor.js +0 -7
- package/dist/esm/NodeCommandExecutor.js.map +0 -1
- package/dist/esm/NodeFileSystem/ParcelWatcher.js +0 -12
- package/dist/esm/NodeFileSystem/ParcelWatcher.js.map +0 -1
- package/dist/esm/NodeFileSystem.js +0 -10
- package/dist/esm/NodeFileSystem.js.map +0 -1
- package/dist/esm/NodeKeyValueStore.js +0 -10
- package/dist/esm/NodeKeyValueStore.js.map +0 -1
- package/dist/esm/NodeMultipart.js +0 -17
- package/dist/esm/NodeMultipart.js.map +0 -1
- package/dist/esm/NodePath.js +0 -20
- package/dist/esm/NodePath.js.map +0 -1
- package/dist/esm/NodeRuntime.js +0 -7
- package/dist/esm/NodeRuntime.js.map +0 -1
- package/dist/esm/NodeSink.js +0 -43
- package/dist/esm/NodeSink.js.map +0 -1
- package/dist/esm/NodeSocket.js.map +0 -1
- package/dist/esm/NodeSocketServer.js +0 -167
- package/dist/esm/NodeSocketServer.js.map +0 -1
- package/dist/esm/NodeStream.js +0 -69
- package/dist/esm/NodeStream.js.map +0 -1
- package/dist/esm/NodeTerminal.js +0 -12
- package/dist/esm/NodeTerminal.js.map +0 -1
- package/dist/esm/internal/commandExecutor.js +0 -146
- package/dist/esm/internal/commandExecutor.js.map +0 -1
- package/dist/esm/internal/error.js.map +0 -1
- package/dist/esm/internal/fileSystem/parcelWatcher.js +0 -61
- package/dist/esm/internal/fileSystem/parcelWatcher.js.map +0 -1
- package/dist/esm/internal/fileSystem.js.map +0 -1
- package/dist/esm/internal/multipart.js +0 -137
- package/dist/esm/internal/multipart.js.map +0 -1
- package/dist/esm/internal/path.js +0 -46
- package/dist/esm/internal/path.js.map +0 -1
- package/dist/esm/internal/runtime.js.map +0 -1
- package/dist/esm/internal/sink.js +0 -19
- package/dist/esm/internal/sink.js.map +0 -1
- package/dist/esm/internal/stream.js +0 -217
- package/dist/esm/internal/stream.js.map +0 -1
- package/dist/esm/internal/terminal.js.map +0 -1
- package/dist/esm/package.json +0 -4
- package/src/NodeCommandExecutor.ts +0 -13
- package/src/NodeFileSystem/ParcelWatcher.ts +0 -15
- package/src/NodeKeyValueStore.ts +0 -20
- package/src/NodeMultipart.ts +0 -40
- package/src/internal/commandExecutor.ts +0 -251
- package/src/internal/fileSystem/parcelWatcher.ts +0 -64
- package/src/internal/fileSystem.ts +0 -648
- package/src/internal/multipart.ts +0 -141
- package/src/internal/path.ts +0 -63
- package/src/internal/runtime.ts +0 -34
- package/src/internal/sink.ts +0 -57
- package/src/internal/stream.ts +0 -375
- package/src/internal/terminal.ts +0 -100
package/src/NodeStream.ts
CHANGED
|
@@ -1,65 +1,97 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @since 1.0.0
|
|
3
3
|
*/
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
4
|
+
import * as Arr from "effect/Array"
|
|
5
|
+
import * as Cause from "effect/Cause"
|
|
6
|
+
import * as Channel from "effect/Channel"
|
|
7
|
+
import * as Effect from "effect/Effect"
|
|
8
|
+
import * as Exit from "effect/Exit"
|
|
9
|
+
import * as Fiber from "effect/Fiber"
|
|
10
|
+
import type { SizeInput } from "effect/FileSystem"
|
|
11
|
+
import { dual, type LazyArg } from "effect/Function"
|
|
12
|
+
import * as MutableRef from "effect/MutableRef"
|
|
13
|
+
import * as Pull from "effect/Pull"
|
|
14
|
+
import * as Scope from "effect/Scope"
|
|
15
|
+
import * as ServiceMap from "effect/ServiceMap"
|
|
10
16
|
import * as Stream from "effect/Stream"
|
|
11
|
-
import type { Duplex
|
|
12
|
-
import
|
|
17
|
+
import type { Duplex } from "node:stream"
|
|
18
|
+
import { Readable } from "node:stream"
|
|
19
|
+
import { pullIntoWritable } from "./NodeSink.ts"
|
|
13
20
|
|
|
14
21
|
/**
|
|
15
|
-
* @category
|
|
22
|
+
* @category constructors
|
|
16
23
|
* @since 1.0.0
|
|
17
24
|
*/
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
readonly
|
|
21
|
-
|
|
25
|
+
export const fromReadable = <A = Uint8Array, E = Cause.UnknownError>(options: {
|
|
26
|
+
readonly evaluate: LazyArg<Readable | NodeJS.ReadableStream>
|
|
27
|
+
readonly onError?: (error: unknown) => E
|
|
28
|
+
readonly chunkSize?: number | undefined
|
|
29
|
+
readonly bufferSize?: number | undefined
|
|
22
30
|
readonly closeOnDone?: boolean | undefined
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @category model
|
|
27
|
-
* @since 1.0.0
|
|
28
|
-
*/
|
|
29
|
-
export interface FromWritableOptions {
|
|
30
|
-
readonly endOnDone?: boolean
|
|
31
|
-
readonly encoding?: BufferEncoding
|
|
32
|
-
}
|
|
31
|
+
}): Stream.Stream<A, E> => Stream.fromChannel(fromReadableChannel<A, E>(options))
|
|
33
32
|
|
|
34
33
|
/**
|
|
35
34
|
* @category constructors
|
|
36
35
|
* @since 1.0.0
|
|
37
36
|
*/
|
|
38
|
-
export const
|
|
39
|
-
evaluate: LazyArg<Readable | NodeJS.ReadableStream
|
|
40
|
-
onError
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
export const fromReadableChannel = <A = Uint8Array, E = Cause.UnknownError>(options: {
|
|
38
|
+
readonly evaluate: LazyArg<Readable | NodeJS.ReadableStream>
|
|
39
|
+
readonly onError?: (error: unknown) => E
|
|
40
|
+
readonly chunkSize?: number | undefined
|
|
41
|
+
readonly closeOnDone?: boolean | undefined
|
|
42
|
+
}): Channel.Channel<Arr.NonEmptyReadonlyArray<A>, E> =>
|
|
43
|
+
Channel.fromTransform((_, scope) =>
|
|
44
|
+
readableToPullUnsafe({
|
|
45
|
+
scope,
|
|
46
|
+
readable: options.evaluate(),
|
|
47
|
+
onError: options.onError ?? defaultOnError as any,
|
|
48
|
+
chunkSize: options.chunkSize,
|
|
49
|
+
closeOnDone: options.closeOnDone
|
|
50
|
+
})
|
|
51
|
+
)
|
|
43
52
|
|
|
44
53
|
/**
|
|
45
54
|
* @category constructors
|
|
46
55
|
* @since 1.0.0
|
|
47
56
|
*/
|
|
48
|
-
export const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
export const fromDuplex = <IE, I = Uint8Array, O = Uint8Array, E = Cause.UnknownError>(
|
|
58
|
+
options: {
|
|
59
|
+
readonly evaluate: LazyArg<Duplex>
|
|
60
|
+
readonly onError?: (error: unknown) => E
|
|
61
|
+
readonly chunkSize?: number | undefined
|
|
62
|
+
readonly bufferSize?: number | undefined
|
|
63
|
+
readonly endOnDone?: boolean | undefined
|
|
64
|
+
readonly encoding?: BufferEncoding | undefined
|
|
65
|
+
}
|
|
66
|
+
): Channel.Channel<Arr.NonEmptyReadonlyArray<O>, IE | E, void, Arr.NonEmptyReadonlyArray<I>, IE> =>
|
|
67
|
+
Channel.fromTransform((upstream, scope) => {
|
|
68
|
+
const duplex = options.evaluate()
|
|
69
|
+
const exit = MutableRef.make<Exit.Exit<never, IE | E | Cause.Done> | undefined>(undefined)
|
|
53
70
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
)
|
|
71
|
+
return pullIntoWritable({
|
|
72
|
+
pull: upstream,
|
|
73
|
+
writable: duplex,
|
|
74
|
+
onError: options.onError ?? defaultOnError as any,
|
|
75
|
+
endOnDone: options.endOnDone,
|
|
76
|
+
encoding: options.encoding
|
|
77
|
+
}).pipe(
|
|
78
|
+
Effect.catchCause((cause) => {
|
|
79
|
+
if (Pull.isDoneCause(cause)) return Effect.void
|
|
80
|
+
exit.current = Exit.failCause(cause as Cause.Cause<IE | E | Cause.Done>)
|
|
81
|
+
return Effect.void
|
|
82
|
+
}),
|
|
83
|
+
Effect.forkIn(scope),
|
|
84
|
+
Effect.flatMap(() =>
|
|
85
|
+
readableToPullUnsafe({
|
|
86
|
+
scope,
|
|
87
|
+
exit,
|
|
88
|
+
readable: duplex,
|
|
89
|
+
onError: options.onError ?? defaultOnError as any,
|
|
90
|
+
chunkSize: options.chunkSize
|
|
91
|
+
})
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
})
|
|
63
95
|
|
|
64
96
|
/**
|
|
65
97
|
* @category combinators
|
|
@@ -70,22 +102,46 @@ export const pipeThroughDuplex: {
|
|
|
70
102
|
* @category combinators
|
|
71
103
|
* @since 1.0.0
|
|
72
104
|
*/
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
105
|
+
<B = Uint8Array, E2 = Cause.UnknownError>(
|
|
106
|
+
options: {
|
|
107
|
+
readonly evaluate: LazyArg<Duplex>
|
|
108
|
+
readonly onError?: (error: unknown) => E2
|
|
109
|
+
readonly chunkSize?: number | undefined
|
|
110
|
+
readonly bufferSize?: number | undefined
|
|
111
|
+
readonly endOnDone?: boolean | undefined
|
|
112
|
+
readonly encoding?: BufferEncoding | undefined
|
|
113
|
+
}
|
|
77
114
|
): <R, E, A>(self: Stream.Stream<A, E, R>) => Stream.Stream<B, E2 | E, R>
|
|
78
115
|
/**
|
|
79
116
|
* @category combinators
|
|
80
117
|
* @since 1.0.0
|
|
81
118
|
*/
|
|
82
|
-
<R, E, A,
|
|
119
|
+
<R, E, A, B = Uint8Array, E2 = Cause.UnknownError>(
|
|
83
120
|
self: Stream.Stream<A, E, R>,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
121
|
+
options: {
|
|
122
|
+
readonly evaluate: LazyArg<Duplex>
|
|
123
|
+
readonly onError?: (error: unknown) => E2
|
|
124
|
+
readonly chunkSize?: number | undefined
|
|
125
|
+
readonly bufferSize?: number | undefined
|
|
126
|
+
readonly endOnDone?: boolean | undefined
|
|
127
|
+
readonly encoding?: BufferEncoding | undefined
|
|
128
|
+
}
|
|
87
129
|
): Stream.Stream<B, E | E2, R>
|
|
88
|
-
} =
|
|
130
|
+
} = dual(2, <R, E, A, B = Uint8Array, E2 = Cause.UnknownError>(
|
|
131
|
+
self: Stream.Stream<A, E, R>,
|
|
132
|
+
options: {
|
|
133
|
+
readonly evaluate: LazyArg<Duplex>
|
|
134
|
+
readonly onError?: (error: unknown) => E2
|
|
135
|
+
readonly chunkSize?: number | undefined
|
|
136
|
+
readonly bufferSize?: number | undefined
|
|
137
|
+
readonly endOnDone?: boolean | undefined
|
|
138
|
+
readonly encoding?: BufferEncoding | undefined
|
|
139
|
+
}
|
|
140
|
+
): Stream.Stream<B, E | E2, R> =>
|
|
141
|
+
Stream.pipeThroughChannelOrFail(
|
|
142
|
+
self,
|
|
143
|
+
fromDuplex(options)
|
|
144
|
+
))
|
|
89
145
|
|
|
90
146
|
/**
|
|
91
147
|
* @category combinators
|
|
@@ -96,70 +152,255 @@ export const pipeThroughSimple: {
|
|
|
96
152
|
* @category combinators
|
|
97
153
|
* @since 1.0.0
|
|
98
154
|
*/
|
|
99
|
-
(duplex: LazyArg<Duplex>): <R, E>(self: Stream.Stream<string | Uint8Array, E, R>) => Stream.Stream<Uint8Array, E |
|
|
155
|
+
(duplex: LazyArg<Duplex>): <R, E>(self: Stream.Stream<string | Uint8Array, E, R>) => Stream.Stream<Uint8Array, E | Cause.UnknownError, R>
|
|
100
156
|
/**
|
|
101
157
|
* @category combinators
|
|
102
158
|
* @since 1.0.0
|
|
103
159
|
*/
|
|
104
|
-
<R, E>(self: Stream.Stream<string | Uint8Array, E, R>, duplex: LazyArg<Duplex>): Stream.Stream<Uint8Array,
|
|
105
|
-
} =
|
|
160
|
+
<R, E>(self: Stream.Stream<string | Uint8Array, E, R>, duplex: LazyArg<Duplex>): Stream.Stream<Uint8Array, Cause.UnknownError | E, R>
|
|
161
|
+
} = dual(2, <R, E>(
|
|
162
|
+
self: Stream.Stream<string | Uint8Array, E, R>,
|
|
163
|
+
duplex: LazyArg<Duplex>
|
|
164
|
+
): Stream.Stream<Uint8Array, Cause.UnknownError | E, R> => pipeThroughDuplex(self, { evaluate: duplex }))
|
|
106
165
|
|
|
107
166
|
/**
|
|
108
167
|
* @since 1.0.0
|
|
109
168
|
* @category conversions
|
|
110
169
|
*/
|
|
111
|
-
export const toReadable
|
|
112
|
-
|
|
170
|
+
export const toReadable = <E, R>(stream: Stream.Stream<string | Uint8Array, E, R>): Effect.Effect<Readable, never, R> =>
|
|
171
|
+
Effect.map(
|
|
172
|
+
Effect.services<R>(),
|
|
173
|
+
(context) => new StreamAdapter(context, stream)
|
|
174
|
+
)
|
|
113
175
|
|
|
114
176
|
/**
|
|
115
177
|
* @since 1.0.0
|
|
116
178
|
* @category conversions
|
|
117
179
|
*/
|
|
118
|
-
export const toReadableNever
|
|
119
|
-
|
|
180
|
+
export const toReadableNever = <E>(stream: Stream.Stream<string | Uint8Array, E, never>): Readable =>
|
|
181
|
+
new StreamAdapter(
|
|
182
|
+
ServiceMap.empty(),
|
|
183
|
+
stream
|
|
184
|
+
)
|
|
120
185
|
|
|
121
186
|
/**
|
|
122
187
|
* @since 1.0.0
|
|
123
188
|
* @category conversions
|
|
124
189
|
*/
|
|
125
|
-
export const toString
|
|
190
|
+
export const toString = <E = Cause.UnknownError>(
|
|
126
191
|
readable: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
127
|
-
options
|
|
128
|
-
readonly
|
|
192
|
+
options?: {
|
|
193
|
+
readonly onError?: (error: unknown) => E
|
|
129
194
|
readonly encoding?: BufferEncoding | undefined
|
|
130
195
|
readonly maxBytes?: SizeInput | undefined
|
|
131
196
|
}
|
|
132
|
-
)
|
|
197
|
+
): Effect.Effect<string, E> => {
|
|
198
|
+
const maxBytesNumber = options?.maxBytes ? Number(options.maxBytes) : undefined
|
|
199
|
+
const onError = options?.onError ?? defaultOnError
|
|
200
|
+
const encoding = options?.encoding ?? "utf8"
|
|
201
|
+
return Effect.callback((resume) => {
|
|
202
|
+
const stream = readable() as Readable
|
|
203
|
+
stream.setEncoding(encoding)
|
|
204
|
+
|
|
205
|
+
stream.once("error", (err) => {
|
|
206
|
+
if ("closed" in stream && !stream.closed) {
|
|
207
|
+
stream.destroy()
|
|
208
|
+
}
|
|
209
|
+
resume(Effect.fail(onError(err) as E))
|
|
210
|
+
})
|
|
211
|
+
stream.once("error", (err) => {
|
|
212
|
+
resume(Effect.fail(onError(err) as E))
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
let string = ""
|
|
216
|
+
let bytes = 0
|
|
217
|
+
stream.once("end", () => {
|
|
218
|
+
resume(Effect.succeed(string))
|
|
219
|
+
})
|
|
220
|
+
stream.on("data", (chunk) => {
|
|
221
|
+
string += chunk
|
|
222
|
+
bytes += Buffer.byteLength(chunk)
|
|
223
|
+
if (maxBytesNumber && bytes > maxBytesNumber) {
|
|
224
|
+
resume(Effect.fail(onError(new Error("maxBytes exceeded")) as E))
|
|
225
|
+
}
|
|
226
|
+
})
|
|
227
|
+
return Effect.sync(() => {
|
|
228
|
+
if ("closed" in stream && !stream.closed) {
|
|
229
|
+
stream.destroy()
|
|
230
|
+
}
|
|
231
|
+
})
|
|
232
|
+
})
|
|
233
|
+
}
|
|
133
234
|
|
|
134
235
|
/**
|
|
135
236
|
* @since 1.0.0
|
|
136
237
|
* @category conversions
|
|
137
238
|
*/
|
|
138
|
-
export const
|
|
239
|
+
export const toArrayBuffer = <E = Cause.UnknownError>(
|
|
139
240
|
readable: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
140
|
-
options
|
|
141
|
-
) =>
|
|
241
|
+
options?: {
|
|
242
|
+
readonly onError?: (error: unknown) => E
|
|
243
|
+
readonly maxBytes?: SizeInput | undefined
|
|
244
|
+
}
|
|
245
|
+
): Effect.Effect<ArrayBuffer, E> => {
|
|
246
|
+
const maxBytesNumber = options?.maxBytes ? Number(options.maxBytes) : undefined
|
|
247
|
+
const onError = options?.onError ?? defaultOnError
|
|
248
|
+
return Effect.callback((resume) => {
|
|
249
|
+
const stream = readable() as Readable
|
|
250
|
+
let buffer = Buffer.alloc(0)
|
|
251
|
+
let bytes = 0
|
|
252
|
+
stream.once("error", (err) => {
|
|
253
|
+
if ("closed" in stream && !stream.closed) {
|
|
254
|
+
stream.destroy()
|
|
255
|
+
}
|
|
256
|
+
resume(Effect.fail(onError(err) as E))
|
|
257
|
+
})
|
|
258
|
+
stream.once("end", () => {
|
|
259
|
+
if (buffer.buffer.byteLength === buffer.byteLength) {
|
|
260
|
+
return resume(Effect.succeed(buffer.buffer))
|
|
261
|
+
}
|
|
262
|
+
resume(Effect.succeed(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength)))
|
|
263
|
+
})
|
|
264
|
+
stream.on("data", (chunk) => {
|
|
265
|
+
buffer = Buffer.concat([buffer, chunk])
|
|
266
|
+
bytes += chunk.length
|
|
267
|
+
if (maxBytesNumber && bytes > maxBytesNumber) {
|
|
268
|
+
resume(Effect.fail(onError(new Error("maxBytes exceeded")) as E))
|
|
269
|
+
}
|
|
270
|
+
})
|
|
271
|
+
return Effect.sync(() => {
|
|
272
|
+
if ("closed" in stream && !stream.closed) {
|
|
273
|
+
stream.destroy()
|
|
274
|
+
}
|
|
275
|
+
})
|
|
276
|
+
})
|
|
277
|
+
}
|
|
142
278
|
|
|
143
279
|
/**
|
|
144
280
|
* @since 1.0.0
|
|
145
|
-
* @category
|
|
281
|
+
* @category conversions
|
|
146
282
|
*/
|
|
147
|
-
export const
|
|
148
|
-
|
|
149
|
-
|
|
283
|
+
export const toUint8Array = <E = Cause.UnknownError>(
|
|
284
|
+
readable: LazyArg<Readable | NodeJS.ReadableStream>,
|
|
285
|
+
options?: {
|
|
286
|
+
readonly onError?: (error: unknown) => E
|
|
287
|
+
readonly maxBytes?: SizeInput | undefined
|
|
288
|
+
}
|
|
289
|
+
): Effect.Effect<Uint8Array, E> => Effect.map(toArrayBuffer(readable, options), (buffer) => new Uint8Array(buffer))
|
|
150
290
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
*/
|
|
155
|
-
export const stdout: Stream.Stream<Uint8Array> = internal.fromReadable(() => process.stdout, (err) => err, {
|
|
156
|
-
closeOnDone: false
|
|
157
|
-
}).pipe(Stream.orDie)
|
|
291
|
+
// ----------------------------------------------------------------------------
|
|
292
|
+
// internal
|
|
293
|
+
// ----------------------------------------------------------------------------
|
|
158
294
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
295
|
+
const readableToPullUnsafe = <A, E>(options: {
|
|
296
|
+
readonly scope: Scope.Scope
|
|
297
|
+
readonly exit?: MutableRef.MutableRef<Exit.Exit<never, E | Cause.Done> | undefined> | undefined
|
|
298
|
+
readonly readable: Readable | NodeJS.ReadableStream
|
|
299
|
+
readonly onError: (error: unknown) => E
|
|
300
|
+
readonly chunkSize: number | undefined
|
|
301
|
+
readonly closeOnDone?: boolean | undefined
|
|
302
|
+
}) => {
|
|
303
|
+
const readable = options.readable as Readable
|
|
304
|
+
const closeOnDone = options.closeOnDone ?? true
|
|
305
|
+
const exit = options.exit ?? MutableRef.make(undefined)
|
|
306
|
+
const latch = Effect.makeLatchUnsafe(false)
|
|
307
|
+
function onReadable() {
|
|
308
|
+
latch.openUnsafe()
|
|
309
|
+
}
|
|
310
|
+
function onError(error: unknown) {
|
|
311
|
+
exit.current = Exit.fail(options.onError(error))
|
|
312
|
+
latch.openUnsafe()
|
|
313
|
+
}
|
|
314
|
+
function onEnd() {
|
|
315
|
+
exit.current = Exit.fail(Cause.Done())
|
|
316
|
+
latch.openUnsafe()
|
|
317
|
+
}
|
|
318
|
+
readable.on("readable", onReadable)
|
|
319
|
+
readable.once("error", onError)
|
|
320
|
+
readable.once("end", onEnd)
|
|
321
|
+
|
|
322
|
+
const pull = Effect.suspend(function loop(): Pull.Pull<Arr.NonEmptyReadonlyArray<A>, E> {
|
|
323
|
+
let item = options.readable.read(options.chunkSize) as A | null
|
|
324
|
+
if (item === null) {
|
|
325
|
+
if (exit.current) {
|
|
326
|
+
return exit.current
|
|
327
|
+
}
|
|
328
|
+
latch.closeUnsafe()
|
|
329
|
+
return Effect.flatMap(latch.await, loop)
|
|
330
|
+
}
|
|
331
|
+
const chunk = Arr.of(item as A)
|
|
332
|
+
while (true) {
|
|
333
|
+
item = options.readable.read(options.chunkSize)
|
|
334
|
+
if (item === null) break
|
|
335
|
+
chunk.push(item)
|
|
336
|
+
}
|
|
337
|
+
return Effect.succeed(chunk)
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
return Effect.as(
|
|
341
|
+
Scope.addFinalizer(
|
|
342
|
+
options.scope,
|
|
343
|
+
Effect.sync(() => {
|
|
344
|
+
readable.off("readable", onReadable)
|
|
345
|
+
readable.off("error", onError)
|
|
346
|
+
readable.off("end", onEnd)
|
|
347
|
+
if (closeOnDone && "closed" in options.readable && !options.readable.closed) {
|
|
348
|
+
options.readable.destroy()
|
|
349
|
+
}
|
|
350
|
+
})
|
|
351
|
+
),
|
|
352
|
+
pull
|
|
353
|
+
)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
class StreamAdapter<E, R> extends Readable {
|
|
357
|
+
private readonly readLatch: Effect.Latch
|
|
358
|
+
private fiber: Fiber.Fiber<void, E> | undefined = undefined
|
|
359
|
+
|
|
360
|
+
constructor(
|
|
361
|
+
context: ServiceMap.ServiceMap<R>,
|
|
362
|
+
stream: Stream.Stream<Uint8Array | string, E, R>
|
|
363
|
+
) {
|
|
364
|
+
super({})
|
|
365
|
+
this.readLatch = Effect.makeLatchUnsafe(false)
|
|
366
|
+
this.fiber = Stream.runForEachArray(stream, (chunk) =>
|
|
367
|
+
this.readLatch.whenOpen(Effect.sync(() => {
|
|
368
|
+
this.readLatch.closeUnsafe()
|
|
369
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
370
|
+
const item = chunk[i]
|
|
371
|
+
if (typeof item === "string") {
|
|
372
|
+
this.push(item, "utf8")
|
|
373
|
+
} else {
|
|
374
|
+
this.push(item)
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}))).pipe(
|
|
378
|
+
this.readLatch.whenOpen,
|
|
379
|
+
Effect.provideServices(context),
|
|
380
|
+
Effect.runFork
|
|
381
|
+
)
|
|
382
|
+
this.fiber.addObserver((exit) => {
|
|
383
|
+
this.fiber = undefined
|
|
384
|
+
if (Exit.isSuccess(exit)) {
|
|
385
|
+
this.push(null)
|
|
386
|
+
} else {
|
|
387
|
+
this.destroy(Cause.squash(exit.cause) as any)
|
|
388
|
+
}
|
|
389
|
+
})
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
override _read(_size: number): void {
|
|
393
|
+
this.readLatch.openUnsafe()
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
override _destroy(error: Error | null, callback: (error?: Error | null | undefined) => void): void {
|
|
397
|
+
if (!this.fiber) {
|
|
398
|
+
return callback(error)
|
|
399
|
+
}
|
|
400
|
+
Effect.runFork(Fiber.interrupt(this.fiber)).addObserver((exit) => {
|
|
401
|
+
callback(exit._tag === "Failure" ? Cause.squash(exit.cause) as any : error)
|
|
402
|
+
})
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const defaultOnError = (error: unknown): Cause.UnknownError => new Cause.UnknownError(error)
|
package/src/NodeTerminal.ts
CHANGED
|
@@ -1,20 +1,111 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @since 1.0.0
|
|
3
3
|
*/
|
|
4
|
-
import type
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import type
|
|
8
|
-
import * as
|
|
4
|
+
import type * as Cause from "effect/Cause"
|
|
5
|
+
import * as Effect from "effect/Effect"
|
|
6
|
+
import * as Layer from "effect/Layer"
|
|
7
|
+
import { badArgument, type PlatformError } from "effect/PlatformError"
|
|
8
|
+
import * as Predicate from "effect/Predicate"
|
|
9
|
+
import * as Queue from "effect/Queue"
|
|
10
|
+
import * as RcRef from "effect/RcRef"
|
|
11
|
+
import type * as Scope from "effect/Scope"
|
|
12
|
+
import * as Terminal from "effect/Terminal"
|
|
13
|
+
import * as readline from "node:readline"
|
|
14
|
+
|
|
9
15
|
/**
|
|
10
16
|
* @since 1.0.0
|
|
11
17
|
* @category constructors
|
|
12
18
|
*/
|
|
13
|
-
export const make: (
|
|
14
|
-
|
|
19
|
+
export const make: (
|
|
20
|
+
shouldQuit?: (input: Terminal.UserInput) => boolean
|
|
21
|
+
) => Effect.Effect<Terminal.Terminal, never, Scope.Scope> = Effect.fnUntraced(
|
|
22
|
+
function*(shouldQuit: (input: Terminal.UserInput) => boolean = defaultShouldQuit) {
|
|
23
|
+
const stdin = process.stdin
|
|
24
|
+
const stdout = process.stdout
|
|
25
|
+
|
|
26
|
+
// Acquire readline interface with TTY setup/cleanup inside the scope
|
|
27
|
+
const rlRef = yield* RcRef.make({
|
|
28
|
+
acquire: Effect.acquireRelease(
|
|
29
|
+
Effect.sync(() => {
|
|
30
|
+
const rl = readline.createInterface({ input: stdin, escapeCodeTimeout: 50 })
|
|
31
|
+
readline.emitKeypressEvents(stdin, rl)
|
|
32
|
+
|
|
33
|
+
if (stdin.isTTY) {
|
|
34
|
+
stdin.setRawMode(true)
|
|
35
|
+
}
|
|
36
|
+
return rl
|
|
37
|
+
}),
|
|
38
|
+
(rl) =>
|
|
39
|
+
Effect.sync(() => {
|
|
40
|
+
if (stdin.isTTY) {
|
|
41
|
+
stdin.setRawMode(false)
|
|
42
|
+
}
|
|
43
|
+
rl.close()
|
|
44
|
+
})
|
|
45
|
+
)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const columns = Effect.sync(() => stdout.columns ?? 0)
|
|
49
|
+
|
|
50
|
+
const readInput = Effect.gen(function*() {
|
|
51
|
+
yield* RcRef.get(rlRef)
|
|
52
|
+
const queue = yield* Queue.make<Terminal.UserInput, Cause.Done>()
|
|
53
|
+
const handleKeypress = (s: string | undefined, k: readline.Key) => {
|
|
54
|
+
const userInput = {
|
|
55
|
+
input: s,
|
|
56
|
+
key: { name: k.name ?? "", ctrl: !!k.ctrl, meta: !!k.meta, shift: !!k.shift }
|
|
57
|
+
}
|
|
58
|
+
Queue.offerUnsafe(queue, userInput)
|
|
59
|
+
if (shouldQuit(userInput)) {
|
|
60
|
+
Queue.endUnsafe(queue)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
yield* Effect.addFinalizer(() => Effect.sync(() => stdin.off("keypress", handleKeypress)))
|
|
64
|
+
stdin.on("keypress", handleKeypress)
|
|
65
|
+
return queue as Queue.Dequeue<Terminal.UserInput, Cause.Done>
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const readLine = Effect.scoped(
|
|
69
|
+
Effect.flatMap(RcRef.get(rlRef), (readlineInterface) =>
|
|
70
|
+
Effect.callback<string, Terminal.QuitError>((resume) => {
|
|
71
|
+
const onLine = (line: string) => resume(Effect.succeed(line))
|
|
72
|
+
readlineInterface.once("line", onLine)
|
|
73
|
+
return Effect.sync(() => readlineInterface.off("line", onLine))
|
|
74
|
+
}))
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
const display = (prompt: string) =>
|
|
78
|
+
Effect.uninterruptible(
|
|
79
|
+
Effect.callback<void, PlatformError>((resume) => {
|
|
80
|
+
stdout.write(prompt, (err) =>
|
|
81
|
+
Predicate.isNullish(err)
|
|
82
|
+
? resume(Effect.void)
|
|
83
|
+
: resume(Effect.fail(
|
|
84
|
+
badArgument({
|
|
85
|
+
module: "Terminal",
|
|
86
|
+
method: "display",
|
|
87
|
+
description: "Failed to write prompt to stdout",
|
|
88
|
+
cause: err
|
|
89
|
+
})
|
|
90
|
+
)))
|
|
91
|
+
})
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
return Terminal.make({
|
|
95
|
+
columns,
|
|
96
|
+
readInput,
|
|
97
|
+
readLine,
|
|
98
|
+
display
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
)
|
|
15
102
|
|
|
16
103
|
/**
|
|
17
104
|
* @since 1.0.0
|
|
18
|
-
* @category
|
|
105
|
+
* @category layers
|
|
19
106
|
*/
|
|
20
|
-
export const layer: Layer<Terminal> =
|
|
107
|
+
export const layer: Layer.Layer<Terminal.Terminal> = Layer.effect(Terminal.Terminal, make(defaultShouldQuit))
|
|
108
|
+
|
|
109
|
+
function defaultShouldQuit(input: Terminal.UserInput) {
|
|
110
|
+
return input.key.ctrl && (input.key.name === "c" || input.key.name === "d")
|
|
111
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
1
|
+
import type { SystemError, SystemErrorKind } from "effect/PlatformError"
|
|
2
|
+
import * as PlatformError from "effect/PlatformError"
|
|
3
3
|
import type { PathLike } from "node:fs"
|
|
4
4
|
|
|
5
5
|
/** @internal */
|
|
@@ -7,8 +7,8 @@ export const handleErrnoException = (module: SystemError["module"], method: stri
|
|
|
7
7
|
(
|
|
8
8
|
err: NodeJS.ErrnoException,
|
|
9
9
|
[path]: [path: PathLike | number, ...args: Array<any>]
|
|
10
|
-
): PlatformError => {
|
|
11
|
-
let reason:
|
|
10
|
+
): PlatformError.PlatformError => {
|
|
11
|
+
let reason: SystemErrorKind = "Unknown"
|
|
12
12
|
|
|
13
13
|
switch (err.code) {
|
|
14
14
|
case "ENOENT":
|
|
@@ -40,13 +40,12 @@ export const handleErrnoException = (module: SystemError["module"], method: stri
|
|
|
40
40
|
break
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
return
|
|
44
|
-
reason,
|
|
43
|
+
return PlatformError.systemError({
|
|
44
|
+
kind: reason,
|
|
45
45
|
module,
|
|
46
46
|
method,
|
|
47
47
|
pathOrDescriptor: path as string | number,
|
|
48
48
|
syscall: err.syscall,
|
|
49
|
-
description: err.message,
|
|
50
49
|
cause: err
|
|
51
50
|
})
|
|
52
51
|
}
|