import { readFileSync } from 'node:fs'; import { join, resolve } from 'node:path'; import { Glob } from 'bun'; /* Which settings sections actually exist, read from the screens that declare them. Separated from `docs-check.ts` because it is the only check that parses source rather than importing it — the sections are JSX-adjacent object literals inside components, so importing them would drag React and a browser environment into a CLI. A regex over `BASE_PATH` and `key:` is the honest tool for that, and it is narrow enough to be obvious when it breaks. */ const ROOT = resolve(import.meta.dir, '..'); const SETTINGS_DIR = join(ROOT, 'src/apps/officer-web/Screens/Dashboard/Settings'); /** `/settings/profile` + `change-password` → `/settings/profile/change-password`. */ export async function declaredSettingsPaths(): Promise> { const paths = new Set(); const glob = new Glob('**/*.tsx'); for await (const file of glob.scan({ cwd: SETTINGS_DIR, absolute: true })) { const body = readFileSync(file, 'utf-8'); const base = /BASE_PATH\s*=\s*'([^']+)'/.exec(body)?.[1]; if (!base) continue; paths.add(base); for (const m of body.matchAll(/key:\s*'([^']+)'/g)) paths.add(`${base}/${m[1]}`); } return paths; } /** * Settings routes Spotlight offers, and which of them nothing declares. * * Parsed rather than imported for the same reason: `useSpotlightItems` is a hook and pulls in the dock, * lucide and React. */ export async function SPOTLIGHT_SETTINGS_PATHS(): Promise<{ offered: string[]; missing: string[] }> { const file = join(ROOT, 'src/apps/officer-web/Screens/Dashboard/Layout/Spotlight/useSpotlightItems.ts'); const body = readFileSync(file, 'utf-8'); const offered = [...body.matchAll(/to:\s*'(\/settings\/[^']+)'/g)].map((m) => m[1]!); const declared = await declaredSettingsPaths(); return { offered, missing: offered.filter((p) => !declared.has(p)) }; }