feat(ui): scaffold the codegraph ui viewer as a Svelte 5 + Vite workspace (CG-40)
Adds `ui/` as an npm workspace (Svelte 5.56 + Vite 7, devDependencies only — the engine's runtime dependencies are untouched) and chains its build into `npm run build`, so the browser viewer ships inside `dist/` with everything else: `build-bundle.sh` already copies `dist` wholesale and `pack-npm.sh` packs that bundle. Output is `dist/viewer/`, NOT `dist/ui/`: `src/ui/` is the engine's terminal ui (shimmer progress + its worker) and tsc compiles it to `dist/ui/`, so emitting there both deletes those modules — the CLI then dies at startup with `Cannot find module '../ui/shimmer-progress'` — and would leave the static server handing out compiled engine internals. The design spec is corrected to match. `scripts/check-ui-build.mjs` is the release guard: index.html must exist, be non-trivial, and every local asset it references must be on disk, and the compiled engine next door must still be intact. It runs after every UI build, again in `build-bundle.sh` once the bundle stage has copied `dist`, and again in `pack-npm.sh` once each archive is unpacked — so a broken viewer fails the release instead of shipping a CLI that serves a 404. `vite build` does not override an ambient NODE_ENV, so a shell or runner with NODE_ENV=development silently shipped dev-mode Svelte (~13 kB of dev-only runtime checks, warning in the user's console). The config now pins production for `command === 'build'`; macOS and Windows ARM64 then emit byte-identical bundle hashes. The shell itself follows docs/design/codegraph-ui-design-spec.md §2–§3.1: design tokens as CSS custom properties (light on bare `:root`, dark under both `prefers-color-scheme` and `[data-theme="dark"]`), square corners, hairline rules, one oxblood accent; top bar 48px / trail bar 34px / main; a hash router over `#/s/<id>`, `#/file/<path>`, with `#/map` and `#/flow` reserved for phase 2. Fonts are vendored through @fontsource rather than fetched, so a local reader works offline and never announces the project to a CDN. Verified: clean `npm run build` from an empty dist on macOS and on the Windows ARM64 VM (forward-slash asset URLs, CLI still starts, both assertion failure modes exit 1); `dist/viewer` present in a real darwin-arm64 bundle and in the packed npm platform package; shell geometry, tokens, all seven routes, both themes and font loading checked in headless Chromium with no console errors; `npm test` unaffected.
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { defineConfig } from 'vite';
|
||||
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
||||
|
||||
// The viewer is emitted straight into the engine's `dist/` tree so it ships
|
||||
// with everything else: `build-bundle.sh` copies `dist` wholesale and
|
||||
// `pack-npm.sh` packs that bundle, so nothing extra has to be taught about it.
|
||||
//
|
||||
// NOT `dist/ui` — that name is already taken. `src/ui/` is the engine's
|
||||
// TERMINAL ui (shimmer progress + its worker) and tsc compiles it to
|
||||
// `dist/ui/`, so emitting here would both clobber it (emptyOutDir) and, worse,
|
||||
// leave the CLI serving compiled engine internals as static files.
|
||||
//
|
||||
// `fileURLToPath` (not a bare '../dist/viewer') keeps this a native path on
|
||||
// Windows, where Rollup resolves outDir against the platform separator.
|
||||
const outDir = fileURLToPath(new URL('../dist/viewer', import.meta.url));
|
||||
|
||||
export default defineConfig(({ command }) => {
|
||||
// `vite build` does NOT override an ambient NODE_ENV, and Svelte compiles in
|
||||
// dev mode when it sees one — a shell (or a CI runner) with
|
||||
// NODE_ENV=development silently ships a viewer carrying Svelte's dev-only
|
||||
// runtime checks: ~13 kB larger, slower, and warning in the user's console.
|
||||
// A release artifact must not depend on the machine that built it.
|
||||
if (command === 'build') process.env.NODE_ENV = 'production';
|
||||
|
||||
return {
|
||||
plugins: [svelte()],
|
||||
// Relative asset URLs: the CLI serves this at '/', but a relative base also
|
||||
// survives being opened from the filesystem or mounted under a sub-path.
|
||||
base: './',
|
||||
build: {
|
||||
// Scoped to dist/viewer — `emptyOutDir` must never be allowed to widen
|
||||
// to dist/, which holds the compiled engine tsc wrote moments earlier.
|
||||
outDir,
|
||||
emptyOutDir: true,
|
||||
target: 'es2022',
|
||||
// A localhost reader has the sources on disk already; sourcemaps would
|
||||
// double the bundle in every platform archive for no one's benefit.
|
||||
sourcemap: false,
|
||||
chunkSizeWarningLimit: 1024,
|
||||
},
|
||||
server: {
|
||||
host: '127.0.0.1',
|
||||
port: 5174,
|
||||
},
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user