diff options
Diffstat (limited to 'u/process/exec.ts')
-rw-r--r-- | u/process/exec.ts | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/u/process/exec.ts b/u/process/exec.ts new file mode 100644 index 0000000..a2cdbca --- /dev/null +++ b/u/process/exec.ts @@ -0,0 +1,59 @@ +import { + Either, + IEither, + type ITraceable, + LogLevel, + LogMetricTraceSupplier, + Metric, + TraceUtil, +} from '@emprespresso/pengueno'; +import { promisify } from 'node:util'; +import { exec as execCallback } from 'node:child_process'; +const exec = promisify(execCallback); + +export type Command = string[] | string; +export type StdStreams = { stdout: string; stderr: string }; + +export const CmdMetric = Metric.fromName('Exec').asResult(); +type Environment = Record<string, string>; +type Options = { env?: Environment; clearEnv?: boolean }; +export const getStdout = ( + cmd: ITraceable<Command, LogMetricTraceSupplier>, + options: Options = {}, +): Promise<IEither<Error, string>> => + cmd + .flatMap(TraceUtil.withFunctionTrace(getStdout)) + .flatMap((tCmd) => tCmd.traceScope(() => `Command = ${tCmd.get()}`)) + .map((tCmd) => { + const cmd = tCmd.get(); + const _exec = typeof cmd === 'string' ? cmd : cmd.join(' '); + const env = options.clearEnv ? options.env : { ...process.env, ...options.env }; + return Either.fromFailableAsync<Error, StdStreams>(exec(_exec, { env })); + }) + .map( + TraceUtil.promiseify((tEitherStdStreams) => + tEitherStdStreams.get().mapRight(({ stderr, stdout }) => { + if (stderr) tEitherStdStreams.trace.traceScope(LogLevel.DEBUG).trace(`StdErr = ${stderr}`); + return stdout; + }), + ), + ) + .peek(TraceUtil.promiseify(TraceUtil.traceResultingEither(CmdMetric))) + .get(); + +export const getStdoutMany = ( + cmds: ITraceable<Array<Command>, LogMetricTraceSupplier>, + options: Options = {}, +): Promise<IEither<Error, Array<string>>> => + cmds + .coExtend((t) => t.get()) + .reduce( + async (_result, tCmd) => { + const result = await _result; + return result.joinRightAsync( + () => tCmd.map((cmd) => getStdout(cmd, options)).get(), + (stdout, pre) => pre.concat(stdout), + ); + }, + Promise.resolve(Either.right<Error, Array<string>>([])), + ); |