diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/either.ts | 29 | ||||
-rw-r--r-- | utils/isObject.ts | 2 | ||||
-rw-r--r-- | utils/mod.ts | 1 | ||||
-rw-r--r-- | utils/run.ts | 11 | ||||
-rw-r--r-- | utils/trace.ts | 5 | ||||
-rw-r--r-- | utils/validate_identifier.ts | 12 |
6 files changed, 52 insertions, 8 deletions
diff --git a/utils/either.ts b/utils/either.ts index d21c796..10e4f43 100644 --- a/utils/either.ts +++ b/utils/either.ts @@ -5,14 +5,37 @@ export interface IEither<E, T> { errBranch: (e: E) => Ee, okBranch: (o: T) => Tt, ) => IEither<Ee, Tt>; + mapRight: <Tt>(mapper: (t: T) => Tt) => Either<E, Tt>; + mapLeft: <Ee>(mapper: (e: E) => Ee) => Either<Ee, T>; + flatMap: <Ee extends E, Tt>( + mapper: (e: T) => Either<Ee, Tt>, + ) => Either<Ee, Tt>; } export class Either<E, T> implements IEither<E, T> { private constructor(readonly err?: E, readonly ok?: T) {} - public mapBoth<Ee, Tt>(errBranch: (e: E) => Ee, okBranch: (t: T) => Tt) { - if (this.err) return new Either<Ee, Tt>(errBranch(this.err)); - return new Either<Ee, Tt>(undefined, okBranch(this.ok!)); + public mapBoth<Ee, Tt>( + errBranch: (e: E) => Ee, + okBranch: (t: T) => Tt, + ): Either<Ee, Tt> { + if (this.err) return Either.left(errBranch(this.err)); + return Either.right(okBranch(this.ok!)); + } + + public flatMap<Ee extends E, Tt>(mapper: (t: T) => Either<Ee, Tt>) { + if (this.ok) return mapper(this.ok); + return this; + } + + public mapRight<Tt>(mapper: (t: T) => Tt): Either<E, Tt> { + if (this.ok) return Either.right(mapper(this.ok)); + return Either.left(this.err!); + } + + public mapLeft<Ee>(mapper: (e: E) => Ee): Either<Ee, T> { + if (this.err) return Either.left(mapper(this.err)); + return Either.right(this.ok!); } static left<E, T>(e: E) { diff --git a/utils/isObject.ts b/utils/isObject.ts new file mode 100644 index 0000000..73f7f80 --- /dev/null +++ b/utils/isObject.ts @@ -0,0 +1,2 @@ +export const isObject = (o: unknown): o is object => + typeof o === "object" && !Array.isArray(o) && !!o; diff --git a/utils/mod.ts b/utils/mod.ts index 53ea173..d8cb526 100644 --- a/utils/mod.ts +++ b/utils/mod.ts @@ -1,3 +1,4 @@ +export * from "./isObject.ts"; export * from "./trace.ts"; export * from "./either.ts"; export * from "./env.ts"; diff --git a/utils/run.ts b/utils/run.ts index 06e7d9f..9093863 100644 --- a/utils/run.ts +++ b/utils/run.ts @@ -1,10 +1,13 @@ -import { Either } from "./mod.ts"; +import { Either, type Traceable } from "./mod.ts"; export class ProcessError extends Error {} export const getStdout = async ( - cmd: string[] | string, + { item: cmd, logger: _logger }: Traceable<string[] | string>, 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, @@ -19,12 +22,16 @@ export const getStdout = async ( 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); } diff --git a/utils/trace.ts b/utils/trace.ts index 373f37e..1a5e51d 100644 --- a/utils/trace.ts +++ b/utils/trace.ts @@ -31,6 +31,7 @@ export interface ITraceable<T, L extends ITraceableLogger<L>> { flatMapAsync<U>( mapper: ITraceableMapper<T, L, Promise<ITraceable<U, L>>>, ): ITraceable<Promise<U>, L>; + move<Tt>(t: Tt): ITraceable<Tt, L>; } export class TraceableLogger implements ITraceableLogger<TraceableLogger> { @@ -96,6 +97,10 @@ class TraceableImpl< return this; } + public move<Tt>(t: Tt) { + return this.map(() => t); + } + public bimap<U>(mapper: ITraceableMapper<T, L, ITraceableTuple<U>>) { const [item, trace] = mapper(this); return new TraceableImpl(item, this.logger.addTracer(trace)); diff --git a/utils/validate_identifier.ts b/utils/validate_identifier.ts index e2a1dc5..ec8b77b 100644 --- a/utils/validate_identifier.ts +++ b/utils/validate_identifier.ts @@ -1,11 +1,17 @@ +import { Either } from "./mod.ts"; + export const validateIdentifier = (token: string) => { return (/^[a-zA-Z0-9_\-:. \/]+$/).test(token) && !token.includes(".."); }; -export const invalidExecutionEntriesOf = ( +// 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>, -): Array<[string, unknown]> => { - return Object.entries(obj).filter((e) => +): Either<Array<[string, unknown]>, Record<string, string>> => { + 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(<Record<string, string>> obj); }; |