the-moby-effect
Version:
Moby/Docker API client built using effect-ts
168 lines • 6.83 kB
JavaScript
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