diff --git a/framework/font.ts b/framework/font.ts index c3935c292b4a7d7648ea0768b56470810f117189..d267bd4e48f97c30c26f86723b0dbe30ed0bd0eb 100644 --- a/framework/font.ts +++ b/framework/font.ts @@ -97,7 +97,7 @@ async function fetchProductionFontFiles( throw new Error(`Fetching fallback from ${url} failed: ${response.status} ${response.statusText}`); } } catch (err) { - throw new Error(`Fetching fallback from ${url} failed: ${error.message(err)}`); + throw new Error(`Fetching fallback from ${url} failed: ${exception.message(err)}`); } } @@ -137,7 +137,7 @@ export async function fetchFont(ref: progress.Ref, name: string, sources: string continue; } } catch (err) { - errs.push(`Fetching from ${source} failed: ${error.message(err)}`); + errs.push(`Fetching from ${source} failed: ${exception.message(err)}`); continue; } } @@ -386,7 +386,7 @@ import * as sg from "#sitegen"; import * as fs from "#sitegen/fs"; import { ASSERT } from "@clo/lib/assert"; import * as async from "@clo/lib/async"; -import * as error from "@clo/lib/error"; +import * as exception from "@clo/lib/exception"; import * as progress from "@clo/lib/progress"; import * as queue from "@clo/lib/queue"; import { readFile } from "node:fs/promises"; diff --git a/framework/generate.ts b/framework/generate.ts index 5d209a5bdc833674665b288334078a84caf81650..a5401f289a5122d3883c856c7cf9a94d72ba4bde 100644 --- a/framework/generate.ts +++ b/framework/generate.ts @@ -362,7 +362,7 @@ export async function preparePage( clientRefs: Array.from(cloverScripts), } as const; } catch (e) { - error.rethrowWithMetadata(e, { page: item.id }); + exception.rethrowWithMetadata(e, { page: item.id }); } } @@ -456,7 +456,7 @@ import * as path from "node:path"; import * as sg from "#sitegen"; import type { FileItem } from "#sitegen"; import * as fs from "#sitegen/fs"; -import * as error from "@clo/lib/error"; +import * as exception from "@clo/lib/exception"; import * as meta from "@clo/lib/meta"; import * as progress from "@clo/lib/progress"; diff --git a/framework/lib/path.ts b/framework/lib/path.ts index 2033131f3405f39ff8fda91b916a12453019a133..9007cab3699224c7f109728491b9d215f9e6bb90 100644 --- a/framework/lib/path.ts +++ b/framework/lib/path.ts @@ -131,7 +131,7 @@ export class Path { try { return this.readSync(encoding); } catch (err) { - if (error.code(err) === "ENOENT") return null; + if (exception.code(err) === "ENOENT") return null; throw err; } } @@ -159,7 +159,7 @@ export class Path { try { return await this.read(encoding); } catch (err) { - if (error.code(err) === "ENOENT") return null; + if (exception.code(err) === "ENOENT") return null; throw err; } } @@ -209,7 +209,7 @@ export class Path { } import { ASSERT } from "@clo/lib/assert"; -import * as error from "@clo/lib/error"; +import * as exception from "@clo/lib/exception"; import type { RmOptions } from "node:fs"; import * as path from "node:path"; import * as util from "node:util"; diff --git a/lib/error.ts b/lib/error.ts deleted file mode 100644 index a4f980f8c7e0d01260dd46b07894d9d01f24a215..0000000000000000000000000000000000000000 --- a/lib/error.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * helper functions for dealing with the `unknown` type, mainly in `catch` - * blocks or promise rejection callbacks. - * - * @module - */ - -/** extra fields on errors are extremely helpful for debugging. */ -export interface Error extends globalThis.Error { - [metadata: string]: unknown; -} - -/** retrieve an error message from any value */ -export function message(error: unknown): string { - let message = (error as { message: unknown })?.message ?? error; - try { - message = typeof message === "string" - ? message - // NOTE: typescript standard library lies here (https://github.com/mattpocock/ts-reset/pull/190) - : String(JSON.stringify(message) as string | undefined); - } catch {} - try { - return String(message); - } catch {} - return `Could not stringify error message ${typeof message}`; -} - -/** retrieve an error-like object from any value. Useful to check fields. */ -export function obj(error: unknown): { message: string } & Partial { - if (error instanceof Error) return error as Error; - return { - message: message(error), - ...(typeof error === "object" && error), - }; -} - -/** node.js error codes are string values on the `.code` property. */ -export function code(error: unknown): node.ErrorCode | null { - const code = (error as { code: unknown })?.code; - return typeof code === "string" ? code : null; -} - -/** attach extra fields and rethrow a value. */ -export function rethrowWithMetadata( - err: unknown, - meta: Record, -): never { - const error = err && typeof err === "object" ? err : new Error(message(err)); // no stack trace :/ - Object.assign(error, meta); - throw error; -} - -import type * as node from "./node.ts"; diff --git a/lib/exception.ts b/lib/exception.ts new file mode 100644 index 0000000000000000000000000000000000000000..a4f980f8c7e0d01260dd46b07894d9d01f24a215 --- /dev/null +++ b/lib/exception.ts @@ -0,0 +1,53 @@ +/** + * helper functions for dealing with the `unknown` type, mainly in `catch` + * blocks or promise rejection callbacks. + * + * @module + */ + +/** extra fields on errors are extremely helpful for debugging. */ +export interface Error extends globalThis.Error { + [metadata: string]: unknown; +} + +/** retrieve an error message from any value */ +export function message(error: unknown): string { + let message = (error as { message: unknown })?.message ?? error; + try { + message = typeof message === "string" + ? message + // NOTE: typescript standard library lies here (https://github.com/mattpocock/ts-reset/pull/190) + : String(JSON.stringify(message) as string | undefined); + } catch {} + try { + return String(message); + } catch {} + return `Could not stringify error message ${typeof message}`; +} + +/** retrieve an error-like object from any value. Useful to check fields. */ +export function obj(error: unknown): { message: string } & Partial { + if (error instanceof Error) return error as Error; + return { + message: message(error), + ...(typeof error === "object" && error), + }; +} + +/** node.js error codes are string values on the `.code` property. */ +export function code(error: unknown): node.ErrorCode | null { + const code = (error as { code: unknown })?.code; + return typeof code === "string" ? code : null; +} + +/** attach extra fields and rethrow a value. */ +export function rethrowWithMetadata( + err: unknown, + meta: Record, +): never { + const error = err && typeof err === "object" ? err : new Error(message(err)); // no stack trace :/ + Object.assign(error, meta); + throw error; +} + +import type * as node from "./node.ts"; diff --git a/lib/http.ts b/lib/http.ts index 2e14823c16d2429c1a158a200710767a8ad20346..46e8222956dc8627fdb83e4ec37466bca119c86c 100644 --- a/lib/http.ts +++ b/lib/http.ts @@ -82,7 +82,7 @@ export async function serve( const actualPort = await new Promise((resolve, reject) => { async function onError(err: unknown) { - if (error.code(err) !== "EADDRINUSE") { + if (exception.code(err) !== "EADDRINUSE") { reject(err); return; } @@ -168,7 +168,7 @@ export interface Range { import * as nodeHttp from "node:http"; import * as stream from "node:stream"; import { ASSERT, UNWRAP } from "./assert.ts"; -import * as error from "./error.ts"; +import * as exception from "./exception.ts"; import * as node from "./node.ts"; import * as progress from "./progress.ts"; import * as subprocess from "./subprocess.ts"; diff --git a/lib/log.ts b/lib/log.ts index 71b884eae08e4e1b2c6da2884e2dd2dde6de5ca6..0e850d87b36322605663ab1d8de8156cb7853961 100644 --- a/lib/log.ts +++ b/lib/log.ts @@ -603,7 +603,7 @@ export function createTerminalWidgetHost( height: rows, }); } catch (e) { - out = e instanceof Error ? stack.format(e, color) : errors.message(e); + out = e instanceof Error ? stack.format(e, color) : exceptions.message(e); } if (out == null) { widgets.splice(w, 1); @@ -1509,7 +1509,7 @@ export type MessageFormatFunction = ( import { ASSERT, UNWRAP } from "./assert.ts"; import * as async from "./async.ts"; -import * as errors from "./error.ts"; +import * as exceptions from "./exception.ts"; import * as stack from "./log/stack.ts"; import * as node from "./node.ts"; import * as ansi from "./string/ansi.ts"; diff --git a/lib/progress.ts b/lib/progress.ts index 1d32fdb4e04fc83895234b05e90f29b4cfbc5a58..40ef7c0b801c5d5f6081066571b512d82d389af4 100644 --- a/lib/progress.ts +++ b/lib/progress.ts @@ -987,7 +987,7 @@ export function encodeEventStream< emitNow(); })); stack.use(root.on("error", (error) => { - s.pendingEvents.push(["error", errors.message(error)]); + s.pendingEvents.push(["error", exceptions.message(error)]); s.ended = true; emitNow(); })); @@ -1857,7 +1857,7 @@ export const internals: { import { ASSERT, UNWRAP } from "./assert.ts"; import * as async from "./async.ts"; import * as bytes from "./bytes.ts"; -import * as errors from "./error.ts"; +import * as exceptions from "./exception.ts"; import { Events } from "./Events.ts"; import * as log from "./log.ts"; import * as stack from "./log/stack.ts"; diff --git a/src/file-viewer/cache.ts b/src/file-viewer/cache.ts index 2fdfc9df29b9d6cef9e3ae343f2a627d8ad41247..ce24b81971e9952a92bfe5cf1d276fb1237b77a3 100644 --- a/src/file-viewer/cache.ts +++ b/src/file-viewer/cache.ts @@ -127,7 +127,7 @@ export async function read( try { ({ size } = await localFile.stat()); } catch (err) { - if (error.code(err) === "ENOENT") { + if (exception.code(err) === "ENOENT") { console.warn(`missing local file: ${localFile}`); break local; } @@ -598,7 +598,7 @@ import * as fs from "#sitegen/fs"; import { Path } from "#sitegen/path"; import { ASSERT, UNWRAP } from "@clo/lib/assert"; import * as async from "@clo/lib/async"; -import * as error from "@clo/lib/error"; +import * as exception from "@clo/lib/exception"; import * as log from "@clo/lib/log"; import { Lru } from "@clo/lib/Lru"; import * as ts from "@clo/lib/ts"; diff --git a/src/file-viewer/indexer/scan.ts b/src/file-viewer/indexer/scan.ts index 4f1988bb1d2e40ed5978bd6b6c8ba3d9bb74645b..964af3c8d18a53ea15658d27a124d884a1f9629a 100644 --- a/src/file-viewer/indexer/scan.ts +++ b/src/file-viewer/indexer/scan.ts @@ -125,7 +125,7 @@ export class Scanner { try { stat = await path.stat(); } catch (err) { - if (error.code(err) !== "ENOENT") throw err; + if (exception.code(err) !== "ENOENT") throw err; // deleted; watcher events often describe files already gone this.#removePath(publicPath); return; @@ -308,7 +308,7 @@ export class Scanner { try { stat = await path.stat(); } catch (err) { - if (error.code(err) === "ENOENT") return null; + if (exception.code(err) === "ENOENT") return null; throw err; } } @@ -546,7 +546,7 @@ import * as path from "node:path"; import { Path } from "#sitegen/path"; import { ASSERT, UNWRAP } from "@clo/lib/assert"; import * as async from "@clo/lib/async"; -import * as error from "@clo/lib/error"; +import * as exception from "@clo/lib/exception"; import * as log from "@clo/lib/log"; import * as progress from "@clo/lib/progress"; import * as queue from "@clo/lib/queue";