UNPKG

the-moby-effect

Version:
168 lines 6.83 kB
import * as Channel from "effect/Channel"; import * as Effect from "effect/Effect"; import * as Function from "effect/Function"; import * as Pipeable from "effect/Pipeable"; import * as Predicate from "effect/Predicate"; import * as Sink from "effect/Sink"; import * as Stream from "effect/Stream"; import * as Tuple from "effect/Tuple"; import * as Socket from "effect/unstable/socket/Socket"; import * as internalCompressed from "./compressed.js"; /** @internal */ export const RawContentType = "application/vnd.docker.raw-stream"; /** @internal */ export const RawSocketTypeId = /*#__PURE__*/Symbol.for("the-moby-effect/demux/RawSocket"); /** @internal */ export const RawChannelTypeId = /*#__PURE__*/Symbol.for("the-moby-effect/demux/RawChannel"); /** @internal */ export const makeRawSocket = underlying => ({ underlying, "content-type": RawContentType, [RawSocketTypeId]: RawSocketTypeId, pipe() { return Pipeable.pipeArguments(this, arguments); } }); /** @internal */ export const makeRawChannel = underlying => ({ underlying, "content-type": RawContentType, [RawChannelTypeId]: RawChannelTypeId, pipe() { return Pipeable.pipeArguments(this, arguments); } }); /** @internal */ export const isRawSocket = u => Predicate.hasProperty(u, RawSocketTypeId); /** @internal */ export const isRawChannel = u => Predicate.hasProperty(u, RawChannelTypeId); /** @internal */ export const never = /*#__PURE__*/makeRawChannel(Channel.never); /** @internal */ export const neverWith = () => makeRawChannel(Channel.never); /** @internal */ export const responseIsRawResponse = response => response.headers["content-type"] === RawContentType; /** @internal */ export const asRawChannel = input => isRawSocket(input) ? makeRawChannel(Socket.toChannel(input.underlying)) : input; /** @internal */ export const rawToStream = input => Stream.pipeThroughChannelOrFail(Stream.empty, asRawChannel(input).underlying); /** @internal */ export const rawToSink = input => Sink.fromChannel(Function.pipe(asRawChannel(input).underlying, Channel.drain, Channel.mapDone(() => [void 0]))); /** @internal */ export const rawFromStreamWith = () => input => makeRawChannel(Stream.toChannel(input)); /** @internal */ export const rawFromStream = input => rawFromStreamWith()(input); // /** @internal */ // export const rawFromSink = <E, R>( // input: Sink.Sink<void, string | Uint8Array | Socket.CloseEvent, Uint8Array, E, R> // ): MobyDemux.RawChannel<never, E, R> => makeRawChannel<never, E, R>(Sink.toChannel(input)); /** @internal */ export const interleaveRaw = (stdout, stderr) => { return Stream.interleave(rawToStream(stdout), rawToStream(stderr)); }; /** @internal */ export const mergeRawToTaggedStream = (stdout, stderr, options) => Function.pipe(Stream.merge(Stream.map(rawToStream(stdout), value => ({ _tag: "stdout", value })), Stream.map(rawToStream(stderr), value => ({ _tag: "stderr", value })), { haltStrategy: "both" }), Stream.buffer({ capacity: options?.bufferSize ?? 16 })); /** @internal */ export const demuxRawToSingleSink = /*#__PURE__*/Function.dual(arguments_ => isRawSocket(arguments_[0]) || isRawChannel(arguments_[0]), (socket, source, sink, options) => Function.pipe(source, Stream.pipeThroughChannelOrFail(asRawChannel(socket).underlying), Stream.decodeText({ encoding: options?.encoding }), Stream.run(sink))); /** @internal */ export const demuxStdioRawTupled = /*#__PURE__*/Effect.fnUntraced(function* (sockets, options) { const { stderr, stdin, stdout } = sockets; const stdinSocketObject = Predicate.isNotUndefined(stdin) ? { stdin: stdin?.[1] } : {}; const stdoutSocketObject = Predicate.isNotUndefined(stdout) ? { stdout: stdout?.[0] } : {}; const stderrSocketObject = Predicate.isNotUndefined(stderr) ? { stderr: stderr?.[0] } : {}; const stdinIoObject = Predicate.isNotUndefined(stdin) ? { stdin: stdin?.[0] } : { stdin: Stream.empty }; const stdoutIoObject = Predicate.isNotUndefined(stdout) ? { stdout: stdout?.[1] } : { stdout: Sink.succeed(void 0) }; const stderrIoObject = Predicate.isNotUndefined(stderr) ? { stderr: stderr?.[1] } : { stderr: Sink.succeed(void 0) }; // `sockets` guarantees at least one of stdin/stdout/stderr is defined, but spreading the // three conditional objects widens to a union that also includes the all-absent case, which // HeterogeneousStdioRawInput deliberately does not model. TypeScript 7 tracks this precisely // where 5.9 did not, so restate the invariant here. const rawSockets = { ...stdinSocketObject, ...stdoutSocketObject, ...stderrSocketObject }; return yield* demuxStdioRawToSeparateSinks(rawSockets, { ...stdinIoObject, ...stdoutIoObject, ...stderrIoObject }, options); }); /** @internal */ export const demuxStdioRawToSingleSink = /*#__PURE__*/Function.dual(arguments_ => "stdin" in arguments_[0] || "stdout" in arguments_[0] || "stderr" in arguments_[0], /*#__PURE__*/Effect.fnUntraced(function* (sockets, source, sink, options) { const { stderr, stdin, stdout } = sockets; const stdoutStream = Predicate.isUndefined(stdout) ? Stream.empty : rawToStream(stdout); const stderrStream = Predicate.isUndefined(stderr) ? Stream.empty : rawToStream(stderr); const runInput = Predicate.isNotUndefined(stdin) ? demuxRawToSingleSink(stdin, source, Sink.drain, options) : Stream.run(source, Sink.drain); const runOutput = Stream.interleave(stdoutStream, stderrStream).pipe(Stream.decodeText({ encoding: options?.encoding }), Stream.run(sink)); return yield* Effect.map(Effect.all({ ranStdin: runInput, ranOutput: runOutput }, { concurrency: 2 }), ({ ranOutput }) => ranOutput); })); /** @internal */ export const demuxStdioRawToSeparateSinks = /*#__PURE__*/Function.dual(arguments_ => !("stdin" in arguments_[0] && Stream.isStream(arguments_[0]["stdin"])), /*#__PURE__*/Effect.fnUntraced(function* (sockets, io, options) { const { stderr, stdin, stdout } = sockets; const runStdin = Predicate.isNotUndefined(stdin) ? demuxRawToSingleSink(stdin, io.stdin, Sink.drain, options) : Stream.run(io.stdin, Sink.succeed(void 0)); const runStdout = Predicate.isNotUndefined(stdout) ? demuxRawToSingleSink(stdout, Stream.never, io.stdout, options) : Stream.run(Stream.empty, io.stdout); const runStderr = Predicate.isNotUndefined(stderr) ? demuxRawToSingleSink(stderr, Stream.never, io.stderr, options) : Stream.run(Stream.empty, io.stderr); return yield* Effect.map(Effect.all({ ranStdin: runStdin, ranStdout: runStdout, ranStderr: runStderr }, { concurrency: 3 }), ({ ranStderr, ranStdout }) => internalCompressed.compressDemuxOutput(Tuple.make(ranStdout, ranStderr))); })); //# sourceMappingURL=raw.js.map