From a4a3bd556152950be95ca8df31787ed9f62f1717 Mon Sep 17 00:00:00 2001 From: josephine Date: Sat, 16 May 2026 14:35:48 +0200 Subject: [PATCH 1/7] feat: add error handling during loading game (#53) --- apps/client/src/server.ts | 57 ++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/apps/client/src/server.ts b/apps/client/src/server.ts index aa9da0e..ce6678e 100644 --- a/apps/client/src/server.ts +++ b/apps/client/src/server.ts @@ -76,27 +76,60 @@ const server = Bun.serve({ return new Response(file, { headers, }); - } catch { + } catch (error) { return new Response(null, { status: 404, }); } }, "/manifest": async () => { - await updateManifest(dir); - return Response.json(MANIFEST, { - headers, - }); + try { + await updateManifest(dir); + return Response.json(MANIFEST, { + headers, + }); + } catch (error) { + console.error("Erreur lors de la génération du manifest:", error); + return Response.json( + { error: "Failed to load manifest", details: String(error) }, + { status: 500, headers } + ); + } }, "/env": () => { - return Response.json(getGameEnv(), { headers }); + try { + const env = getGameEnv(); + return Response.json({ ...env, tlsEnabled: !!tls }, { headers }); + } catch (error) { + console.error("Failed to load environment:", error); + return Response.json( + { error: "Failed to load environment", details: String(error) }, + { status: 500, headers } + ); + } }, - "/game/*": (req) => { - const path = new URL(req.url).pathname.replace("/game", ""); - const file = Bun.file(join(dir, path)); - return new Response(file, { - headers, - }); + "/game/*": async (req) => { + try { + const path = new URL(req.url).pathname.replace("/game", ""); + const file = Bun.file(join(dir, path)); + + if (!(await file.exists())) { + return Response.json( + { error: "Game file not found", path }, + { status: 404, headers } + ); + } + + return new Response(file, { + headers, + }); + } catch (error) { + console.error(`Error reading game file ${req.url}:`, error); + return Response.json( + { error: "Error reading game file", details: String(error) }, + { status: 500, headers } + ); + } }, }, }); From 613c63c82269ab4297afb73685ffa10e4d451500 Mon Sep 17 00:00:00 2001 From: josephine Date: Sat, 16 May 2026 14:41:24 +0200 Subject: [PATCH 2/7] fix: unused variable(#53) --- apps/client/src/server.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/apps/client/src/server.ts b/apps/client/src/server.ts index ce6678e..4079078 100644 --- a/apps/client/src/server.ts +++ b/apps/client/src/server.ts @@ -76,7 +76,7 @@ const server = Bun.serve({ return new Response(file, { headers, }); - } catch (error) { + } catch { return new Response(null, { status: 404, }); @@ -91,8 +91,8 @@ const server = Bun.serve({ } catch (error) { console.error("Erreur lors de la génération du manifest:", error); return Response.json( - { error: "Failed to load manifest", details: String(error) }, - { status: 500, headers } + { error: "Failed to load manifest", details: String(error) }, + { status: 500, headers }, ); } }, @@ -103,8 +103,8 @@ const server = Bun.serve({ } catch (error) { console.error("Failed to load environment:", error); return Response.json( - { error: "Failed to load environment", details: String(error) }, - { status: 500, headers } + { error: "Failed to load environment", details: String(error) }, + { status: 500, headers }, ); } }, @@ -114,10 +114,7 @@ const server = Bun.serve({ const file = Bun.file(join(dir, path)); if (!(await file.exists())) { - return Response.json( - { error: "Game file not found", path }, - { status: 404, headers } - ); + return Response.json({ error: "Game file not found", path }, { status: 404, headers }); } return new Response(file, { @@ -126,8 +123,8 @@ const server = Bun.serve({ } catch (error) { console.error(`Error reading game file ${req.url}:`, error); return Response.json( - { error: "Error reading game file", details: String(error) }, - { status: 500, headers } + { error: "Error reading game file", details: String(error) }, + { status: 500, headers }, ); } }, From 3ab1a35e14eea481fd139725faa43d23376326d7 Mon Sep 17 00:00:00 2001 From: josephine Date: Sat, 16 May 2026 14:50:22 +0200 Subject: [PATCH 3/7] feat: handle runload error(#53) --- apps/website/src/index.ts | 5 +++++ apps/website/src/window.ts | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/website/src/index.ts b/apps/website/src/index.ts index 3c64905..29e067b 100644 --- a/apps/website/src/index.ts +++ b/apps/website/src/index.ts @@ -11,6 +11,11 @@ const logger = new Logger("Loader"); const runLoad = async () => { logger.info("Starting loading game"); + if (!window.isSecureContext) { + throw new Error( + "Storage issue: The game must be hosted with SSL (HTTPS) to enable local storage and load properly.", + ); + } const manifest = await getManifest(); runWatcher(manifest.watch); diff --git a/apps/website/src/window.ts b/apps/website/src/window.ts index 6c0031e..eacf1c2 100644 --- a/apps/website/src/window.ts +++ b/apps/website/src/window.ts @@ -37,11 +37,12 @@ export const setLoadingTotalFiles = (total: number) => { totalFiles = total; }; -export const setError = (error: string) => { +export const setError = (error: string | Error | unknown) => { const loaderErrorMessage = document.getElementById(IDS.loaderErrorMessage); if (!loaderErrorMessage) return; - loaderErrorMessage.innerText = error; + const errorMessage = error instanceof Error ? error.message : String(error); + loaderErrorMessage.innerText = errorMessage; setHiddenStatusOnId(IDS.loadingStatus, true); setHiddenStatusOnId(IDS.loaderError, false); From 9ac5aaa86b254bf9cc21d29dbd760a65b3cac1f4 Mon Sep 17 00:00:00 2001 From: josephine Date: Sat, 16 May 2026 14:54:41 +0200 Subject: [PATCH 4/7] feat: handle runtime error(#53) --- apps/website/src/index.ts | 10 ++++++++++ apps/website/src/window.ts | 3 +++ 2 files changed, 13 insertions(+) diff --git a/apps/website/src/index.ts b/apps/website/src/index.ts index 29e067b..991b999 100644 --- a/apps/website/src/index.ts +++ b/apps/website/src/index.ts @@ -27,6 +27,16 @@ const runLoad = async () => { runGame(mainModule, { files, env }); }; +window.addEventListener("error", (event) => { + setError(event.error || event.message); + logger.error(`Runtime error : ${event.message}`); +}); + +window.addEventListener("unhandledrejection", (event) => { + setError(event.reason); + logger.error(`Unhandled promise rejection : ${event.reason}`); +}); + runLoad() .then(() => { logger.info("Game loaded !"); diff --git a/apps/website/src/window.ts b/apps/website/src/window.ts index eacf1c2..b4a3996 100644 --- a/apps/website/src/window.ts +++ b/apps/website/src/window.ts @@ -44,6 +44,9 @@ export const setError = (error: string | Error | unknown) => { const errorMessage = error instanceof Error ? error.message : String(error); loaderErrorMessage.innerText = errorMessage; + setHiddenStatusOnId(IDS.container, true); + setHiddenStatusOnId(IDS.loader, false); + setHiddenStatusOnId(IDS.loadingStatus, true); setHiddenStatusOnId(IDS.loaderError, false); }; From fff1ac2e2e61d50c5db3faaf947871d07de80653 Mon Sep 17 00:00:00 2001 From: josephine Date: Sun, 17 May 2026 16:15:11 +0200 Subject: [PATCH 5/7] fix: console.error in french, switched in english --- apps/client/src/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/src/server.ts b/apps/client/src/server.ts index 4079078..371f226 100644 --- a/apps/client/src/server.ts +++ b/apps/client/src/server.ts @@ -89,7 +89,7 @@ const server = Bun.serve({ headers, }); } catch (error) { - console.error("Erreur lors de la génération du manifest:", error); + console.error("Failed to load manifest:", error); return Response.json( { error: "Failed to load manifest", details: String(error) }, { status: 500, headers }, From d199b2e9568800831a8271b85e7eb05212ec57d0 Mon Sep 17 00:00:00 2001 From: josephine Date: Sun, 17 May 2026 16:26:51 +0200 Subject: [PATCH 6/7] fix: parse 404 error to display missing file path in cache --- apps/website/src/cache/cache.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/apps/website/src/cache/cache.ts b/apps/website/src/cache/cache.ts index 6612519..55064cc 100644 --- a/apps/website/src/cache/cache.ts +++ b/apps/website/src/cache/cache.ts @@ -46,6 +46,22 @@ export class GameCache { private async _updateCacheFile(fileManifest: IManifestFile): Promise { const res = await fetch(`/game/${fileManifest.path.replace(/^\/+/, "")}`); + if (!res.ok) { + let errorMessage = `Failed to download file`; + try { + const errorData = await res.json(); + + if (errorData.path) { + errorMessage = `${errorData.error} : ${errorData.path}`; + } else { + errorMessage = errorData.error || `HTTP Error ${res.status}`; + } + } catch { + errorMessage = `HTTP Error ${res.status} on file ${fileManifest.path}`; + } + throw new Error(errorMessage); + } + const file = await this.fs.getFile(fileManifest.path); const writable = await file.getWritable(); From 3233ef8dce43aaa7d2924eb29dbfeedcbe07d302 Mon Sep 17 00:00:00 2001 From: josephine Date: Sun, 17 May 2026 16:29:41 +0200 Subject: [PATCH 7/7] fix: remove redundant variable initializer --- apps/website/src/cache/cache.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/website/src/cache/cache.ts b/apps/website/src/cache/cache.ts index 55064cc..f5d0236 100644 --- a/apps/website/src/cache/cache.ts +++ b/apps/website/src/cache/cache.ts @@ -47,7 +47,7 @@ export class GameCache { const res = await fetch(`/game/${fileManifest.path.replace(/^\/+/, "")}`); if (!res.ok) { - let errorMessage = `Failed to download file`; + let errorMessage: string; try { const errorData = await res.json();