From 3a256ccef5b223cc7fbe1d61195fa49e27609b1a Mon Sep 17 00:00:00 2001 From: Falkan Date: Tue, 17 Mar 2026 20:36:12 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20adminPath=20reroute=20=E2=80=94=20move?= =?UTF-8?q?=20to=20hooks.ts=20universal=20hook,=20read=20config.json=20dir?= =?UTF-8?q?ectly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks.server.ts | 30 ++------------------------ src/hooks.ts | 40 +++++++++++++++++++++++++++++++++++ src/routes/admin/+page.svelte | 2 ++ 3 files changed, 44 insertions(+), 28 deletions(-) create mode 100644 src/hooks.ts diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 756fe1e..c15fdc2 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -2,35 +2,9 @@ import { loadConfig } from '$lib/server/data'; import type { Handle } from '@sveltejs/kit'; /** - * Rewrites requests from the configured adminPath to the internal /admin route. - * - * Example: if adminPath = "secret-panel", then: - * /secret-panel → /admin - * /secret-panel/login → /admin/login - * /secret-panel/api/units → /admin/api/units - * - * If adminPath = "admin" (default), this is a no-op. + * handle: no URL rewriting here (that's reroute in hooks.ts). + * Kept as a placeholder for future server-only middleware. */ export const handle: Handle = async ({ event, resolve }) => { - const config = loadConfig(); - const adminPath = (config.adminPath ?? 'admin').replace(/^\/|\/$/g, ''); - - if (adminPath !== 'admin') { - const url = event.url; - const prefix = `/${adminPath}`; - - if (url.pathname === prefix || url.pathname.startsWith(prefix + '/')) { - // Rewrite the URL to use /admin internally - const rewritten = '/admin' + url.pathname.slice(prefix.length); - event.url = new URL(rewritten + url.search + url.hash, url.origin); - // Also update request.url so auth helpers see the rewritten path - Object.defineProperty(event.request, 'url', { - value: event.url.toString(), - writable: false, - configurable: true - }); - } - } - return resolve(event); }; diff --git a/src/hooks.ts b/src/hooks.ts new file mode 100644 index 0000000..3059b55 --- /dev/null +++ b/src/hooks.ts @@ -0,0 +1,40 @@ +import type { Reroute } from '@sveltejs/kit'; + +/** + * reroute: rewrites the configured adminPath to the internal /admin route. + * Reads config.json directly (not via $lib/server/data) so this universal + * hook can run server-side without triggering the browser-import guard. + * + * Example: adminPath = "boss" + * /boss → /admin + * /boss/login → /admin/login + * /boss/api/... → /admin/api/... + */ +export const reroute: Reroute = ({ url }) => { + // Only runs on the server — typeof window is undefined here during SSR/Node. + // In the browser, SvelteKit client-side routing never calls reroute for + // server routes, so this branch is safe to guard. + if (typeof window !== 'undefined') return url.pathname; + + try { + // Dynamic require so bundler doesn't try to resolve at build time + // eslint-disable-next-line @typescript-eslint/no-require-imports + const fs = require('fs') as typeof import('fs'); + // eslint-disable-next-line @typescript-eslint/no-require-imports + const path = require('path') as typeof import('path'); + const configPath = path.resolve('data', 'config.json'); + const config = JSON.parse(fs.readFileSync(configPath, 'utf8')) as { adminPath?: string }; + const adminPath = (config.adminPath ?? 'admin').replace(/^\/|\/$/g, ''); + + if (adminPath === 'admin') return url.pathname; + + const prefix = `/${adminPath}`; + if (url.pathname === prefix || url.pathname.startsWith(prefix + '/')) { + return '/admin' + url.pathname.slice(prefix.length); + } + } catch { + // If config can't be read, fall through to default routing + } + + return url.pathname; +}; diff --git a/src/routes/admin/+page.svelte b/src/routes/admin/+page.svelte index ebfe9f8..4cb9d17 100644 --- a/src/routes/admin/+page.svelte +++ b/src/routes/admin/+page.svelte @@ -771,6 +771,8 @@ > onUnitDragStart(e, unit.id, null)} ondragend={onUnitDragEnd}