diff --git a/package-lock.json b/package-lock.json index c6a082f..be1aa15 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2720,9 +2720,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001702", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001702.tgz", - "integrity": "sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA==", + "version": "1.0.30001757", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz", + "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==", "dev": true, "funding": [ { diff --git a/src/lib/Toasts.svelte b/src/lib/Toasts.svelte new file mode 100644 index 0000000..e7f33e0 --- /dev/null +++ b/src/lib/Toasts.svelte @@ -0,0 +1,84 @@ + + + + +{#if currentToast != undefined} +
+ {currentToast.message} +
+{/if} + + diff --git a/src/lib/errors.test.ts b/src/lib/errors.test.ts new file mode 100644 index 0000000..ad09d9e --- /dev/null +++ b/src/lib/errors.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from "vitest"; +import { getErrorMessage } from "./errors"; + +describe("getErrorMessage", () => { + it("should return string unchanged", () => { + expect(getErrorMessage("example string")).toBe("example string"); + }); + + it("should get message from error", () => { + expect(getErrorMessage(new Error("example message"))).toBe("example message"); + }); +}); diff --git a/src/lib/errors.ts b/src/lib/errors.ts new file mode 100644 index 0000000..bfb4753 --- /dev/null +++ b/src/lib/errors.ts @@ -0,0 +1,42 @@ +import { showToast } from "./Toasts.svelte"; + +export function getErrorMessage(error: unknown): string { + if (typeof error == "string") { + return error; + } + + if ( + typeof error == "object" && + error != null && + "message" in error && + typeof error.message == "string" + ) { + return error.message; + } + + console.error("unknown error", error); + return String(error); +} + +export function toastError(error: unknown) { + console.error(error); + + const message = getErrorMessage(error); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-call -- this is just eslint getting confused by svelte + showToast({ message, style: "error" }); +} + +export async function assertOk(response: Response | Promise): Promise { + response = await response; + + if (response.ok) { + return response; + } + + if (response.headers.get("Content-Type")?.startsWith("application/json")) { + throw await response.json(); + } else { + throw await response.text(); + } +} diff --git a/src/lib/themes.css b/src/lib/themes.css index 5fba398..6ac48ab 100644 --- a/src/lib/themes.css +++ b/src/lib/themes.css @@ -1,7 +1,7 @@ :root { color-scheme: light dark; - background-color: light-dark(white, #121212); - color: light-dark(black, white); + background-color: var(--background-color); + color: var(--foreground-color); accent-color: var(--primary); --red: oklch(57% 0.26 28deg); @@ -12,4 +12,6 @@ --purple: oklch(48% 0.24 311deg); --pink: oklch(77% 0.19 356deg); --primary: light-dark(var(--blue), var(--aqua)); + --background-color: light-dark(white, #121212); + --foreground-color: light-dark(black, white); } diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index ce9bd52..e7cc81b 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -13,6 +13,8 @@ import Modal from "$lib/Modal.svelte"; import EditNameForm from "$lib/EditNameForm.svelte"; import AccountModal from "$lib/AccountModal.svelte"; + import Toasts from "$lib/Toasts.svelte"; + import { toastError } from "$lib/errors.js"; let { data, children } = $props(); let { supabase, session, user, profilePromise, lightModeCookie } = $derived(data); @@ -54,6 +56,11 @@ + toastError(event instanceof ErrorEvent ? event.error : event)} + onunhandledrejection={(event) => toastError(event.reason)} +/> +

Connexagon

@@ -78,6 +85,8 @@ {/if} + +