W0 web foundation: Vite + React SPA under /app/, sync-pull ledger, auth, tokens, shared components
Build Kvitt images / build (push) Failing after 1h14m5s
Build Kvitt images / build (push) Failing after 1h14m5s
web/ is the browser client's scaffold: Vite 8, React 19, TypeScript 5.9 strict, React Router 7 (basename /app, every fixed route with a lazy placeholder page), TanStack Query 5 (refetch on focus and every 60 s), openapi-typescript types generated from contracts/openapi.yaml with openapi-fetch. Reads go through GET /sync (no REST reads exist for the ledger, SPEC §7): useLedger() pulls from cursor 0 and then incrementally, restarting on a new epoch or cursor_ahead. Login pairs the browser as "Web · <browser>" with an invite code (E-3); every call sends the SPEC §14.3.1 headers, a 401 signs out. kvitt-domain's split, balances, allocation and settlement rules are ported to web/src/lib and pass every case of contracts/test-vectors. Design tokens from design-spec §2 in tokens.css (light-dark()), Material Symbols Rounded (Apache-2.0) as generated inline SVG, sv/en catalogs generated from docs/ux/strings.csv plus web-strings.csv. Gate: cd web && npm run check. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
// Fails when a committed generated file differs from what its source gives (part of npm run check):
|
||||
// src/api/schema.d.ts from ../contracts/openapi.yaml, src/i18n/{sv,en}.json, src/design/icons.generated.ts.
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
|
||||
const web = new URL('../', import.meta.url);
|
||||
let failed = false;
|
||||
|
||||
const dir = mkdtempSync(join(tmpdir(), 'kvitt-web-api-'));
|
||||
try {
|
||||
const fresh = join(dir, 'schema.d.ts');
|
||||
execFileSync('npx', ['openapi-typescript', '../contracts/openapi.yaml', '-o', fresh], { cwd: web, stdio: 'pipe' });
|
||||
const committed = readFileSync(new URL('src/api/schema.d.ts', web), 'utf-8');
|
||||
if (readFileSync(fresh, 'utf-8') !== committed) {
|
||||
console.error('src/api/schema.d.ts is stale: run npm run api:types');
|
||||
failed = true;
|
||||
} else {
|
||||
console.log('src/api/schema.d.ts: up to date');
|
||||
}
|
||||
} finally {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
for (const script of ['scripts/gen-i18n.mjs', 'scripts/gen-icons.mjs']) {
|
||||
try {
|
||||
execFileSync(process.execPath, [script, '--check'], { cwd: web, stdio: 'inherit' });
|
||||
console.log(`${script}: up to date`);
|
||||
} catch (error) {
|
||||
console.error(`${script} --check failed: ${error instanceof Error ? error.message : String(error)}`);
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) process.exit(1);
|
||||
Reference in New Issue
Block a user