1/**
2 * Process stdio for Deno applications.
3 *
4 * This module provides Effect's `Stdio` service using Deno's native process
5 * arguments and Web Streams. Standard input remains open, and standard output
6 * and error output are not closed unless requested through `endOnDone`.
7 *
8 * @since 4.0.0
9 */
10import * as Effect from "effect/Effect"
11import * as Layer from "effect/Layer"
12import * as Sink from "effect/Sink"
13import * as Stdio from "effect/Stdio"
14import * as Stream from "effect/Stream"
15import { handleError } from "./internal/error.ts"
16
17const encoder = new TextEncoder()
18
19const output = (
20 evaluate: () => WritableStream<Uint8Array>,
21 method: "stdout" | "stderr",
22 options?: { readonly endOnDone?: boolean | undefined }
23) =>
24 Sink.fromWritableStream({
25 evaluate,
26 onError: handleError("Stdio", method),
27 closeOnDone: options?.endOnDone ?? false
28 }).pipe(
29 Sink.mapInput((input: string | Uint8Array) => typeof input === "string" ? encoder.encode(input) : input)
30 )
31
32/**
33 * Provides the `Stdio` service backed by `Deno.args`, `Deno.stdin`,
34 * `Deno.stdout`, and `Deno.stderr`.
35 *
36 * @category layers
37 * @since 4.0.0
38 */
39export const layer: Layer.Layer<Stdio.Stdio> = Layer.succeed(
40 Stdio.Stdio,
41 Stdio.make({
42 args: Effect.sync(() => Deno.args),
43 stdinIsTerminal: Effect.sync(() => Deno.stdin.isTerminal()),
44 stdoutIsTerminal: Effect.sync(() => Deno.stdout.isTerminal()),
45 stdout: (options) => output(() => Deno.stdout.writable, "stdout", options),
46 stderr: (options) => output(() => Deno.stderr.writable, "stderr", options),
47 stdin: Stream.fromReadableStream({
48 evaluate: () => Deno.stdin.readable,
49 onError: handleError("Stdio", "stdin"),
50 releaseLockOnEnd: true
51 })
52 })
53)