From ce31a1e3432939fb763120cf1ce305fd1adf2cd0 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 28 Apr 2026 00:42:44 +0200 Subject: [PATCH] =?UTF-8?q?refactor(client):=20migrate=20ui-state.js=20?= =?UTF-8?q?=E2=86=92=20client/ui-state.ts=20(first=20real=20frontend=20mod?= =?UTF-8?q?ule=20conversion)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ui-state was the smallest, most isolated module: 35 lines, zero legacy- global dependencies, single concern (localStorage helpers under the 'ped_ui/' namespace). Ideal first migration to validate the strangler- fig pattern end-to-end. Changes: - New: client/ui-state.ts — exports get/set/del + UIState bundle. Keeps (window as any).UIState = UIState assignment so the 10+ legacy consumers (sub-nav.js, peGuide.js, app.js, etc.) keep working without modification. As each consumer is migrated, it will replace the window.UIState read with an explicit import. - client/main.ts: import './ui-state' so it gets bundled into main.js. - scripts/build-client.mjs: explicit ENTRIES list (just 'main.ts' for now) — was scanning every top-level .ts as an entry, which produced duplicate ui-state.js bundle. - public/index.html: - + diff --git a/public/js/ui-state.js b/public/js/ui-state.js deleted file mode 100644 index 9dc9d40..0000000 --- a/public/js/ui-state.js +++ /dev/null @@ -1,35 +0,0 @@ -// ============================================================ -// UI STATE — sub-pill / sub-tab persistence across browser restart -// ============================================================ -// Tab-level selection (ped_last_tab) is handled in app.js. This file -// persists the finer-grained choices that would otherwise reset to -// defaults when the user closes the browser, signs out / back in, or -// reloads the page — because _componentCache is in-memory and cleared -// on reload. -// -// All keys live under the "ped_ui/" namespace in localStorage so they -// are easy to enumerate and clear. Reads and writes are wrapped in -// try/catch — localStorage can throw in some contexts (Safari private -// mode, storage quotas), and a persistence failure must never break -// the UI. -// ============================================================ - -(function () { - var PREFIX = 'ped_ui/'; - - function get(key) { - try { return localStorage.getItem(PREFIX + key); } catch (e) { return null; } - } - function set(key, value) { - try { localStorage.setItem(PREFIX + key, value); } catch (e) {} - } - function del(key) { - try { localStorage.removeItem(PREFIX + key); } catch (e) {} - } - - window.UIState = { - get: get, - set: set, - del: del, - }; -})(); diff --git a/scripts/build-client.mjs b/scripts/build-client.mjs index 1ac54c2..4c2ebb4 100644 --- a/scripts/build-client.mjs +++ b/scripts/build-client.mjs @@ -31,17 +31,22 @@ if (!existsSync(SRC)) { } mkdirSync(OUT, { recursive: true }); -// Each top-level .ts/.tsx file in client/ is a separate entry point. -// Sub-directories are imported by the entries via TS imports — they -// are NOT separate entries, they get bundled into their parent. -const entryFiles = readdirSync(SRC, { withFileTypes: true }) - .filter(d => d.isFile() && /\.tsx?$/.test(d.name)) - .map(d => resolve(SRC, d.name)); +// Explicit entry list — every other .ts file in client/ is a sub-module +// imported by an entry. Add new entries here when a feature truly needs +// its own separate bundle (different DOM lifecycle, lazy-loaded route, +// etc.). For most modernization work, just import into main.ts. +const ENTRIES = [ + 'main.ts', +]; -if (entryFiles.length === 0) { - console.error(`[build-client] No .ts entry points found in ${SRC}`); - process.exit(1); -} +const entryFiles = ENTRIES.map(name => { + const p = resolve(SRC, name); + if (!existsSync(p)) { + console.error(`[build-client] Entry file does not exist: ${p}`); + process.exit(1); + } + return p; +}); const buildOpts = { entryPoints: entryFiles,