@effect/platform-node-shared 4.0.0-beta.8 → 4.0.0-beta.81

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 (66) hide show
  1. package/dist/NodeChildProcessSpawner.d.ts +19 -5
  2. package/dist/NodeChildProcessSpawner.d.ts.map +1 -1
  3. package/dist/NodeChildProcessSpawner.js +77 -18
  4. package/dist/NodeChildProcessSpawner.js.map +1 -1
  5. package/dist/NodeClusterSocket.d.ts +10 -4
  6. package/dist/NodeClusterSocket.d.ts.map +1 -1
  7. package/dist/NodeClusterSocket.js +22 -8
  8. package/dist/NodeClusterSocket.js.map +1 -1
  9. package/dist/NodeCrypto.d.ts +27 -0
  10. package/dist/NodeCrypto.d.ts.map +1 -0
  11. package/dist/NodeCrypto.js +55 -0
  12. package/dist/NodeCrypto.js.map +1 -0
  13. package/dist/NodeFileSystem.d.ts +5 -2
  14. package/dist/NodeFileSystem.d.ts.map +1 -1
  15. package/dist/NodeFileSystem.js +33 -26
  16. package/dist/NodeFileSystem.js.map +1 -1
  17. package/dist/NodePath.d.ts +15 -6
  18. package/dist/NodePath.d.ts.map +1 -1
  19. package/dist/NodePath.js +23 -7
  20. package/dist/NodePath.js.map +1 -1
  21. package/dist/NodeRuntime.d.ts +26 -7
  22. package/dist/NodeRuntime.d.ts.map +1 -1
  23. package/dist/NodeRuntime.js +8 -8
  24. package/dist/NodeRuntime.js.map +1 -1
  25. package/dist/NodeSink.d.ts +33 -4
  26. package/dist/NodeSink.d.ts.map +1 -1
  27. package/dist/NodeSink.js +31 -4
  28. package/dist/NodeSink.js.map +1 -1
  29. package/dist/NodeSocket.d.ts +41 -10
  30. package/dist/NodeSocket.d.ts.map +1 -1
  31. package/dist/NodeSocket.js +39 -16
  32. package/dist/NodeSocket.js.map +1 -1
  33. package/dist/NodeSocketServer.d.ts +25 -8
  34. package/dist/NodeSocketServer.d.ts.map +1 -1
  35. package/dist/NodeSocketServer.js +29 -12
  36. package/dist/NodeSocketServer.js.map +1 -1
  37. package/dist/NodeStdio.d.ts +6 -5
  38. package/dist/NodeStdio.d.ts.map +1 -1
  39. package/dist/NodeStdio.js +23 -7
  40. package/dist/NodeStdio.js.map +1 -1
  41. package/dist/NodeStream.d.ts +76 -20
  42. package/dist/NodeStream.d.ts.map +1 -1
  43. package/dist/NodeStream.js +68 -23
  44. package/dist/NodeStream.js.map +1 -1
  45. package/dist/NodeTerminal.d.ts +9 -2
  46. package/dist/NodeTerminal.d.ts.map +1 -1
  47. package/dist/NodeTerminal.js +13 -3
  48. package/dist/NodeTerminal.js.map +1 -1
  49. package/dist/index.d.ts +52 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +53 -0
  52. package/dist/index.js.map +1 -0
  53. package/package.json +7 -6
  54. package/src/NodeChildProcessSpawner.ts +117 -29
  55. package/src/NodeClusterSocket.ts +22 -8
  56. package/src/NodeCrypto.ts +60 -0
  57. package/src/NodeFileSystem.ts +40 -28
  58. package/src/NodePath.ts +23 -7
  59. package/src/NodeRuntime.ts +28 -13
  60. package/src/NodeSink.ts +40 -4
  61. package/src/NodeSocket.ts +47 -17
  62. package/src/NodeSocketServer.ts +39 -13
  63. package/src/NodeStdio.ts +41 -23
  64. package/src/NodeStream.ts +89 -30
  65. package/src/NodeTerminal.ts +22 -4
  66. package/src/index.ts +65 -0
@@ -1,17 +1,32 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Node-compatible process runner for Effect programs.
3
+ *
4
+ * This module provides the shared `runMain` implementation used by
5
+ * Node-compatible platform packages. It runs one Effect as the main process
6
+ * fiber, interrupts that fiber on `SIGINT` or `SIGTERM`, and delegates final
7
+ * exit-code handling to the configured teardown.
8
+ *
9
+ * @since 4.0.0
3
10
  */
4
11
  import type { Effect } from "effect/Effect"
5
12
  import * as Runtime from "effect/Runtime"
6
13
 
7
14
  /**
8
- * @since 1.0.0
9
- * @category Run main
15
+ * Runs an Effect as the Node process main program, interrupting the fiber on
16
+ * `SIGINT` or `SIGTERM` and invoking the configured teardown to determine the
17
+ * process exit code.
18
+ *
19
+ * @category running
20
+ * @since 4.0.0
10
21
  */
11
22
  export const runMain: {
12
23
  /**
13
- * @since 1.0.0
14
- * @category Run main
24
+ * Runs an Effect as the Node process main program, interrupting the fiber on
25
+ * `SIGINT` or `SIGTERM` and invoking the configured teardown to determine the
26
+ * process exit code.
27
+ *
28
+ * @category running
29
+ * @since 4.0.0
15
30
  */
16
31
  (
17
32
  options?: {
@@ -20,8 +35,12 @@ export const runMain: {
20
35
  }
21
36
  ): <E, A>(effect: Effect<A, E>) => void
22
37
  /**
23
- * @since 1.0.0
24
- * @category Run main
38
+ * Runs an Effect as the Node process main program, interrupting the fiber on
39
+ * `SIGINT` or `SIGTERM` and invoking the configured teardown to determine the
40
+ * process exit code.
41
+ *
42
+ * @category running
43
+ * @since 4.0.0
25
44
  */
26
45
  <E, A>(
27
46
  effect: Effect<A, E>,
@@ -37,10 +56,8 @@ export const runMain: {
37
56
  let receivedSignal = false
38
57
 
39
58
  fiber.addObserver((exit) => {
40
- if (!receivedSignal) {
41
- process.removeListener("SIGINT", onSigint)
42
- process.removeListener("SIGTERM", onSigint)
43
- }
59
+ process.removeListener("SIGINT", onSigint)
60
+ process.removeListener("SIGTERM", onSigint)
44
61
  teardown(exit, (code) => {
45
62
  if (receivedSignal || code !== 0) {
46
63
  process.exit(code)
@@ -50,8 +67,6 @@ export const runMain: {
50
67
 
51
68
  function onSigint() {
52
69
  receivedSignal = true
53
- process.removeListener("SIGINT", onSigint)
54
- process.removeListener("SIGTERM", onSigint)
55
70
  fiber.interruptUnsafe(fiber.id)
56
71
  }
57
72
 
package/src/NodeSink.ts CHANGED
@@ -1,5 +1,13 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Sink adapters for writing Effect chunks into Node writable streams.
3
+ *
4
+ * `fromWritable` creates a `Sink`, `fromWritableChannel` creates a lower-level
5
+ * `Channel`, and `pullIntoWritable` writes from an existing pull loop. All
6
+ * three adapters respect writable-stream backpressure, map writable errors with
7
+ * the supplied `onError` function, and can end the writable when the upstream
8
+ * data is done.
9
+ *
10
+ * @since 4.0.0
3
11
  */
4
12
  import type { NonEmptyReadonlyArray } from "effect/Array"
5
13
  import * as Cause from "effect/Cause"
@@ -11,8 +19,12 @@ import * as Sink from "effect/Sink"
11
19
  import type { Writable } from "node:stream"
12
20
 
13
21
  /**
22
+ * Creates a `Sink` that writes chunks to a Node writable stream, respecting
23
+ * backpressure, mapping writable errors with `onError`, and ending the stream
24
+ * on completion unless `endOnDone` is `false`.
25
+ *
14
26
  * @category constructors
15
- * @since 1.0.0
27
+ * @since 4.0.0
16
28
  */
17
29
  export const fromWritable = <E, A = Uint8Array | string>(
18
30
  options: {
@@ -25,8 +37,12 @@ export const fromWritable = <E, A = Uint8Array | string>(
25
37
  Sink.fromChannel(Channel.mapDone(fromWritableChannel<never, E, A>(options), (_) => [_]))
26
38
 
27
39
  /**
40
+ * Creates a `Channel` that pulls chunks from upstream and writes them to a
41
+ * Node writable stream, respecting backpressure and optionally ending the
42
+ * writable when upstream is done.
43
+ *
28
44
  * @category constructors
29
- * @since 1.0.0
45
+ * @since 4.0.0
30
46
  */
31
47
  export const fromWritableChannel = <IE, E, A = Uint8Array | string>(
32
48
  options: {
@@ -42,7 +58,20 @@ export const fromWritableChannel = <IE, E, A = Uint8Array | string>(
42
58
  })
43
59
 
44
60
  /**
45
- * @since 1.0.0
61
+ * Writes Effect chunks into a Node writable stream.
62
+ *
63
+ * **When to use**
64
+ *
65
+ * Use to implement custom Node stream adapters that already have an upstream
66
+ * pull and need direct control over a writable stream.
67
+ *
68
+ * **Details**
69
+ *
70
+ * The loop waits for `drain` when needed, fails on writable errors, and ends
71
+ * the writable on upstream completion unless `endOnDone` is `false`.
72
+ *
73
+ * @category converting
74
+ * @since 4.0.0
46
75
  */
47
76
  export const pullIntoWritable = <A, IE, E>(options: {
48
77
  readonly pull: Pull.Pull<NonEmptyReadonlyArray<A>, IE, unknown>
@@ -66,6 +95,13 @@ export const pullIntoWritable = <A, IE, E>(options: {
66
95
  })
67
96
  }),
68
97
  Effect.forever({ disableYield: true }),
98
+ Effect.raceFirst(Effect.callback<never, E>((resume) => {
99
+ const onError = (error: unknown) => resume(Effect.fail(options.onError(error)))
100
+ options.writable.once("error", onError)
101
+ return Effect.sync(() => {
102
+ options.writable.off("error", onError)
103
+ })
104
+ })),
69
105
  options.endOnDone !== false ?
70
106
  Pull.catchDone((_) => {
71
107
  if ("closed" in options.writable && options.writable.closed) {
package/src/NodeSocket.ts CHANGED
@@ -1,8 +1,16 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Node socket adapters for Effect sockets.
3
+ *
4
+ * This module opens `node:net` connections or wraps existing Node `Duplex`
5
+ * streams and presents them as `Socket.Socket` values, socket channels, or
6
+ * layers. It also exposes the current underlying `NetSocket` service for code
7
+ * running inside a socket handler and re-exports the `ws` package namespace.
8
+ *
9
+ * @since 4.0.0
3
10
  */
4
11
  import type { Array } from "effect"
5
12
  import * as Channel from "effect/Channel"
13
+ import * as Context from "effect/Context"
6
14
  import * as Deferred from "effect/Deferred"
7
15
  import type * as Duration from "effect/Duration"
8
16
  import * as Effect from "effect/Effect"
@@ -12,28 +20,41 @@ import { identity } from "effect/Function"
12
20
  import * as Latch from "effect/Latch"
13
21
  import * as Layer from "effect/Layer"
14
22
  import * as Scope from "effect/Scope"
15
- import * as ServiceMap from "effect/ServiceMap"
16
23
  import * as Socket from "effect/unstable/socket/Socket"
17
24
  import * as Net from "node:net"
18
25
  import type { Duplex } from "node:stream"
19
26
 
20
27
  /**
21
- * @since 1.0.0
22
28
  * @category re-exports
29
+ * @since 4.0.0
23
30
  */
24
31
  export * as NodeWS from "ws"
25
32
 
26
33
  /**
27
- * @since 1.0.0
28
- * @category tags
34
+ * Service tag for the underlying Node `net.Socket` associated with the current
35
+ * socket connection.
36
+ *
37
+ * @category services
38
+ * @since 4.0.0
29
39
  */
30
- export class NetSocket extends ServiceMap.Service<NetSocket, Net.Socket>()(
40
+ export class NetSocket extends Context.Service<NetSocket, Net.Socket>()(
31
41
  "@effect/platform-node/NodeSocket/NetSocket"
32
42
  ) {}
33
43
 
34
44
  /**
35
- * @since 1.0.0
45
+ * Opens a Node TCP connection as an Effect socket.
46
+ *
47
+ * **When to use**
48
+ *
49
+ * Use to create a scoped `Socket.Socket` from Node `net.createConnection`.
50
+ *
51
+ * **Details**
52
+ *
53
+ * Supports `openTimeout` and closes or destroys the underlying socket when the
54
+ * enclosing scope is finalized.
55
+ *
36
56
  * @category constructors
57
+ * @since 4.0.0
37
58
  */
38
59
  export const makeNet = (
39
60
  options: Net.NetConnectOpts & {
@@ -41,11 +62,11 @@ export const makeNet = (
41
62
  }
42
63
  ): Effect.Effect<Socket.Socket> =>
43
64
  fromDuplex(
44
- Effect.servicesWith((services: ServiceMap.ServiceMap<Scope.Scope>) => {
65
+ Effect.contextWith((context: Context.Context<Scope.Scope>) => {
45
66
  let conn: Net.Socket | undefined
46
67
  return Effect.flatMap(
47
68
  Scope.addFinalizer(
48
- ServiceMap.get(services, Scope.Scope),
69
+ Context.get(context, Scope.Scope),
49
70
  Effect.sync(() => {
50
71
  if (!conn) return
51
72
  if (conn.closed === false) {
@@ -77,8 +98,12 @@ export const makeNet = (
77
98
  )
78
99
 
79
100
  /**
80
- * @since 1.0.0
101
+ * Adapts a Node `Duplex` into a `Socket.Socket`, wiring data events to socket
102
+ * handlers, providing a scoped writer, and mapping open, read, write, and close
103
+ * failures to `SocketError`.
104
+ *
81
105
  * @category constructors
106
+ * @since 4.0.0
82
107
  */
83
108
  export const fromDuplex = <RO>(
84
109
  open: Effect.Effect<Duplex, Socket.SocketError, RO>,
@@ -89,7 +114,7 @@ export const fromDuplex = <RO>(
89
114
  Effect.withFiber<Socket.Socket, never, Exclude<RO, Scope.Scope>>((fiber) => {
90
115
  let currentSocket: Duplex | undefined
91
116
  const latch = Latch.makeUnsafe(false)
92
- const openServices = fiber.services as ServiceMap.ServiceMap<RO>
117
+ const openServices = fiber.context as Context.Context<RO>
93
118
 
94
119
  const run = <R, E, _>(handler: (_: Uint8Array) => Effect.Effect<_, E, R> | void, opts?: {
95
120
  readonly onOpen?: Effect.Effect<void> | undefined
@@ -113,7 +138,7 @@ export const fromDuplex = <RO>(
113
138
  options?.openTimeout ?
114
139
  Effect.timeoutOrElse({
115
140
  duration: options.openTimeout,
116
- onTimeout: () =>
141
+ orElse: () =>
117
142
  Effect.fail(
118
143
  new Socket.SocketError({
119
144
  reason: new Socket.SocketOpenError({ kind: "Timeout", cause: new Error("Connection timed out") })
@@ -166,7 +191,7 @@ export const fromDuplex = <RO>(
166
191
  )
167
192
  }
168
193
  })).pipe(
169
- Effect.updateServices((input: ServiceMap.ServiceMap<R>) => ServiceMap.merge(openServices, input)),
194
+ Effect.updateContext((input: Context.Context<R>) => Context.merge(openServices, input)),
170
195
  Effect.onExit(() =>
171
196
  Effect.sync(() => {
172
197
  latch.closeUnsafe()
@@ -204,8 +229,7 @@ export const fromDuplex = <RO>(
204
229
  })
205
230
  )
206
231
 
207
- return Effect.succeed(Socket.Socket.of({
208
- [Socket.TypeId]: Socket.TypeId,
232
+ return Effect.succeed(Socket.make({
209
233
  run,
210
234
  runRaw: run,
211
235
  writer
@@ -213,8 +237,11 @@ export const fromDuplex = <RO>(
213
237
  })
214
238
 
215
239
  /**
216
- * @since 1.0.0
240
+ * Creates a `Channel` over a TCP socket, reading arrays of `Uint8Array`
241
+ * chunks and writing arrays of bytes, strings, or socket close events.
242
+ *
217
243
  * @category constructors
244
+ * @since 4.0.0
218
245
  */
219
246
  export const makeNetChannel = <IE = never>(
220
247
  options: Net.NetConnectOpts
@@ -230,8 +257,11 @@ export const makeNetChannel = <IE = never>(
230
257
  )
231
258
 
232
259
  /**
233
- * @since 1.0.0
260
+ * Provides a `Socket.Socket` by opening a TCP connection with the supplied
261
+ * Node `net` connection options.
262
+ *
234
263
  * @category layers
264
+ * @since 4.0.0
235
265
  */
236
266
  export const layerNet: (options: Net.NetConnectOpts) => Layer.Layer<
237
267
  Socket.Socket,
@@ -1,7 +1,17 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Node socket server adapters for Effect's unstable socket server API.
3
+ *
4
+ * This module turns `node:net` TCP or Unix-domain servers and `ws` WebSocket
5
+ * servers into scoped `SocketServer.SocketServer` services. Use the TCP
6
+ * constructors when handlers should receive a `Socket.Socket` backed by a Node
7
+ * `net.Socket`; use the WebSocket constructors when handlers should receive a
8
+ * `Socket.Socket` backed by `ws` and have access to the per-connection
9
+ * WebSocket and `IncomingMessage` services.
10
+ *
11
+ * @since 4.0.0
3
12
  */
4
13
  import type { Cause } from "effect/Cause"
14
+ import * as Context from "effect/Context"
5
15
  import * as Deferred from "effect/Deferred"
6
16
  import * as Effect from "effect/Effect"
7
17
  import * as Exit from "effect/Exit"
@@ -11,7 +21,6 @@ import * as Function from "effect/Function"
11
21
  import * as Layer from "effect/Layer"
12
22
  import * as References from "effect/References"
13
23
  import * as Scope from "effect/Scope"
14
- import * as ServiceMap from "effect/ServiceMap"
15
24
  import * as Socket from "effect/unstable/socket/Socket"
16
25
  import * as SocketServer from "effect/unstable/socket/SocketServer"
17
26
  import type * as Http from "node:http"
@@ -20,17 +29,24 @@ import * as NodeSocket from "./NodeSocket.ts"
20
29
  import { NodeWS } from "./NodeSocket.ts"
21
30
 
22
31
  /**
23
- * @since 1.0.0
24
- * @category tags
32
+ * Service tag for the Node `IncomingMessage` associated with the current
33
+ * WebSocket server connection.
34
+ *
35
+ * @category services
36
+ * @since 4.0.0
25
37
  */
26
- export class IncomingMessage extends ServiceMap.Service<
38
+ export class IncomingMessage extends Context.Service<
27
39
  IncomingMessage,
28
40
  Http.IncomingMessage
29
41
  >()("@effect/platform-node-shared/NodeSocketServer/IncomingMessage") {}
30
42
 
31
43
  /**
32
- * @since 1.0.0
44
+ * Creates a scoped TCP `SocketServer` from a Node `net.Server`, starts
45
+ * listening with the supplied options, queues pending connections until `run`
46
+ * is called, and closes the server when the scope ends.
47
+ *
33
48
  * @category constructors
49
+ * @since 4.0.0
34
50
  */
35
51
  export const make = Effect.fnUntraced(function*(
36
52
  options: Net.ServerOpts & Net.ListenOptions
@@ -69,7 +85,7 @@ export const make = Effect.fnUntraced(function*(
69
85
 
70
86
  const run = Effect.fnUntraced(function*<R, E, _>(handler: (socket: Socket.Socket) => Effect.Effect<_, E, R>) {
71
87
  const scope = yield* Scope.make()
72
- const services = ServiceMap.omit(Scope.Scope)(yield* Effect.services<R>()) as ServiceMap.ServiceMap<R>
88
+ const services = Context.omit(Scope.Scope)(yield* Effect.context<R>()) as Context.Context<R>
73
89
  const trackFiber = Fiber.runIn(scope)
74
90
  const prevOnConnection = onConnection
75
91
  onConnection = function(conn: Net.Socket) {
@@ -109,7 +125,7 @@ export const make = Effect.fnUntraced(function*(
109
125
  ),
110
126
  Effect.flatMap(handler),
111
127
  Effect.catchCause(reportUnhandledError),
112
- Effect.runForkWith(ServiceMap.add(services, NodeSocket.NetSocket, conn)),
128
+ Effect.runForkWith(Context.add(services, NodeSocket.NetSocket, conn)),
113
129
  trackFiber
114
130
  )
115
131
  }
@@ -144,8 +160,11 @@ export const make = Effect.fnUntraced(function*(
144
160
  })
145
161
 
146
162
  /**
147
- * @since 1.0.0
163
+ * Provides a TCP `SocketServer` by creating and managing a scoped Node
164
+ * `net.Server` with the supplied server and listen options.
165
+ *
148
166
  * @category layers
167
+ * @since 4.0.0
149
168
  */
150
169
  export const layer: (
151
170
  options: Net.ServerOpts & Net.ListenOptions
@@ -155,8 +174,12 @@ export const layer: (
155
174
  > = Function.flow(make, Layer.effect(SocketServer.SocketServer))
156
175
 
157
176
  /**
158
- * @since 1.0.0
177
+ * Creates a scoped WebSocket `SocketServer` backed by the `ws` package,
178
+ * providing the WebSocket and its Node `IncomingMessage` to connection
179
+ * handlers and closing the server when the scope ends.
180
+ *
159
181
  * @category constructors
182
+ * @since 4.0.0
160
183
  */
161
184
  export const makeWebSocket: (
162
185
  options: NodeWS.ServerOptions<typeof NodeWS.WebSocket, typeof Http.IncomingMessage>
@@ -202,7 +225,7 @@ export const makeWebSocket: (
202
225
 
203
226
  const run = Effect.fnUntraced(function*<R, E, _>(handler: (socket: Socket.Socket) => Effect.Effect<_, E, R>) {
204
227
  const scope = yield* Scope.make()
205
- const services = ServiceMap.omit(Scope.Scope)(yield* Effect.services<R>()) as ServiceMap.ServiceMap<R>
228
+ const services = Context.omit(Scope.Scope)(yield* Effect.context<R>()) as Context.Context<R>
206
229
  const trackFiber = Fiber.runIn(scope)
207
230
  const prevOnConnection = onConnection
208
231
  onConnection = function(conn: globalThis.WebSocket, req: Http.IncomingMessage) {
@@ -221,7 +244,7 @@ export const makeWebSocket: (
221
244
  ),
222
245
  Effect.flatMap(handler),
223
246
  Effect.catchCause(reportUnhandledError),
224
- Effect.runForkWith(ServiceMap.makeUnsafe(map)),
247
+ Effect.runForkWith(Context.makeUnsafe(map)),
225
248
  trackFiber
226
249
  )
227
250
  }
@@ -255,8 +278,11 @@ export const makeWebSocket: (
255
278
  })
256
279
 
257
280
  /**
258
- * @since 1.0.0
281
+ * Provides a WebSocket `SocketServer` backed by the `ws` package and managed
282
+ * with the supplied server options.
283
+ *
259
284
  * @category layers
285
+ * @since 4.0.0
260
286
  */
261
287
  export const layerWebSocket: (
262
288
  options: NodeSocket.NodeWS.ServerOptions<typeof NodeSocket.NodeWS.WebSocket, typeof Http.IncomingMessage>
package/src/NodeStdio.ts CHANGED
@@ -1,6 +1,15 @@
1
1
  /**
2
- * @since 1.0.0
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,32 +17,41 @@ import { fromWritable } from "./NodeSink.ts"
8
17
  import { fromReadable } from "./NodeStream.ts"
9
18
 
10
19
  /**
11
- * @category Layers
12
- * @since 1.0.0
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
- stdout: fromWritable({
18
- evaluate: () => process.stdout,
19
- onError: (cause) =>
20
- systemError({
21
- module: "Stdio",
22
- method: "stdout",
23
- _tag: "Unknown",
24
- cause
25
- })
26
- }),
27
- stderr: fromWritable({
28
- evaluate: () => process.stderr,
29
- onError: (cause) =>
30
- systemError({
31
- module: "Stdio",
32
- method: "stderr",
33
- _tag: "Unknown",
34
- cause
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) =>