aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoramankumarsingh77 <amankumarsingh7702@gmal.com>2026-05-02 15:31:01 +0530
committeramankumarsingh77 <amankumarsingh7702@gmal.com>2026-05-02 15:31:01 +0530
commit310d0a7324477079022b178f1a83161e9e61fb1d (patch)
tree69e7bbad57cdffe8e8e174fbd6b84fa88388a7fe
parent6759b6fd0ab435aa1e9fdb4591bd828b7a861a33 (diff)
feat(util): add result, time, and paths primitives for v0.3 rewrite
-rw-r--r--src/util/paths.ts9
-rw-r--r--src/util/result.ts15
-rw-r--r--src/util/time.ts29
3 files changed, 53 insertions, 0 deletions
diff --git a/src/util/paths.ts b/src/util/paths.ts
new file mode 100644
index 0000000..8cd9961
--- /dev/null
+++ b/src/util/paths.ts
@@ -0,0 +1,9 @@
+import { randomUUID } from "node:crypto";
+import { tmpdir } from "node:os";
+import { join } from "node:path";
+
+export const screenshotPath = (namespace: string, ext: "png" | "jpeg" = "png"): string =>
+ join(tmpdir(), `pi-browser-screenshot-${namespace}-${randomUUID()}.${ext}`);
+
+export const pdfPath = (namespace: string): string =>
+ join(tmpdir(), `pi-browser-pdf-${namespace}-${randomUUID()}.pdf`);
diff --git a/src/util/result.ts b/src/util/result.ts
new file mode 100644
index 0000000..ca57c2a
--- /dev/null
+++ b/src/util/result.ts
@@ -0,0 +1,15 @@
+export type Result<T, E> =
+ | { readonly success: true; readonly data: T }
+ | { readonly success: false; readonly error: E };
+
+export const ok = <T>(data: T): Result<T, never> => ({ success: true, data });
+export const err = <E>(error: E): Result<never, E> => ({ success: false, error });
+
+export const map = <T, U, E>(r: Result<T, E>, f: (t: T) => U): Result<U, E> =>
+ r.success ? ok(f(r.data)) : r;
+
+export const andThen = <T, U, E>(r: Result<T, E>, f: (t: T) => Result<U, E>): Result<U, E> =>
+ r.success ? f(r.data) : r;
+
+export const mapErr = <T, E, F>(r: Result<T, E>, f: (e: E) => F): Result<T, F> =>
+ r.success ? r : err(f(r.error));
diff --git a/src/util/time.ts b/src/util/time.ts
new file mode 100644
index 0000000..73990ad
--- /dev/null
+++ b/src/util/time.ts
@@ -0,0 +1,29 @@
+export const sleep = (ms: number, signal?: AbortSignal): Promise<void> =>
+ new Promise((resolve, reject) => {
+ if (signal?.aborted) {
+ reject(new Error("aborted"));
+ return;
+ }
+ const timer = setTimeout(() => {
+ signal?.removeEventListener("abort", onAbort);
+ resolve();
+ }, ms);
+ const onAbort = (): void => {
+ clearTimeout(timer);
+ reject(new Error("aborted"));
+ };
+ signal?.addEventListener("abort", onAbort, { once: true });
+ });
+
+export type Deadline = {
+ readonly remainingMs: () => number;
+ readonly expired: () => boolean;
+};
+
+export const deadline = (totalMs: number): Deadline => {
+ const end = Date.now() + totalMs;
+ return {
+ remainingMs: () => Math.max(0, end - Date.now()),
+ expired: () => Date.now() >= end,
+ };
+};