| 1 | import * as DenoStdio from "@effect/platform-deno/DenoStdio" |
| 2 | import { assert, describe, it } from "@effect/vitest" |
| 3 | import * as Effect from "effect/Effect" |
| 4 | import * as Stdio from "effect/Stdio" |
| 5 | |
| 6 | const streams = [Deno.stdin, Deno.stdout] as const |
| 7 | |
| 8 | const setIsTerminal = (stdin: boolean, stdout: boolean) => |
| 9 | Effect.sync(() => { |
| 10 | Object.defineProperty(streams[0], "isTerminal", { configurable: true, value: () => stdin }) |
| 11 | Object.defineProperty(streams[1], "isTerminal", { configurable: true, value: () => stdout }) |
| 12 | }) |
| 13 | |
| 14 | const withRestoredIsTerminal = <A, E, R>(effect: Effect.Effect<A, E, R>) => |
| 15 | Effect.acquireUseRelease( |
| 16 | Effect.sync(() => streams.map((stream) => Object.getOwnPropertyDescriptor(stream, "isTerminal"))), |
| 17 | () => effect, |
| 18 | (descriptors) => |
| 19 | Effect.sync(() => { |
| 20 | streams.forEach((stream, index) => { |
| 21 | const descriptor = descriptors[index] |
| 22 | if (descriptor === undefined) { |
| 23 | Reflect.deleteProperty(stream, "isTerminal") |
| 24 | } else { |
| 25 | Object.defineProperty(stream, "isTerminal", descriptor) |
| 26 | } |
| 27 | }) |
| 28 | }) |
| 29 | ) |
| 30 | |
| 31 | describe("DenoStdio", () => { |
| 32 | it.effect("reads terminal state when the effects run", () => |
| 33 | withRestoredIsTerminal( |
| 34 | Effect.gen(function*() { |
| 35 | const stdio = yield* Stdio.Stdio |
| 36 | |
| 37 | yield* setIsTerminal(true, false) |
| 38 | assert.deepStrictEqual( |
| 39 | yield* Effect.all([stdio.stdinIsTerminal, stdio.stdoutIsTerminal]), |
| 40 | [true, false] |
| 41 | ) |
| 42 | |
| 43 | yield* setIsTerminal(false, true) |
| 44 | assert.deepStrictEqual( |
| 45 | yield* Effect.all([stdio.stdinIsTerminal, stdio.stdoutIsTerminal]), |
| 46 | [false, true] |
| 47 | ) |
| 48 | }).pipe(Effect.provide(DenoStdio.layer)) |
| 49 | )) |
| 50 | }) |