From 1c66bc0fcfd3f8f2ee89be5b2841867d963376f5 Mon Sep 17 00:00:00 2001 From: Elijah Duffy Date: Fri, 13 Feb 2026 16:28:25 -0800 Subject: [PATCH] improve error handling with 'builder'-type structure --- src/lib/ErrorBox.svelte | 22 +++++++++---- src/lib/error.ts | 68 ++++++++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 30 deletions(-) diff --git a/src/lib/ErrorBox.svelte b/src/lib/ErrorBox.svelte index e0aa28b..4f1c69a 100644 --- a/src/lib/ErrorBox.svelte +++ b/src/lib/ErrorBox.svelte @@ -1,18 +1,28 @@ -{#if error} - +{#if errorMessage && errorMessage.hasError()}
- {@html error.message} + {#each errorMessage.lines as line} +

{line}

+ {/each}
{/if} diff --git a/src/lib/error.ts b/src/lib/error.ts index b5a950e..c8d196e 100644 --- a/src/lib/error.ts +++ b/src/lib/error.ts @@ -10,20 +10,41 @@ export interface GraphError { export type RawError = Error | string | GraphError[]; export class ErrorMessage { - private _message: string; + private _lines: string[] = []; - /** converts a RawError to a string and stores it for later access */ - constructor(raw: RawError) { - this._message = ErrorMessage.rawErrorToString(raw); + /** + * Converts a RawError to an array of lines and stores it for later access, + * or initializes without any errors if the input is null or undefined. + * @param raw The raw error to convert and store, or null/undefined for no error. + * @throws If the raw error is of an unsupported type. + */ + constructor(raw: RawError | null | undefined) { + if (raw) { + this._lines = ErrorMessage.rawErrorToLines(raw); + } } - /** returns the stored message */ - get message(): string { - return this._message; + /** returns the stored lines */ + get lines(): string[] { + return this._lines; } - /** returns the error as a string */ + /** returns the error lines as a string, separated by newlines */ toString(): string { - return this._message; + return this._lines.join('\n'); + } + /** returns the error lines as an HTML string, separated by
*/ + toHTML(): string { + return this._lines.join('
'); + } + + /** returns true if there are any error lines */ + hasError(): boolean { + return this._lines.length > 0; + } + + /** adds a new line to the error message */ + addLine(line: string): void { + this._lines.push(line); } /** optionally returns a new ErrorMessage only if the RawError is not empty */ @@ -32,28 +53,27 @@ export class ErrorMessage { return new ErrorMessage(raw); } - /** converts a RawError to a string */ - static rawErrorToString(raw: RawError | null | undefined): string { - if (!raw) return 'No error'; + /** converts a RawError to an array of lines */ + static rawErrorToLines(raw: RawError | null | undefined): string[] { + if (!raw) return ['No error']; - let errorString: string; + let errorLines: string[]; if (typeof raw === 'string') { - errorString = raw; + errorLines = [raw]; } else if (raw instanceof Error) { - errorString = raw.message; + errorLines = [raw.message]; } else if (Array.isArray(raw)) { - errorString = raw - .flatMap((e) => { - const messageString = e.message || 'Unknown error'; - if (e.path && e.path.length > 0) { - return `"${messageString}" at ${e.path.join('.')}`; - } - }) - .join('
'); + errorLines = raw.map((e) => { + const messageString = e.message || 'Unknown error'; + if (e.path && e.path.length > 0) { + return `"${messageString}" at ${e.path.join('.')}`; + } + return messageString; + }); } else { throw `Bad error value ${raw}`; } - return errorString; + return errorLines; } }