diff options
Diffstat (limited to 'u/process')
-rw-r--r-- | u/process/env.ts | 2 | ||||
-rw-r--r-- | u/process/run.ts | 97 | ||||
-rw-r--r-- | u/process/validate_identifier.ts | 19 |
3 files changed, 74 insertions, 44 deletions
diff --git a/u/process/env.ts b/u/process/env.ts index c3ae800..26e1158 100644 --- a/u/process/env.ts +++ b/u/process/env.ts @@ -1,4 +1,4 @@ -import { Either, type IEither } from "@emprespresso/utils"; +import { Either, type IEither } from "@emprespresso/pengueno"; export const getRequiredEnv = (name: string): IEither<Error, string> => Either diff --git a/u/process/run.ts b/u/process/run.ts index 6dc37d0..670f567 100644 --- a/u/process/run.ts +++ b/u/process/run.ts @@ -1,40 +1,63 @@ -import { Either, type Traceable } from "@emprespresso/utils"; +import { + Either, + type IEither, + type ITraceable, + LogLevel, + TraceUtil, +} from "@emprespresso/pengueno"; + +type Command = string[] | string; +type CommandOutputDecoded = { + code: number; + stdoutText: string; + stderrText: string; +}; export class ProcessError extends Error {} -export const getStdout = async ( - { item: cmd, logger: _logger }: Traceable<string[] | string>, +export const getStdout = ( + c: ITraceable<Command>, options: Deno.CommandOptions = {}, -): Promise<Either<ProcessError, string>> => { - const logger = _logger.addTracer(() => "[getStdout]"); - - logger.log(`:> im gonna run this command!`, cmd); - const [exec, ...args] = (typeof cmd === "string") ? cmd.split(" ") : cmd; - const command = new Deno.Command(exec, { - args, - stdout: "piped", - stderr: "piped", - ...options, - }); - - try { - const { code, stdout, stderr } = await command.output(); - const stdoutText = new TextDecoder().decode(stdout); - const stderrText = new TextDecoder().decode(stderr); - - if (code !== 0) { - logger.error(`i weceived an exit code of ${code} i wanna zeroooo :<`); - return Either.left<ProcessError, string>( - new ProcessError(`command failed\n${stderrText}`), - ); - } - - logger.log("yay! i got code 0 :3", cmd); - return Either.right<ProcessError, string>(stdoutText); - } catch (e) { - logger.error(`o.o wat`, e); - if (e instanceof Error) { - return Either.left<ProcessError, string>(e); - } - throw new Error("unknown error " + e); - } -}; +): Promise<IEither<ProcessError, string>> => + c.bimap(TraceUtil.withFunctionTrace(getStdout)) + .map(({ item: cmd, trace }) => { + trace.trace(`:> im gonna run this command! ${cmd}`); + const [exec, ...args] = (typeof cmd === "string") ? cmd.split(" ") : cmd; + return new Deno.Command(exec, { + args, + stdout: "piped", + stderr: "piped", + ...options, + }).output(); + }) + .map(({ item: p }) => + Either.fromFailableAsync<Error, Deno.CommandOutput>(p) + ) + .map( + TraceUtil.promiseify(({ item: eitherOutput, trace }) => + eitherOutput.flatMap(({ code, stderr, stdout }) => + Either + .fromFailable<Error, CommandOutputDecoded>(() => { + const stdoutText = new TextDecoder().decode(stdout); + const stderrText = new TextDecoder().decode(stderr); + return { code, stdoutText, stderrText }; + }) + .mapLeft((e) => { + trace.addTrace(LogLevel.ERROR).trace(`o.o wat ${e}`); + return new ProcessError(`${e}`); + }) + .flatMap((decodedOutput): Either<ProcessError, string> => { + const { code, stdoutText, stderrText } = decodedOutput; + trace.addTrace(LogLevel.DEBUG).trace( + `stderr hehehe ${stderrText}`, + ); + if (code !== 0) { + const msg = + `i weceived an exit code of ${code} i wanna zewoooo :<`; + trace.addTrace(LogLevel.ERROR).trace(msg); + return Either.left(new ProcessError(msg)); + } + return Either.right(stdoutText); + }) + ) + ), + ).item; diff --git a/u/process/validate_identifier.ts b/u/process/validate_identifier.ts index ec8b77b..32952a6 100644 --- a/u/process/validate_identifier.ts +++ b/u/process/validate_identifier.ts @@ -1,4 +1,4 @@ -import { Either } from "./mod.ts"; +import { Either, type IEither } from "@emprespresso/pengueno"; export const validateIdentifier = (token: string) => { return (/^[a-zA-Z0-9_\-:. \/]+$/).test(token) && !token.includes(".."); @@ -6,11 +6,18 @@ export const validateIdentifier = (token: string) => { // ensure {@param obj} is a Record<string, string> with stuff that won't // have the potential for shell injection, just to be super safe. -export const validateExecutionEntries = ( - obj: Record<string, unknown>, -): Either<Array<[string, unknown]>, Record<string, string>> => { - const invalidEntries = Object.entries(obj).filter((e) => - !e.every((x) => typeof x === "string" && validateIdentifier(x)) +type InvalidEntry<K, T> = [K, T]; +export const validateExecutionEntries = < + T, + K extends symbol | number | string = symbol | number | string, +>( + obj: Record<K, T>, +): IEither< + Array<InvalidEntry<K, T>>, + Record<string, string> +> => { + const invalidEntries = <Array<InvalidEntry<K, T>>> Object.entries(obj).filter( + (e) => !e.every((x) => typeof x === "string" && validateIdentifier(x)), ); if (invalidEntries.length > 0) return Either.left(invalidEntries); return Either.right(<Record<string, string>> obj); |