From 1d66a0f58e4ebcdf4f42c9d78f82a1ab49a2cf11 Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Tue, 13 May 2025 18:58:45 -0700 Subject: snapshot! --- u/process/env.ts | 10 ++++++++++ u/process/mod.ts | 3 +++ u/process/run.ts | 40 ++++++++++++++++++++++++++++++++++++++++ u/process/validate_identifier.ts | 17 +++++++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 u/process/env.ts create mode 100644 u/process/mod.ts create mode 100644 u/process/run.ts create mode 100644 u/process/validate_identifier.ts (limited to 'u/process') diff --git a/u/process/env.ts b/u/process/env.ts new file mode 100644 index 0000000..e80ec4a --- /dev/null +++ b/u/process/env.ts @@ -0,0 +1,10 @@ +import { Either, type IEither } from "@emprespresso/utils"; + +export const getRequiredEnv = (name: string): IEither => + Either.fromFailable(() => { + const value = Deno.env.get(name); // could throw when no permission. + if (!value) { + throw new Error(`environment variable "${name}" is required D:`); + } + return value; + }); diff --git a/u/process/mod.ts b/u/process/mod.ts new file mode 100644 index 0000000..3f02d46 --- /dev/null +++ b/u/process/mod.ts @@ -0,0 +1,3 @@ +export * from "./env.ts"; +export * from "./run.ts"; +export * from "./validate_identifier.ts"; diff --git a/u/process/run.ts b/u/process/run.ts new file mode 100644 index 0000000..6dc37d0 --- /dev/null +++ b/u/process/run.ts @@ -0,0 +1,40 @@ +import { Either, type Traceable } from "@emprespresso/utils"; + +export class ProcessError extends Error {} +export const getStdout = async ( + { item: cmd, logger: _logger }: Traceable, + options: Deno.CommandOptions = {}, +): Promise> => { + 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( + new ProcessError(`command failed\n${stderrText}`), + ); + } + + logger.log("yay! i got code 0 :3", cmd); + return Either.right(stdoutText); + } catch (e) { + logger.error(`o.o wat`, e); + if (e instanceof Error) { + return Either.left(e); + } + throw new Error("unknown error " + e); + } +}; diff --git a/u/process/validate_identifier.ts b/u/process/validate_identifier.ts new file mode 100644 index 0000000..ec8b77b --- /dev/null +++ b/u/process/validate_identifier.ts @@ -0,0 +1,17 @@ +import { Either } from "./mod.ts"; + +export const validateIdentifier = (token: string) => { + return (/^[a-zA-Z0-9_\-:. \/]+$/).test(token) && !token.includes(".."); +}; + +// ensure {@param obj} is a Record with stuff that won't +// have the potential for shell injection, just to be super safe. +export const validateExecutionEntries = ( + obj: Record, +): Either, Record> => { + const invalidEntries = Object.entries(obj).filter((e) => + !e.every((x) => typeof x === "string" && validateIdentifier(x)) + ); + if (invalidEntries.length > 0) return Either.left(invalidEntries); + return Either.right(> obj); +}; -- cgit v1.2.3-70-g09d2