summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/either.ts29
-rw-r--r--utils/isObject.ts2
-rw-r--r--utils/mod.ts1
-rw-r--r--utils/run.ts11
-rw-r--r--utils/trace.ts5
-rw-r--r--utils/validate_identifier.ts12
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);
};