the-moby-effect
Version:
Moby/Docker API client built using effect-ts
97 lines (87 loc) • 4 kB
text/typescript
import type * as Socket from "@effect/platform/Socket";
import type * as Channel from "effect/Channel";
import type * as Chunk from "effect/Chunk";
import type * as ParseResult from "effect/ParseResult";
import type * as Scope from "effect/Scope";
import type * as Stream from "effect/Stream";
import type * as MobyDemux from "../../MobyDemux.js";
import * as Console from "effect/Console";
import * as Data from "effect/Data";
import * as Effect from "effect/Effect";
import * as Sink from "effect/Sink";
import { asMultiplexedChannel, demuxMultiplexedToSeparateSinks, makeMultiplexedChannel } from "./multiplexed.js";
/**
* @since 1.0.0
* @category Errors
*/
export class StdinError extends Data.TaggedError("StdinError")<{ message: string; cause: unknown }> {}
/**
* @since 1.0.0
* @category Errors
*/
export class StdoutError extends Data.TaggedError("StdoutError")<{ message: string; cause: unknown }> {}
/**
* @since 1.0.0
* @category Errors
*/
export class StderrError extends Data.TaggedError("StderrError")<{ message: string; cause: unknown }> {}
/** @internal */
export const demuxFromStdinToStdoutAndStderr = <IE = never, OE = Socket.SocketError, R = never>(
sockets: MobyDemux.EitherMultiplexedInput<IE, OE, R>,
options?: { bufferSize?: number | undefined; encoding?: string | undefined } | undefined
): Effect.Effect<
void,
IE | OE | StdinError | StdoutError | StderrError | ParseResult.ParseError,
Exclude<R, Scope.Scope>
> =>
Effect.flatMap(
Effect.all(
{
NodeSinkLazy: Effect.promise(() => import("@effect/platform-node/NodeSink")),
NodeStreamLazy: Effect.promise(() => import("@effect/platform-node/NodeStream")),
},
{ concurrency: 2 }
),
({ NodeSinkLazy, NodeStreamLazy }) => {
const stdin: Stream.Stream<Uint8Array, StdinError, never> = NodeStreamLazy.fromReadable(
() => process.stdin,
(cause: unknown) => new StdinError({ cause, message: "stdin is not readable" })
);
const stdout: Sink.Sink<void, string | Uint8Array, never, StdoutError, never> = NodeSinkLazy.fromWritable(
() => process.stdout,
(cause: unknown) => new StdoutError({ cause, message: "stdout is not writable" }),
{ endOnDone: false }
);
const stderr: Sink.Sink<void, string | Uint8Array, never, StderrError, never> = NodeSinkLazy.fromWritable(
() => process.stderr,
(cause: unknown) => new StderrError({ cause, message: "stderr is not writable" }),
{ endOnDone: false }
);
const { underlying } = asMultiplexedChannel(sockets);
const multiplexedChannel = makeMultiplexedChannel<IE | StdinError, IE | OE | StdinError, R>(
underlying as Channel.Channel<
Chunk.Chunk<Uint8Array>,
Chunk.Chunk<string | Uint8Array | Socket.CloseEvent>,
IE | OE | StdinError,
IE | StdinError,
void,
unknown,
R
>
);
return demuxMultiplexedToSeparateSinks(multiplexedChannel, stdin, stdout, stderr, options);
}
);
/** @internal */
export const demuxWithInputToConsole = <E, R1, IE = never, OE = Socket.SocketError, R2 = never>(
sockets: MobyDemux.EitherMultiplexedInput<E | IE, OE, R2>,
input: Stream.Stream<string | Uint8Array, E, R1>,
options?: { bufferSize?: number | undefined; encoding?: string | undefined } | undefined
): Effect.Effect<void, E | IE | OE | ParseResult.ParseError, Exclude<R1, Scope.Scope> | Exclude<R2, Scope.Scope>> =>
demuxMultiplexedToSeparateSinks(
sockets,
input,
Sink.forEach<string, void, never, never>(Console.log),
Sink.forEach<string, void, never, never>(Console.error),
options
);