import { Command, Path } from '@effect/platform';
import { Effect, Option, pipe, Stream, String } from 'effect';
export const CommandUtils = {
withLog: (
cmd: Command.Command,
runner: (cmd: Command.Command) => Effect.Effect,
) =>
Effect.gen(function* () {
const flattenedCmd = Command.flatten(cmd);
const [firstCmd] = flattenedCmd;
yield* Effect.logDebug(
`Running: '${flattenedCmd
.map((c) => `${c.command} ${c.args.join(' ')}`)
.join(' | ')}' in ${Option.getOrElse(firstCmd.cwd, () => '.')}`,
);
return yield* runner(cmd);
}),
/**
* Command.workingDirectory does not set the PWD env var.
*/
withCwd: (cwd: string) =>
Effect.gen(function* () {
const path = yield* Path.Path;
const absoluteCwd = path.resolve(path.join(process.cwd(), cwd));
return (cmd: Command.Command) =>
cmd.pipe(
Command.workingDirectory(absoluteCwd),
Command.env({ PWD: absoluteCwd }),
);
}),
bufferStringStream: (
stream: Stream.Stream,
): Effect.Effect =>
stream.pipe(
Stream.decodeText(),
Stream.runFold(String.empty, String.concat),
),
runCommandBuffered: (command: Command.Command) =>
pipe(
Command.start(command),
Effect.flatMap((process) =>
Effect.all(
[
process.exitCode,
CommandUtils.bufferStringStream(process.stdout),
CommandUtils.bufferStringStream(process.stderr),
],
{ concurrency: 3 },
),
),
Effect.map(([exitCode, stdout, stderr]) => ({
exitCode,
stdout,
stderr,
})),
),
};