From dc4ac7742690f8f2bd759d57108ac4455e717fe9 Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Sun, 20 Jul 2025 13:03:39 -0700 Subject: Mount src directory from path on host running worker container --- u/process/env.ts | 24 ++++++++++------------ u/process/exec.ts | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ u/process/index.ts | 2 +- u/process/run.ts | 40 ------------------------------------ 4 files changed, 71 insertions(+), 54 deletions(-) create mode 100644 u/process/exec.ts delete mode 100644 u/process/run.ts (limited to 'u/process') diff --git a/u/process/env.ts b/u/process/env.ts index 88fb490..f59fadf 100644 --- a/u/process/env.ts +++ b/u/process/env.ts @@ -1,27 +1,25 @@ -import { IOptional, Either, Optional, type IEither } from '@emprespresso/pengueno'; +import { IOptional, Either, Optional, type IEither, type ObjectFromList } from '@emprespresso/pengueno'; -export const getEnv = (name: string): IOptional => Optional.from(process.env[name]); +// type safe environment variables -export const getRequiredEnv = (name: string): IEither => - Either.fromFailable(() => getEnv(name).get()).mapLeft( +export const getEnv = (name: string): IOptional => Optional.from(process.env[name]); + +export const getRequiredEnv = (name: V): IEither => + Either.fromFailable(() => getEnv(name).get()).mapLeft( () => new Error(`environment variable "${name}" is required D:`), ); -type ObjectFromList, V = string> = { - [K in T extends ReadonlyArray ? U : never]: V; -}; - -export const getRequiredEnvVars = (vars: Array) => { +export const getRequiredEnvVars = (vars: Array): IEither> => { type Environment = ObjectFromList; const emptyEnvironment = Either.right({}); - const addTo = (env: Environment, key: V) => (val: string) => + const addTo = (env: Environment, key: V, val: string) => { ...env, [key]: val, }; - return Either.joinRight( - vars, - (envVar: V, environment: Environment) => getRequiredEnv(envVar).mapRight(addTo(environment, envVar)), + return vars.reduce( + (environment, key) => + environment.joinRight(getRequiredEnv(key), (value, environment) => addTo(environment, key, value)), emptyEnvironment, ); }; 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; +type Options = { env?: Environment; clearEnv?: boolean }; +export const getStdout = ( + cmd: ITraceable, + options: Options = {}, +): Promise> => + 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(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, LogMetricTraceSupplier>, + options: Options = {}, +): Promise>> => + 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>([])), + ); diff --git a/u/process/index.ts b/u/process/index.ts index 6945a0f..2d74a5f 100644 --- a/u/process/index.ts +++ b/u/process/index.ts @@ -1,5 +1,5 @@ +export * from './exec.js'; export * from './env.js'; -export * from './run.js'; export * from './validate_identifier.js'; export * from './argv.js'; export * from './signals.js'; diff --git a/u/process/run.ts b/u/process/run.ts deleted file mode 100644 index 1d19129..0000000 --- a/u/process/run.ts +++ /dev/null @@ -1,40 +0,0 @@ -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(); -export const getStdout = ( - c: ITraceable, - options: { env?: Record; clearEnv?: boolean } = {}, -): Promise> => - c - .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(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(); -- cgit v1.2.3-70-g09d2