@effect/platform-node-shared 0.57.1 → 4.0.0-beta.1

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.
Files changed (218) hide show
  1. package/README.md +3 -3
  2. package/dist/NodeChildProcessSpawner.d.ts +37 -0
  3. package/dist/NodeChildProcessSpawner.d.ts.map +1 -0
  4. package/dist/NodeChildProcessSpawner.js +567 -0
  5. package/dist/NodeChildProcessSpawner.js.map +1 -0
  6. package/dist/{dts/NodeClusterSocket.d.ts → NodeClusterSocket.d.ts} +4 -7
  7. package/dist/NodeClusterSocket.d.ts.map +1 -0
  8. package/dist/{esm/NodeClusterSocket.js → NodeClusterSocket.js} +9 -10
  9. package/dist/NodeClusterSocket.js.map +1 -0
  10. package/dist/NodeFileSystem.d.ts +8 -0
  11. package/dist/NodeFileSystem.d.ts.map +1 -0
  12. package/dist/{esm/internal/fileSystem.js → NodeFileSystem.js} +125 -96
  13. package/dist/NodeFileSystem.js.map +1 -0
  14. package/dist/NodePath.d.ts +18 -0
  15. package/dist/NodePath.d.ts.map +1 -0
  16. package/dist/NodePath.js +56 -0
  17. package/dist/NodePath.js.map +1 -0
  18. package/dist/NodeRuntime.d.ts +28 -0
  19. package/dist/NodeRuntime.d.ts.map +1 -0
  20. package/dist/{esm/internal/runtime.js → NodeRuntime.js} +8 -8
  21. package/dist/NodeRuntime.js.map +1 -0
  22. package/dist/NodeSink.d.ts +40 -0
  23. package/dist/NodeSink.d.ts.map +1 -0
  24. package/dist/NodeSink.js +50 -0
  25. package/dist/NodeSink.js.map +1 -0
  26. package/dist/{dts/NodeSocket.d.ts → NodeSocket.d.ts} +10 -10
  27. package/dist/NodeSocket.d.ts.map +1 -0
  28. package/dist/{esm/NodeSocket.js → NodeSocket.js} +51 -39
  29. package/dist/NodeSocket.js.map +1 -0
  30. package/dist/{dts/NodeSocketServer.d.ts → NodeSocketServer.d.ts} +8 -10
  31. package/dist/NodeSocketServer.d.ts.map +1 -0
  32. package/dist/NodeSocketServer.js +192 -0
  33. package/dist/NodeSocketServer.js.map +1 -0
  34. package/dist/NodeStdio.d.ts +11 -0
  35. package/dist/NodeStdio.d.ts.map +1 -0
  36. package/dist/NodeStdio.js +43 -0
  37. package/dist/NodeStdio.js.map +1 -0
  38. package/dist/NodeStream.d.ts +127 -0
  39. package/dist/NodeStream.d.ts.map +1 -0
  40. package/dist/NodeStream.js +249 -0
  41. package/dist/NodeStream.js.map +1 -0
  42. package/dist/NodeTerminal.d.ts +15 -0
  43. package/dist/NodeTerminal.d.ts.map +1 -0
  44. package/dist/{esm/internal/terminal.js → NodeTerminal.js} +28 -25
  45. package/dist/NodeTerminal.js.map +1 -0
  46. package/dist/internal/utils.d.ts +2 -0
  47. package/dist/internal/utils.d.ts.map +1 -0
  48. package/dist/{esm/internal/error.js → internal/utils.js} +4 -5
  49. package/dist/internal/utils.js.map +1 -0
  50. package/package.json +53 -124
  51. package/src/NodeChildProcessSpawner.ts +713 -0
  52. package/src/NodeClusterSocket.ts +12 -13
  53. package/src/NodeFileSystem.ts +632 -5
  54. package/src/NodePath.ts +48 -9
  55. package/src/NodeRuntime.ts +53 -4
  56. package/src/NodeSink.ts +65 -62
  57. package/src/NodeSocket.ts +65 -49
  58. package/src/NodeSocketServer.ts +108 -88
  59. package/src/NodeStdio.ts +49 -0
  60. package/src/NodeStream.ts +324 -83
  61. package/src/NodeTerminal.ts +100 -9
  62. package/src/internal/{error.ts → utils.ts} +6 -7
  63. package/NodeClusterSocket/package.json +0 -6
  64. package/NodeCommandExecutor/package.json +0 -6
  65. package/NodeFileSystem/ParcelWatcher/package.json +0 -6
  66. package/NodeFileSystem/package.json +0 -6
  67. package/NodeKeyValueStore/package.json +0 -6
  68. package/NodeMultipart/package.json +0 -6
  69. package/NodePath/package.json +0 -6
  70. package/NodeRuntime/package.json +0 -6
  71. package/NodeSink/package.json +0 -6
  72. package/NodeSocket/package.json +0 -6
  73. package/NodeSocketServer/package.json +0 -6
  74. package/NodeStream/package.json +0 -6
  75. package/NodeTerminal/package.json +0 -6
  76. package/dist/cjs/NodeClusterSocket.js +0 -50
  77. package/dist/cjs/NodeClusterSocket.js.map +0 -1
  78. package/dist/cjs/NodeCommandExecutor.js +0 -14
  79. package/dist/cjs/NodeCommandExecutor.js.map +0 -1
  80. package/dist/cjs/NodeFileSystem/ParcelWatcher.js +0 -20
  81. package/dist/cjs/NodeFileSystem/ParcelWatcher.js.map +0 -1
  82. package/dist/cjs/NodeFileSystem.js +0 -18
  83. package/dist/cjs/NodeFileSystem.js.map +0 -1
  84. package/dist/cjs/NodeKeyValueStore.js +0 -18
  85. package/dist/cjs/NodeKeyValueStore.js.map +0 -1
  86. package/dist/cjs/NodeMultipart.js +0 -24
  87. package/dist/cjs/NodeMultipart.js.map +0 -1
  88. package/dist/cjs/NodePath.js +0 -28
  89. package/dist/cjs/NodePath.js.map +0 -1
  90. package/dist/cjs/NodeRuntime.js +0 -14
  91. package/dist/cjs/NodeRuntime.js.map +0 -1
  92. package/dist/cjs/NodeSink.js +0 -50
  93. package/dist/cjs/NodeSink.js.map +0 -1
  94. package/dist/cjs/NodeSocket.js +0 -153
  95. package/dist/cjs/NodeSocket.js.map +0 -1
  96. package/dist/cjs/NodeSocketServer.js +0 -178
  97. package/dist/cjs/NodeSocketServer.js.map +0 -1
  98. package/dist/cjs/NodeStream.js +0 -76
  99. package/dist/cjs/NodeStream.js.map +0 -1
  100. package/dist/cjs/NodeTerminal.js +0 -19
  101. package/dist/cjs/NodeTerminal.js.map +0 -1
  102. package/dist/cjs/internal/commandExecutor.js +0 -153
  103. package/dist/cjs/internal/commandExecutor.js.map +0 -1
  104. package/dist/cjs/internal/error.js +0 -45
  105. package/dist/cjs/internal/error.js.map +0 -1
  106. package/dist/cjs/internal/fileSystem/parcelWatcher.js +0 -68
  107. package/dist/cjs/internal/fileSystem/parcelWatcher.js.map +0 -1
  108. package/dist/cjs/internal/fileSystem.js +0 -400
  109. package/dist/cjs/internal/fileSystem.js.map +0 -1
  110. package/dist/cjs/internal/multipart.js +0 -147
  111. package/dist/cjs/internal/multipart.js.map +0 -1
  112. package/dist/cjs/internal/path.js +0 -53
  113. package/dist/cjs/internal/path.js.map +0 -1
  114. package/dist/cjs/internal/runtime.js +0 -37
  115. package/dist/cjs/internal/runtime.js.map +0 -1
  116. package/dist/cjs/internal/sink.js +0 -28
  117. package/dist/cjs/internal/sink.js.map +0 -1
  118. package/dist/cjs/internal/stream.js +0 -233
  119. package/dist/cjs/internal/stream.js.map +0 -1
  120. package/dist/cjs/internal/terminal.js +0 -90
  121. package/dist/cjs/internal/terminal.js.map +0 -1
  122. package/dist/dts/NodeClusterSocket.d.ts.map +0 -1
  123. package/dist/dts/NodeCommandExecutor.d.ts +0 -12
  124. package/dist/dts/NodeCommandExecutor.d.ts.map +0 -1
  125. package/dist/dts/NodeFileSystem/ParcelWatcher.d.ts +0 -13
  126. package/dist/dts/NodeFileSystem/ParcelWatcher.d.ts.map +0 -1
  127. package/dist/dts/NodeFileSystem.d.ts +0 -11
  128. package/dist/dts/NodeFileSystem.d.ts.map +0 -1
  129. package/dist/dts/NodeKeyValueStore.d.ts +0 -12
  130. package/dist/dts/NodeKeyValueStore.d.ts.map +0 -1
  131. package/dist/dts/NodeMultipart.d.ts +0 -27
  132. package/dist/dts/NodeMultipart.d.ts.map +0 -1
  133. package/dist/dts/NodePath.d.ts +0 -21
  134. package/dist/dts/NodePath.d.ts.map +0 -1
  135. package/dist/dts/NodeRuntime.d.ts +0 -10
  136. package/dist/dts/NodeRuntime.d.ts.map +0 -1
  137. package/dist/dts/NodeSink.d.ts +0 -36
  138. package/dist/dts/NodeSink.d.ts.map +0 -1
  139. package/dist/dts/NodeSocket.d.ts.map +0 -1
  140. package/dist/dts/NodeSocketServer.d.ts.map +0 -1
  141. package/dist/dts/NodeStream.d.ts +0 -119
  142. package/dist/dts/NodeStream.d.ts.map +0 -1
  143. package/dist/dts/NodeTerminal.d.ts +0 -18
  144. package/dist/dts/NodeTerminal.d.ts.map +0 -1
  145. package/dist/dts/internal/commandExecutor.d.ts +0 -2
  146. package/dist/dts/internal/commandExecutor.d.ts.map +0 -1
  147. package/dist/dts/internal/error.d.ts +0 -2
  148. package/dist/dts/internal/error.d.ts.map +0 -1
  149. package/dist/dts/internal/fileSystem/parcelWatcher.d.ts +0 -4
  150. package/dist/dts/internal/fileSystem/parcelWatcher.d.ts.map +0 -1
  151. package/dist/dts/internal/fileSystem.d.ts +0 -2
  152. package/dist/dts/internal/fileSystem.d.ts.map +0 -1
  153. package/dist/dts/internal/multipart.d.ts +0 -2
  154. package/dist/dts/internal/multipart.d.ts.map +0 -1
  155. package/dist/dts/internal/path.d.ts +0 -2
  156. package/dist/dts/internal/path.d.ts.map +0 -1
  157. package/dist/dts/internal/runtime.d.ts +0 -2
  158. package/dist/dts/internal/runtime.d.ts.map +0 -1
  159. package/dist/dts/internal/sink.d.ts +0 -2
  160. package/dist/dts/internal/sink.d.ts.map +0 -1
  161. package/dist/dts/internal/stream.d.ts +0 -2
  162. package/dist/dts/internal/stream.d.ts.map +0 -1
  163. package/dist/dts/internal/terminal.d.ts +0 -2
  164. package/dist/dts/internal/terminal.d.ts.map +0 -1
  165. package/dist/esm/NodeClusterSocket.js.map +0 -1
  166. package/dist/esm/NodeCommandExecutor.js +0 -7
  167. package/dist/esm/NodeCommandExecutor.js.map +0 -1
  168. package/dist/esm/NodeFileSystem/ParcelWatcher.js +0 -12
  169. package/dist/esm/NodeFileSystem/ParcelWatcher.js.map +0 -1
  170. package/dist/esm/NodeFileSystem.js +0 -10
  171. package/dist/esm/NodeFileSystem.js.map +0 -1
  172. package/dist/esm/NodeKeyValueStore.js +0 -10
  173. package/dist/esm/NodeKeyValueStore.js.map +0 -1
  174. package/dist/esm/NodeMultipart.js +0 -17
  175. package/dist/esm/NodeMultipart.js.map +0 -1
  176. package/dist/esm/NodePath.js +0 -20
  177. package/dist/esm/NodePath.js.map +0 -1
  178. package/dist/esm/NodeRuntime.js +0 -7
  179. package/dist/esm/NodeRuntime.js.map +0 -1
  180. package/dist/esm/NodeSink.js +0 -43
  181. package/dist/esm/NodeSink.js.map +0 -1
  182. package/dist/esm/NodeSocket.js.map +0 -1
  183. package/dist/esm/NodeSocketServer.js +0 -167
  184. package/dist/esm/NodeSocketServer.js.map +0 -1
  185. package/dist/esm/NodeStream.js +0 -69
  186. package/dist/esm/NodeStream.js.map +0 -1
  187. package/dist/esm/NodeTerminal.js +0 -12
  188. package/dist/esm/NodeTerminal.js.map +0 -1
  189. package/dist/esm/internal/commandExecutor.js +0 -146
  190. package/dist/esm/internal/commandExecutor.js.map +0 -1
  191. package/dist/esm/internal/error.js.map +0 -1
  192. package/dist/esm/internal/fileSystem/parcelWatcher.js +0 -61
  193. package/dist/esm/internal/fileSystem/parcelWatcher.js.map +0 -1
  194. package/dist/esm/internal/fileSystem.js.map +0 -1
  195. package/dist/esm/internal/multipart.js +0 -137
  196. package/dist/esm/internal/multipart.js.map +0 -1
  197. package/dist/esm/internal/path.js +0 -46
  198. package/dist/esm/internal/path.js.map +0 -1
  199. package/dist/esm/internal/runtime.js.map +0 -1
  200. package/dist/esm/internal/sink.js +0 -19
  201. package/dist/esm/internal/sink.js.map +0 -1
  202. package/dist/esm/internal/stream.js +0 -217
  203. package/dist/esm/internal/stream.js.map +0 -1
  204. package/dist/esm/internal/terminal.js.map +0 -1
  205. package/dist/esm/package.json +0 -4
  206. package/src/NodeCommandExecutor.ts +0 -13
  207. package/src/NodeFileSystem/ParcelWatcher.ts +0 -15
  208. package/src/NodeKeyValueStore.ts +0 -20
  209. package/src/NodeMultipart.ts +0 -40
  210. package/src/internal/commandExecutor.ts +0 -251
  211. package/src/internal/fileSystem/parcelWatcher.ts +0 -64
  212. package/src/internal/fileSystem.ts +0 -648
  213. package/src/internal/multipart.ts +0 -141
  214. package/src/internal/path.ts +0 -63
  215. package/src/internal/runtime.ts +0 -34
  216. package/src/internal/sink.ts +0 -57
  217. package/src/internal/stream.ts +0 -375
  218. package/src/internal/terminal.ts +0 -104
package/src/NodeStream.ts CHANGED
@@ -1,65 +1,97 @@
1
1
  /**
2
2
  * @since 1.0.0
3
3
  */
4
- import type { PlatformError } from "@effect/platform/Error"
5
- import type { SizeInput } from "@effect/platform/FileSystem"
6
- import type { Channel } from "effect/Channel"
7
- import type { Chunk } from "effect/Chunk"
8
- import type { Effect } from "effect/Effect"
9
- import type { LazyArg } from "effect/Function"
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, Readable } from "node:stream"
12
- import * as internal from "./internal/stream.js"
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 models
22
+ * @category constructors
16
23
  * @since 1.0.0
17
24
  */
18
- export interface FromReadableOptions {
19
- /** Defaults to undefined, which lets Node.js decide the chunk size */
20
- readonly chunkSize?: SizeInput
21
- /** Default to true, which means the stream will be closed when done */
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 fromReadable: <E, A = Uint8Array<ArrayBufferLike>>(
39
- evaluate: LazyArg<Readable | NodeJS.ReadableStream>,
40
- onError: (error: unknown) => E,
41
- options?: FromReadableOptions
42
- ) => Stream.Stream<A, E> = internal.fromReadable
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 fromReadableChannel: <E, A = Uint8Array<ArrayBufferLike>>(
49
- evaluate: LazyArg<Readable | NodeJS.ReadableStream>,
50
- onError: (error: unknown) => E,
51
- options?: FromReadableOptions | undefined
52
- ) => Channel<Chunk<A>, unknown, E> = internal.fromReadableChannel
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
- * @category constructors
56
- * @since 1.0.0
57
- */
58
- export const fromDuplex: <IE, E, I = Uint8Array, O = Uint8Array>(
59
- evaluate: LazyArg<Duplex>,
60
- onError: (error: unknown) => E,
61
- options?: FromReadableOptions & FromWritableOptions
62
- ) => Channel<Chunk<O>, Chunk<I>, IE | E, IE, void, unknown> = internal.fromDuplex
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
- <E2, B = Uint8Array>(
74
- duplex: LazyArg<Duplex>,
75
- onError: (error: unknown) => E2,
76
- options?: (FromReadableOptions & FromWritableOptions) | undefined
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, E2, B = Uint8Array>(
119
+ <R, E, A, B = Uint8Array, E2 = Cause.UnknownError>(
83
120
  self: Stream.Stream<A, E, R>,
84
- duplex: LazyArg<Duplex>,
85
- onError: (error: unknown) => E2,
86
- options?: (FromReadableOptions & FromWritableOptions) | undefined
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
- } = internal.pipeThroughDuplex
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 | PlatformError, R>
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, PlatformError | E, R>
105
- } = internal.pipeThroughSimple
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: <E, R>(stream: Stream.Stream<string | Uint8Array, E, R>) => Effect<Readable, never, R> =
112
- internal.toReadable
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: <E>(stream: Stream.Stream<string | Uint8Array, E, never>) => Readable =
119
- internal.toReadableNever
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: <E>(
190
+ export const toString = <E = Cause.UnknownError>(
126
191
  readable: LazyArg<Readable | NodeJS.ReadableStream>,
127
- options: {
128
- readonly onFailure: (error: unknown) => E
192
+ options?: {
193
+ readonly onError?: (error: unknown) => E
129
194
  readonly encoding?: BufferEncoding | undefined
130
195
  readonly maxBytes?: SizeInput | undefined
131
196
  }
132
- ) => Effect<string, E> = internal.toString
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 toUint8Array: <E>(
239
+ export const toArrayBuffer = <E = Cause.UnknownError>(
139
240
  readable: LazyArg<Readable | NodeJS.ReadableStream>,
140
- options: { readonly onFailure: (error: unknown) => E; readonly maxBytes?: SizeInput | undefined }
141
- ) => Effect<Uint8Array, E> = internal.toUint8Array
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 stdio
281
+ * @category conversions
146
282
  */
147
- export const stdin: Stream.Stream<Uint8Array> = internal.fromReadable(() => process.stdin, (err) => err, {
148
- closeOnDone: false
149
- }).pipe(Stream.orDie)
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
- * @since 1.0.0
153
- * @category stdio
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
- * @since 1.0.0
161
- * @category stdio
162
- */
163
- export const stderr: Stream.Stream<Uint8Array> = internal.fromReadable(() => process.stderr, (err) => err, {
164
- closeOnDone: false
165
- }).pipe(Stream.orDie)
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)
@@ -1,20 +1,111 @@
1
1
  /**
2
2
  * @since 1.0.0
3
3
  */
4
- import type { Terminal, UserInput } from "@effect/platform/Terminal"
5
- import type { Effect } from "effect/Effect"
6
- import type { Layer } from "effect/Layer"
7
- import type { Scope } from "effect/Scope"
8
- import * as InternalTerminal from "./internal/terminal.js"
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: (shouldQuit?: (input: UserInput) => boolean) => Effect<Terminal, never, Scope> =
14
- InternalTerminal.make
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 layer
105
+ * @category layers
19
106
  */
20
- export const layer: Layer<Terminal> = InternalTerminal.layer
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 { PlatformError, SystemErrorReason } from "@effect/platform/Error"
2
- import { SystemError } from "@effect/platform/Error"
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: SystemErrorReason = "Unknown"
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 new SystemError({
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
  }
@@ -1,6 +0,0 @@
1
- {
2
- "sideEffects": [],
3
- "main": "../dist/cjs/NodeClusterSocket.js",
4
- "module": "../dist/esm/NodeClusterSocket.js",
5
- "types": "../dist/dts/NodeClusterSocket.d.ts"
6
- }
@@ -1,6 +0,0 @@
1
- {
2
- "sideEffects": [],
3
- "main": "../dist/cjs/NodeCommandExecutor.js",
4
- "module": "../dist/esm/NodeCommandExecutor.js",
5
- "types": "../dist/dts/NodeCommandExecutor.d.ts"
6
- }
@@ -1,6 +0,0 @@
1
- {
2
- "sideEffects": [],
3
- "main": "../../dist/cjs/NodeFileSystem/ParcelWatcher.js",
4
- "module": "../../dist/esm/NodeFileSystem/ParcelWatcher.js",
5
- "types": "../../dist/dts/NodeFileSystem/ParcelWatcher.d.ts"
6
- }
@@ -1,6 +0,0 @@
1
- {
2
- "sideEffects": [],
3
- "main": "../dist/cjs/NodeFileSystem.js",
4
- "module": "../dist/esm/NodeFileSystem.js",
5
- "types": "../dist/dts/NodeFileSystem.d.ts"
6
- }
@@ -1,6 +0,0 @@
1
- {
2
- "sideEffects": [],
3
- "main": "../dist/cjs/NodeKeyValueStore.js",
4
- "module": "../dist/esm/NodeKeyValueStore.js",
5
- "types": "../dist/dts/NodeKeyValueStore.d.ts"
6
- }