@squadbase/vantage 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/{chunk-UHZ7XSAN.js → chunk-5UGRNXHC.js} +61 -21
- package/dist/chunk-5UGRNXHC.js.map +1 -0
- package/dist/cli.js +380 -30
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/vite/index.js +1 -1
- package/docs/en/changelog.md +71 -0
- package/docs/en/cli-reference.md +59 -5
- package/docs/en/components.md +2 -1
- package/docs/en/getting-started.md +6 -3
- package/docs/en/routing.md +27 -1
- package/docs/en/ui-and-theming.md +4 -2
- package/docs/ja/changelog.md +65 -0
- package/docs/ja/cli-reference.md +59 -5
- package/docs/ja/components.md +3 -2
- package/docs/ja/getting-started.md +6 -3
- package/docs/ja/routing.md +26 -1
- package/docs/ja/ui-and-theming.md +4 -2
- package/package.json +1 -1
- package/skills/vantage-add-feature/SKILL.md +26 -7
- package/skills/vantage-app/SKILL.md +9 -5
- package/templates/AGENTS.md +54 -8
- package/dist/chunk-UHZ7XSAN.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ You write `index.tsx`. Vantage owns routing, React, TanStack Query, Tailwind v4,
|
|
|
7
7
|
the UI kit, the dev server, the optional API server, and the build. There is no
|
|
8
8
|
config file.
|
|
9
9
|
|
|
10
|
-
> **Status: prototype (v0.
|
|
10
|
+
> **Status: prototype (v0.3.0).** APIs may still change between releases.
|
|
11
11
|
|
|
12
12
|
## Install
|
|
13
13
|
|
|
@@ -64,7 +64,7 @@ a bare `vantage dev` only works from inside an npm script, where
|
|
|
64
64
|
| `vantage build` | Production build → `dist/` (client + optional server + `vantage-manifest.json`) |
|
|
65
65
|
| `vantage preview` | Run the production build locally |
|
|
66
66
|
| `vantage check` | Static diagnostics (routes, boundaries, forbidden files). Exit 1 on error |
|
|
67
|
-
| `vantage routes` | Print the page + API URL map |
|
|
67
|
+
| `vantage routes` | Print the page + API URL map (`--pages` \| `--apis` for one side, `--detail` for each route's spec) |
|
|
68
68
|
| `vantage add <kind> <name>` | Scaffold a `page` \| `api`, or copy an editable `ui` \| `block`, agent `skill` \| `agents` file |
|
|
69
69
|
| `vantage docs [name]` | Print the bundled guide + component reference (`--list`, `--all`, `--json`, `--lang`) |
|
|
70
70
|
| `vantage search <query>` | Search that same reference by meaning (BM25) or by `--regex` (`--limit`, `--json`, `--lang`) |
|
|
@@ -12,6 +12,7 @@ import { getRequestListener } from '@hono/node-server';
|
|
|
12
12
|
|
|
13
13
|
// src/core/constants.ts
|
|
14
14
|
var VANTAGE_DIR = ".vantage";
|
|
15
|
+
var SRC_DIR = "src";
|
|
15
16
|
var NON_ROUTE_DIRS = /* @__PURE__ */ new Set([
|
|
16
17
|
"components",
|
|
17
18
|
"hooks",
|
|
@@ -22,6 +23,31 @@ var NON_ROUTE_DIRS = /* @__PURE__ */ new Set([
|
|
|
22
23
|
VANTAGE_DIR,
|
|
23
24
|
"dist"
|
|
24
25
|
]);
|
|
26
|
+
var SUSPICIOUS_ROUTE_DIRS = /* @__PURE__ */ new Set([
|
|
27
|
+
SRC_DIR,
|
|
28
|
+
"app",
|
|
29
|
+
"pages",
|
|
30
|
+
"routes",
|
|
31
|
+
"views",
|
|
32
|
+
"screens",
|
|
33
|
+
"features",
|
|
34
|
+
"containers",
|
|
35
|
+
"modules",
|
|
36
|
+
"layouts",
|
|
37
|
+
"utils",
|
|
38
|
+
"types",
|
|
39
|
+
"styles",
|
|
40
|
+
"assets",
|
|
41
|
+
"store",
|
|
42
|
+
"stores",
|
|
43
|
+
"context",
|
|
44
|
+
"contexts",
|
|
45
|
+
"providers",
|
|
46
|
+
"api",
|
|
47
|
+
"test",
|
|
48
|
+
"tests",
|
|
49
|
+
"__tests__"
|
|
50
|
+
]);
|
|
25
51
|
var PAGE_EXTENSIONS = [".tsx", ".jsx"];
|
|
26
52
|
var API_EXTENSIONS = [".ts", ".tsx", ".js"];
|
|
27
53
|
var RESERVED_PAGE_NAMES = {
|
|
@@ -297,12 +323,13 @@ import "./runtime.css"
|
|
|
297
323
|
bootstrap(manifest)
|
|
298
324
|
`;
|
|
299
325
|
}
|
|
300
|
-
function renderRuntimeCss(root) {
|
|
326
|
+
function renderRuntimeCss(root, pageDir) {
|
|
301
327
|
const parts = [];
|
|
302
328
|
parts.push('@import "tailwindcss";');
|
|
303
329
|
parts.push(`@import "${PKG}/theme.css";`);
|
|
304
|
-
|
|
305
|
-
|
|
330
|
+
const stylesRel = pageDir === "" ? "styles.css" : `${pageDir}/styles.css`;
|
|
331
|
+
if (fs2.existsSync(path3.join(root, stylesRel))) {
|
|
332
|
+
parts.push(`@import "../${stylesRel}";`);
|
|
306
333
|
}
|
|
307
334
|
const vantageDir = resolveVantageDir(root);
|
|
308
335
|
if (vantageDir) {
|
|
@@ -335,6 +362,7 @@ function renderInternalManifest(model) {
|
|
|
335
362
|
return JSON.stringify(
|
|
336
363
|
{
|
|
337
364
|
schemaVersion: MANIFEST_SCHEMA_VERSION,
|
|
365
|
+
pageDir: model.pageDir,
|
|
338
366
|
pages: model.pages.map((p) => ({ file: p.file, route: p.routePath })),
|
|
339
367
|
apis: model.apis.map((a) => ({ file: a.file, route: a.routePath })),
|
|
340
368
|
hasServer: model.hasServer
|
|
@@ -351,7 +379,7 @@ function generateArtifacts({ root, model }) {
|
|
|
351
379
|
writeIfChanged(path3.join(vantageDir, "index.html"), renderIndexHtml());
|
|
352
380
|
writeIfChanged(path3.join(vantageDir, "client-entry.tsx"), renderClientEntry());
|
|
353
381
|
writeIfChanged(path3.join(vantageDir, "route-tree.gen.ts"), renderRouteTree(model));
|
|
354
|
-
writeIfChanged(path3.join(vantageDir, "runtime.css"), renderRuntimeCss(root));
|
|
382
|
+
writeIfChanged(path3.join(vantageDir, "runtime.css"), renderRuntimeCss(root, model.pageDir));
|
|
355
383
|
writeIfChanged(path3.join(vantageDir, "types", "env.d.ts"), renderEnvTypes());
|
|
356
384
|
writeIfChanged(path3.join(vantageDir, "manifest.json"), renderInternalManifest(model));
|
|
357
385
|
if (model.hasServer) {
|
|
@@ -410,30 +438,39 @@ function walk(dir, root, out) {
|
|
|
410
438
|
}
|
|
411
439
|
}
|
|
412
440
|
}
|
|
413
|
-
function
|
|
441
|
+
function resolvePageRoot(root) {
|
|
442
|
+
const abs = path3.join(root, SRC_DIR);
|
|
443
|
+
try {
|
|
444
|
+
if (fs2.statSync(abs).isDirectory()) return { dir: SRC_DIR, abs };
|
|
445
|
+
} catch {
|
|
446
|
+
}
|
|
447
|
+
return { dir: "", abs: root };
|
|
448
|
+
}
|
|
449
|
+
function scanPages(root, pageRoot) {
|
|
414
450
|
const files = [];
|
|
415
|
-
walk(
|
|
451
|
+
walk(pageRoot, pageRoot, files);
|
|
416
452
|
const pages = [];
|
|
417
453
|
const layouts = [];
|
|
418
454
|
let notFound = null;
|
|
419
455
|
let error = null;
|
|
420
456
|
for (const abs of files) {
|
|
421
|
-
const
|
|
457
|
+
const file = toPosix(root, abs);
|
|
458
|
+
const rel = toPosix(pageRoot, abs);
|
|
422
459
|
const base = path3.posix.basename(rel);
|
|
423
460
|
if (!hasExt(base, PAGE_EXTENSIONS)) continue;
|
|
424
461
|
const nameNoExt = stripExt(base, PAGE_EXTENSIONS);
|
|
425
462
|
const dir = path3.posix.dirname(rel);
|
|
426
463
|
const dirPosix = dir === "." ? "" : dir;
|
|
427
464
|
if (nameNoExt === RESERVED_PAGE_NAMES.layout) {
|
|
428
|
-
layouts.push({ file
|
|
465
|
+
layouts.push({ file, absFile: abs, dir: dirPosix });
|
|
429
466
|
continue;
|
|
430
467
|
}
|
|
431
468
|
if (nameNoExt === RESERVED_PAGE_NAMES.notFound) {
|
|
432
|
-
if (dirPosix === "") notFound =
|
|
469
|
+
if (dirPosix === "") notFound = file;
|
|
433
470
|
continue;
|
|
434
471
|
}
|
|
435
472
|
if (nameNoExt === RESERVED_PAGE_NAMES.error) {
|
|
436
|
-
if (dirPosix === "") error =
|
|
473
|
+
if (dirPosix === "") error = file;
|
|
437
474
|
continue;
|
|
438
475
|
}
|
|
439
476
|
if (nameNoExt.startsWith("_")) continue;
|
|
@@ -441,7 +478,7 @@ function scanPages(root) {
|
|
|
441
478
|
const segments = fileToSegments(relNoExt);
|
|
442
479
|
const routePath = displayPath(segments);
|
|
443
480
|
const dynamic = segments.some((s) => s.kind !== "static");
|
|
444
|
-
pages.push({ file
|
|
481
|
+
pages.push({ file, absFile: abs, routePath, segments, dir: dirPosix, dynamic });
|
|
445
482
|
}
|
|
446
483
|
pages.sort((a, b) => routeSortKey(a).localeCompare(routeSortKey(b)));
|
|
447
484
|
layouts.sort((a, b) => a.dir.localeCompare(b.dir));
|
|
@@ -496,10 +533,11 @@ function scanApis(root) {
|
|
|
496
533
|
return apis;
|
|
497
534
|
}
|
|
498
535
|
function scanProject(root) {
|
|
499
|
-
const
|
|
536
|
+
const pageRoot = resolvePageRoot(root);
|
|
537
|
+
const { pages, layouts, notFound, error } = scanPages(root, pageRoot.abs);
|
|
500
538
|
const hasServer = fs2.existsSync(path3.join(root, "server"));
|
|
501
539
|
const apis = hasServer ? scanApis(root) : [];
|
|
502
|
-
return { pages, layouts, notFound, error, apis, hasServer };
|
|
540
|
+
return { pages, layouts, notFound, error, apis, hasServer, pageDir: pageRoot.dir };
|
|
503
541
|
}
|
|
504
542
|
function createApiDevMiddleware(opts) {
|
|
505
543
|
const { server, getModel, getEnv } = opts;
|
|
@@ -556,8 +594,8 @@ function createApiDevMiddleware(opts) {
|
|
|
556
594
|
|
|
557
595
|
// src/vite/index.ts
|
|
558
596
|
var DEDUPE = ["react", "react-dom", "@tanstack/react-router", "@tanstack/react-query"];
|
|
559
|
-
function isPageFile(
|
|
560
|
-
const rel = path3.relative(
|
|
597
|
+
function isPageFile(pageRoot, file) {
|
|
598
|
+
const rel = path3.relative(pageRoot, file);
|
|
561
599
|
if (rel.startsWith("..")) return false;
|
|
562
600
|
const segments = rel.split(path3.sep);
|
|
563
601
|
if (segments.some((s) => NON_ROUTE_DIRS.has(s) || s.startsWith(".") && s !== "..")) return false;
|
|
@@ -575,6 +613,7 @@ function vantagePlugin(options) {
|
|
|
575
613
|
const root = path3.resolve(options.root);
|
|
576
614
|
const vantageDir = path3.join(root, VANTAGE_DIR);
|
|
577
615
|
let model = scanProject(root);
|
|
616
|
+
const pageRoot = () => model.pageDir === "" ? root : path3.join(root, model.pageDir);
|
|
578
617
|
const regenerate = () => {
|
|
579
618
|
model = scanProject(root);
|
|
580
619
|
generateArtifacts({ root, model });
|
|
@@ -640,7 +679,7 @@ function vantagePlugin(options) {
|
|
|
640
679
|
// preserved (6 spaces for "export") so sourcemaps stay accurate.
|
|
641
680
|
transform(code, id) {
|
|
642
681
|
const clean = id.split("?")[0];
|
|
643
|
-
if (!isPageFile(
|
|
682
|
+
if (!isPageFile(pageRoot(), clean)) return null;
|
|
644
683
|
if (!/export\s+const\s+page\b/.test(code)) return null;
|
|
645
684
|
const out = code.replace(
|
|
646
685
|
/^([ \t]*)export(\s+const\s+page\b)/gm,
|
|
@@ -675,9 +714,10 @@ function vantagePlugin(options) {
|
|
|
675
714
|
if (model.hasServer) return apiMw(req, res, next);
|
|
676
715
|
return next();
|
|
677
716
|
});
|
|
678
|
-
const isStylesFile = (file) => path3.relative(
|
|
717
|
+
const isStylesFile = (file) => path3.relative(pageRoot(), file) === "styles.css";
|
|
679
718
|
const onStructural = (file) => {
|
|
680
|
-
|
|
719
|
+
const rootMoved = resolvePageRoot(root).dir !== model.pageDir;
|
|
720
|
+
if (rootMoved || isPageFile(pageRoot(), file) || isApiFile(root, file) || isStylesFile(file)) {
|
|
681
721
|
regenerate();
|
|
682
722
|
server.ws.send({ type: "full-reload" });
|
|
683
723
|
}
|
|
@@ -757,6 +797,6 @@ function handleConsoleBeacon(req, res) {
|
|
|
757
797
|
});
|
|
758
798
|
}
|
|
759
799
|
|
|
760
|
-
export { API_METHODS, FORBIDDEN_FILES, MANIFEST_SCHEMA_VERSION, PAGE_EXTENSIONS, PUBLIC_ENV_PREFIX, VANTAGE_DIR, generateArtifacts, scanProject, vantagePlugin };
|
|
761
|
-
//# sourceMappingURL=chunk-
|
|
762
|
-
//# sourceMappingURL=chunk-
|
|
800
|
+
export { API_METHODS, FORBIDDEN_FILES, MANIFEST_SCHEMA_VERSION, PAGE_EXTENSIONS, PUBLIC_ENV_PREFIX, SRC_DIR, SUSPICIOUS_ROUTE_DIRS, VANTAGE_DIR, extractPageMeta, generateArtifacts, resolvePageRoot, scanProject, vantagePlugin };
|
|
801
|
+
//# sourceMappingURL=chunk-5UGRNXHC.js.map
|
|
802
|
+
//# sourceMappingURL=chunk-5UGRNXHC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/constants.ts","../src/core/route-tree.ts","../src/core/generate.ts","../src/core/scan.ts","../src/server/dev.ts","../src/vite/index.ts"],"names":["depth","fs","path","require"],"mappings":"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","file":"chunk-5UGRNXHC.js","sourcesContent":["/**\n * Framework-wide constants: naming conventions and reserved paths.\n * These encode the \"convention over configuration\" contract from the design.\n */\n\n/** Directory that holds all generated, hidden artifacts. */\nexport const VANTAGE_DIR = \".vantage\"\n\n/**\n * Optional directory holding the app's client source. When it exists, it is the\n * one and only page-scan root; when it does not, pages live at the project root.\n * Both layouts are supported so a single-file app stays a single file, while an\n * app (or a coding agent) that reaches for the near-universal `src/` convention\n * gets routes that make sense instead of a `/src/...` prefix on every page.\n */\nexport const SRC_DIR = \"src\"\n\n/** Directories that are never scanned for pages. */\nexport const NON_ROUTE_DIRS = new Set([\n \"components\",\n \"hooks\",\n \"lib\",\n \"server\",\n \"public\",\n \"node_modules\",\n VANTAGE_DIR,\n \"dist\",\n])\n\n/**\n * Directory names that almost always mean \"framework scaffolding\", not \"a URL\n * segment\". Page scanning is a denylist (`NON_ROUTE_DIRS`), so any directory\n * not on it becomes part of the route path — `pages/sales.tsx` silently serves\n * `/pages/sales`. These names are still scanned (they may be deliberate), but\n * routes coming out of them raise `SUSPICIOUS_ROUTE_DIR`.\n */\nexport const SUSPICIOUS_ROUTE_DIRS = new Set([\n SRC_DIR,\n \"app\",\n \"pages\",\n \"routes\",\n \"views\",\n \"screens\",\n \"features\",\n \"containers\",\n \"modules\",\n \"layouts\",\n \"utils\",\n \"types\",\n \"styles\",\n \"assets\",\n \"store\",\n \"stores\",\n \"context\",\n \"contexts\",\n \"providers\",\n \"api\",\n \"test\",\n \"tests\",\n \"__tests__\",\n])\n\n/** File extensions treated as page modules. */\nexport const PAGE_EXTENSIONS = [\".tsx\", \".jsx\"]\n\n/** File extensions treated as server API modules. */\nexport const API_EXTENSIONS = [\".ts\", \".tsx\", \".js\"]\n\n/** Reserved page filenames (without extension). */\nexport const RESERVED_PAGE_NAMES = {\n layout: \"_layout\",\n notFound: \"_404\",\n error: \"_error\",\n} as const\n\n/** HTTP methods that an API module may export. */\nexport const API_METHODS = [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"] as const\nexport type ApiMethod = (typeof API_METHODS)[number]\n\n/**\n * Files that must not exist in a Vantage project. Their presence means the\n * user is trying to escape the managed stack, which v1 forbids.\n */\nexport const FORBIDDEN_FILES: { pattern: RegExp; label: string; remedy: string }[] = [\n {\n pattern: /^vite\\.config\\.(ts|js|mjs|cjs|mts|cts)$/,\n label: \"Vite config\",\n remedy: \"Vantage owns the Vite configuration. Remove this file.\",\n },\n {\n pattern: /^tailwind\\.config\\.(ts|js|mjs|cjs)$/,\n label: \"Tailwind config\",\n remedy: \"Customize theme tokens in styles.css instead.\",\n },\n {\n pattern: /^postcss\\.config\\.(ts|js|mjs|cjs)$/,\n label: \"PostCSS config\",\n remedy: \"Vantage manages PostCSS/Tailwind. Remove this file.\",\n },\n {\n pattern: /^components\\.json$/,\n label: \"shadcn components.json\",\n remedy: \"Use `vantage add ui <name>` to copy UI source instead.\",\n },\n {\n pattern: /^vantage\\.config\\.(ts|js|mjs|cjs)$/,\n label: \"Vantage config\",\n remedy: \"v1 has no vantage.config. Configuration lives in file conventions.\",\n },\n]\n\n/** Public env var prefix exposed to the client bundle. */\nexport const PUBLIC_ENV_PREFIX = \"PUBLIC_\"\n\n/** Manifest schema version emitted into build output. */\nexport const MANIFEST_SCHEMA_VERSION = 1\n","import fs from \"node:fs\"\nimport type { RouteModel, Segment } from \"./types\"\n\n/** A layout route (path-bearing) in the built tree. */\nexport interface BuiltLayout {\n id: string\n dir: string\n parentId: string | null\n /** Router path relative to its parent (TanStack `$param` form). */\n path: string\n file: string\n}\n\n/** A page route in the built tree. */\nexport interface BuiltPage {\n file: string\n routePath: string\n parentLayoutId: string | null\n /** Router path relative to parent, or \"/\" for an index route. */\n path: string\n index: boolean\n title?: string\n description?: string\n navLabel?: string\n}\n\n/** The structured route tree emitted for the client runtime. */\nexport interface BuiltTree {\n rootLayout: string | null\n notFound: string | null\n error: string | null\n layouts: BuiltLayout[]\n pages: BuiltPage[]\n}\n\nfunction segToRouter(s: Segment): string {\n if (s.kind === \"static\") return s.value\n if (s.kind === \"param\") return `$${s.name}`\n return \"$\"\n}\n\n/** Convert a relative directory string (may contain `[param]`) to a router path. */\nfunction dirToRouterPath(relDir: string): string {\n return relDir\n .split(\"/\")\n .filter(Boolean)\n .map((token) => {\n const catchall = token.match(/^\\[\\.\\.\\.(.+)\\]$/)\n if (catchall) return \"$\"\n const param = token.match(/^\\[(.+)\\]$/)\n if (param) return `$${param[1]}`\n return token\n })\n .join(\"/\")\n}\n\nfunction isAncestorDir(ancestor: string, dir: string): boolean {\n if (ancestor === \"\") return true\n return dir === ancestor || dir.startsWith(ancestor + \"/\")\n}\n\nfunction isStrictAncestorDir(ancestor: string, dir: string): boolean {\n return dir.startsWith(ancestor + \"/\")\n}\n\nfunction depth(dir: string): number {\n return dir === \"\" ? 0 : dir.split(\"/\").length\n}\n\n/**\n * Extract the argument object body of the first `definePage({ ... })` call\n * using balanced-brace scanning, so nested objects/functions (e.g.\n * `validateSearch: (s) => ({ ... })`) don't truncate the match. Returns null\n * when there is no definePage call — the caller then emits no metadata rather\n * than falling back to the whole file (which would match unrelated `title:`\n * keys in chart/option configs).\n */\nfunction extractDefinePageArgs(src: string): string | null {\n const call = src.match(/\\bdefinePage\\s*\\(/)\n if (!call) return null\n let i = (call.index ?? 0) + call[0].length\n while (i < src.length && /\\s/.test(src[i]!)) i++\n if (src[i] !== \"{\") return null\n const start = i\n let depth = 0\n for (; i < src.length; i++) {\n const c = src[i]\n if (c === \"{\") depth++\n else if (c === \"}\" && --depth === 0) return src.slice(start + 1, i)\n }\n return null\n}\n\n/**\n * Match `key: \"...\"` allowing the value's own quote character to differ and\n * handling escapes, so values containing an apostrophe/quote are not truncated.\n */\nfunction matchStringField(scope: string, key: string): string | undefined {\n const re = new RegExp(\n `\\\\b${key}\\\\s*:\\\\s*(?:\"((?:\\\\\\\\.|[^\"\\\\\\\\])*)\"|'((?:\\\\\\\\.|[^'\\\\\\\\])*)'|\\`((?:\\\\\\\\.|[^\\`\\\\\\\\])*)\\`)`,\n )\n const m = scope.match(re)\n if (!m) return undefined\n return (m[1] ?? m[2] ?? m[3] ?? \"\").replace(/\\\\(.)/g, \"$1\")\n}\n\n/** Best-effort static extraction of definePage title/description/navLabel. */\nexport function extractPageMeta(absFile: string): {\n title?: string\n description?: string\n navLabel?: string\n} {\n let src: string\n try {\n src = fs.readFileSync(absFile, \"utf8\")\n } catch {\n return {}\n }\n const args = extractDefinePageArgs(src)\n if (args == null) return {}\n const meta: { title?: string; description?: string; navLabel?: string } = {}\n const title = matchStringField(args, \"title\")\n const description = matchStringField(args, \"description\")\n const navLabel = matchStringField(args, \"navLabel\")\n if (title) meta.title = title\n if (description) meta.description = description\n if (navLabel) meta.navLabel = navLabel\n return meta\n}\n\n/**\n * Build the structured route tree from a scan. Layouts become path-bearing\n * routes; pages attach to the deepest layout that owns their directory.\n */\nexport function buildRouteTree(model: RouteModel): BuiltTree {\n const rootLayoutRoute = model.layouts.find((l) => l.dir === \"\") ?? null\n const nestedLayouts = model.layouts\n .filter((l) => l.dir !== \"\")\n .sort((a, b) => depth(a.dir) - depth(b.dir))\n\n const built: BuiltLayout[] = []\n const dirToId = new Map<string, string>()\n\n nestedLayouts.forEach((layout, i) => {\n const id = `L${i}`\n // Parent = deepest other layout that is a strict ancestor of this dir.\n let parent: { id: string; dir: string } | null = null\n for (const cand of built) {\n if (isStrictAncestorDir(cand.dir, layout.dir)) {\n if (!parent || depth(cand.dir) > depth(parent.dir)) parent = { id: cand.id, dir: cand.dir }\n }\n }\n const parentDir = parent ? parent.dir : \"\"\n const relDir = parentDir === \"\" ? layout.dir : layout.dir.slice(parentDir.length + 1)\n built.push({\n id,\n dir: layout.dir,\n parentId: parent ? parent.id : null,\n path: dirToRouterPath(relDir),\n file: layout.file,\n })\n dirToId.set(layout.dir, id)\n })\n\n const pages: BuiltPage[] = model.pages.map((page) => {\n // Owner = deepest layout whose dir is an ancestor-or-equal of the page dir.\n let owner: BuiltLayout | null = null\n for (const l of built) {\n if (isAncestorDir(l.dir, page.dir)) {\n if (!owner || depth(l.dir) > depth(owner.dir)) owner = l\n }\n }\n const ownerSegCount = owner ? depth(owner.dir) : 0\n const remaining = page.segments.slice(ownerSegCount)\n const index = remaining.length === 0\n const path = index ? \"/\" : remaining.map(segToRouter).join(\"/\")\n const meta = extractPageMeta(page.absFile)\n return {\n file: page.file,\n routePath: page.routePath,\n parentLayoutId: owner ? owner.id : null,\n path,\n index,\n ...(meta.title ? { title: meta.title } : {}),\n ...(meta.description ? { description: meta.description } : {}),\n ...(meta.navLabel ? { navLabel: meta.navLabel } : {}),\n }\n })\n\n return {\n rootLayout: rootLayoutRoute ? rootLayoutRoute.file : null,\n notFound: model.notFound,\n error: model.error,\n layouts: built,\n pages,\n }\n}\n","import fs from \"node:fs\"\nimport path from \"node:path\"\nimport { createRequire } from \"node:module\"\nimport { MANIFEST_SCHEMA_VERSION, VANTAGE_DIR } from \"./constants\"\nimport { buildRouteTree } from \"./route-tree\"\nimport type { RouteModel, Segment } from \"./types\"\n\nconst PKG = \"@squadbase/vantage\"\n\n/** Resolve the absolute directory of the installed @squadbase/vantage package. */\nfunction resolveVantageDir(root: string): string | null {\n try {\n const require = createRequire(path.join(root, \"noop.js\"))\n const pkgJson = require.resolve(`${PKG}/package.json`)\n return path.dirname(pkgJson)\n } catch {\n return null\n }\n}\n\n/** POSIX import specifier from `.vantage/` to a project-relative file. */\nfunction importFromVantage(relFile: string): string {\n return `../${relFile}`\n}\n\nfunction ensureDir(dir: string): void {\n fs.mkdirSync(dir, { recursive: true })\n}\n\nfunction writeIfChanged(file: string, content: string): void {\n try {\n if (fs.existsSync(file) && fs.readFileSync(file, \"utf8\") === content) return\n } catch {\n /* fall through to write */\n }\n fs.writeFileSync(file, content)\n}\n\nfunction serializeSegments(segments: Segment[]): string {\n return (\n \"[\" +\n segments\n .map((s) => {\n if (s.kind === \"static\") return `{ kind: \"static\", value: ${JSON.stringify(s.value)} }`\n if (s.kind === \"param\") return `{ kind: \"param\", name: ${JSON.stringify(s.name)} }`\n return `{ kind: \"catchall\", name: ${JSON.stringify(s.name)} }`\n })\n .join(\", \") +\n \"]\"\n )\n}\n\nconst BANNER =\n \"// AUTO-GENERATED by @squadbase/vantage. Do not edit — regenerated on every run.\\n\"\n\nfunction renderRouteTree(model: RouteModel): string {\n const tree = buildRouteTree(model)\n const lines: string[] = []\n lines.push(BANNER)\n lines.push(`import type { ClientManifest } from \"${PKG}/client\"`)\n lines.push(\"\")\n lines.push(\"export const manifest: ClientManifest = {\")\n lines.push(\n ` rootLayout: ${tree.rootLayout ? `() => import(${JSON.stringify(importFromVantage(tree.rootLayout))})` : \"null\"},`,\n )\n lines.push(\n ` notFound: ${tree.notFound ? `() => import(${JSON.stringify(importFromVantage(tree.notFound))})` : \"null\"},`,\n )\n lines.push(\n ` error: ${tree.error ? `() => import(${JSON.stringify(importFromVantage(tree.error))})` : \"null\"},`,\n )\n lines.push(\" layouts: [\")\n for (const l of tree.layouts) {\n lines.push(\n ` { id: ${JSON.stringify(l.id)}, parentId: ${JSON.stringify(l.parentId)}, path: ${JSON.stringify(\n l.path,\n )}, load: () => import(${JSON.stringify(importFromVantage(l.file))}) },`,\n )\n }\n lines.push(\" ],\")\n lines.push(\" pages: [\")\n for (const p of tree.pages) {\n const extra: string[] = []\n if (p.title) extra.push(`title: ${JSON.stringify(p.title)}`)\n if (p.description) extra.push(`description: ${JSON.stringify(p.description)}`)\n if (p.navLabel) extra.push(`navLabel: ${JSON.stringify(p.navLabel)}`)\n lines.push(\n ` { parentLayoutId: ${JSON.stringify(p.parentLayoutId)}, path: ${JSON.stringify(\n p.path,\n )}, index: ${p.index}, routePath: ${JSON.stringify(p.routePath)}${\n extra.length ? \", \" + extra.join(\", \") : \"\"\n }, load: () => import(${JSON.stringify(importFromVantage(p.file))}) },`,\n )\n }\n lines.push(\" ],\")\n lines.push(\"}\")\n lines.push(\"\")\n return lines.join(\"\\n\")\n}\n\nfunction renderServerRoutes(model: RouteModel): string {\n const lines: string[] = []\n lines.push(BANNER)\n lines.push(`import type { ProdApiRoute } from \"${PKG}/server/node\"`)\n model.apis.forEach((a, i) => {\n lines.push(`import * as m${i} from ${JSON.stringify(importFromVantage(a.file))}`)\n })\n lines.push(\"\")\n lines.push(\"export const apiRoutes: ProdApiRoute[] = [\")\n model.apis.forEach((a, i) => {\n lines.push(\n ` { routePath: ${JSON.stringify(a.routePath)}, segments: ${serializeSegments(\n a.segments,\n )}, module: m${i} },`,\n )\n })\n lines.push(\"]\")\n lines.push(\"\")\n return lines.join(\"\\n\")\n}\n\nfunction renderIndexHtml(): string {\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>Vantage</title>\n </head>\n <body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"/.vantage/client-entry.tsx\"></script>\n </body>\n</html>\n`\n}\n\nfunction renderClientEntry(): string {\n return `${BANNER}import { bootstrap } from \"${PKG}/client\"\nimport { manifest } from \"./route-tree.gen\"\nimport \"./runtime.css\"\n\nbootstrap(manifest)\n`\n}\n\nfunction renderRuntimeCss(root: string, pageDir: string): string {\n const parts: string[] = []\n parts.push('@import \"tailwindcss\";')\n parts.push(`@import \"${PKG}/theme.css\";`)\n // The global stylesheet lives next to the pages: styles.css at the project\n // root, or src/styles.css once src/ exists (`SRC_DIR_SPLIT` catches a leftover\n // root-level one instead of importing both).\n const stylesRel = pageDir === \"\" ? \"styles.css\" : `${pageDir}/styles.css`\n if (fs.existsSync(path.join(root, stylesRel))) {\n parts.push(`@import \"../${stylesRel}\";`)\n }\n // Tailwind auto-detects the Vite project root; the packaged components live\n // in node_modules, which Tailwind skips by default, so register them here.\n // The whole of dist/ has to be scanned, not just dist/ui and dist/components:\n // tsup hoists code shared between entries into top-level dist/chunk-*.js, and\n // that is where most of the component class strings end up.\n const vantageDir = resolveVantageDir(root)\n if (vantageDir) {\n parts.push(`@source ${JSON.stringify(path.join(vantageDir, \"dist\"))};`)\n }\n return parts.join(\"\\n\") + \"\\n\"\n}\n\nfunction renderEnvTypes(): string {\n return `${BANNER}\ninterface ImportMetaEnv {\n readonly MODE: string\n readonly DEV: boolean\n readonly PROD: boolean\n readonly SSR: boolean\n readonly BASE_URL: string\n readonly [key: \\`PUBLIC_\\${string}\\`]: string | undefined\n}\n\ninterface ImportMeta {\n readonly env: ImportMetaEnv\n}\n\ndeclare module \"*.css\" {\n const content: string\n export default content\n}\n`\n}\n\nfunction renderInternalManifest(model: RouteModel): string {\n return (\n JSON.stringify(\n {\n schemaVersion: MANIFEST_SCHEMA_VERSION,\n pageDir: model.pageDir,\n pages: model.pages.map((p) => ({ file: p.file, route: p.routePath })),\n apis: model.apis.map((a) => ({ file: a.file, route: a.routePath })),\n hasServer: model.hasServer,\n },\n null,\n 2,\n ) + \"\\n\"\n )\n}\n\n/** Options controlling artifact generation. */\nexport interface GenerateOptions {\n root: string\n model: RouteModel\n}\n\n/**\n * Regenerate the `.vantage/` directory from a route model. Idempotent and\n * content-stable so it does not thrash file watchers.\n */\nexport function generateArtifacts({ root, model }: GenerateOptions): string {\n const vantageDir = path.join(root, VANTAGE_DIR)\n ensureDir(vantageDir)\n ensureDir(path.join(vantageDir, \"types\"))\n\n // Everything in .vantage is generated and git/agent/search invisible.\n writeIfChanged(path.join(vantageDir, \".gitignore\"), \"*\\n\")\n writeIfChanged(path.join(vantageDir, \"index.html\"), renderIndexHtml())\n writeIfChanged(path.join(vantageDir, \"client-entry.tsx\"), renderClientEntry())\n writeIfChanged(path.join(vantageDir, \"route-tree.gen.ts\"), renderRouteTree(model))\n writeIfChanged(path.join(vantageDir, \"runtime.css\"), renderRuntimeCss(root, model.pageDir))\n writeIfChanged(path.join(vantageDir, \"types\", \"env.d.ts\"), renderEnvTypes())\n writeIfChanged(path.join(vantageDir, \"manifest.json\"), renderInternalManifest(model))\n\n if (model.hasServer) {\n writeIfChanged(path.join(vantageDir, \"server-routes.gen.ts\"), renderServerRoutes(model))\n }\n\n return vantageDir\n}\n","import fs from \"node:fs\"\nimport path from \"node:path\"\nimport {\n API_EXTENSIONS,\n NON_ROUTE_DIRS,\n PAGE_EXTENSIONS,\n RESERVED_PAGE_NAMES,\n SRC_DIR,\n} from \"./constants\"\nimport type { ApiRoute, LayoutRoute, PageRoute, RouteModel, Segment } from \"./types\"\n\n/** Convert an absolute path to a project-relative POSIX path. */\nfunction toPosix(root: string, abs: string): string {\n return path.relative(root, abs).split(path.sep).join(\"/\")\n}\n\n/** Parse one raw path token into a segment descriptor. */\nfunction parseRawSegment(raw: string): Segment {\n const catchall = raw.match(/^\\[\\.\\.\\.(.+)\\]$/)\n if (catchall) return { kind: \"catchall\", name: catchall[1]! }\n const param = raw.match(/^\\[(.+)\\]$/)\n if (param) return { kind: \"param\", name: param[1]! }\n return { kind: \"static\", value: raw }\n}\n\n/** Build a human/display route path from segments. */\nfunction displayPath(segments: Segment[]): string {\n if (segments.length === 0) return \"/\"\n const parts = segments.map((s) => {\n if (s.kind === \"static\") return s.value\n if (s.kind === \"param\") return `:${s.name}`\n return \"*\"\n })\n return \"/\" + parts.join(\"/\")\n}\n\n/** Split a relative POSIX file (without extension) into route segments. */\nfunction fileToSegments(relNoExt: string): Segment[] {\n const raw = relNoExt.split(\"/\")\n // A trailing `index` maps to its directory (drop it).\n if (raw[raw.length - 1] === \"index\") raw.pop()\n return raw.map(parseRawSegment)\n}\n\n/** Strip a known extension from a filename. */\nfunction stripExt(file: string, exts: string[]): string {\n for (const ext of exts) {\n if (file.endsWith(ext)) return file.slice(0, -ext.length)\n }\n return file\n}\n\nfunction hasExt(file: string, exts: string[]): boolean {\n return exts.some((ext) => file.endsWith(ext))\n}\n\n/** Recursively collect files under a directory, respecting ignore rules. */\nfunction walk(dir: string, root: string, out: string[]): void {\n let entries: fs.Dirent[]\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true })\n } catch {\n return\n }\n for (const entry of entries) {\n const abs = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n if (NON_ROUTE_DIRS.has(entry.name)) continue\n if (entry.name.startsWith(\".\")) continue\n walk(abs, root, out)\n } else if (entry.isFile()) {\n out.push(abs)\n }\n }\n}\n\n/**\n * Decide where pages are scanned from: `<root>/src` when that directory exists,\n * the project root otherwise. The two never mix — a project that has `src/`\n * keeps every page inside it (`SRC_DIR_SPLIT` reports the leftovers).\n */\nexport function resolvePageRoot(root: string): { dir: string; abs: string } {\n const abs = path.join(root, SRC_DIR)\n try {\n if (fs.statSync(abs).isDirectory()) return { dir: SRC_DIR, abs }\n } catch {\n /* no src/ — pages live at the project root */\n }\n return { dir: \"\", abs: root }\n}\n\n/**\n * Discover page and layout routes under the page root. `file` stays relative to\n * the *project* root (generated imports resolve from `.vantage/`), while\n * `dir`/`segments`/`routePath` are relative to the *page* root so that `src/`\n * never leaks into a URL — and so `dir` keeps matching `segments` one-to-one,\n * which is how `buildRouteTree` pairs pages with their layouts.\n */\nfunction scanPages(\n root: string,\n pageRoot: string,\n): {\n pages: PageRoute[]\n layouts: LayoutRoute[]\n notFound: string | null\n error: string | null\n} {\n const files: string[] = []\n walk(pageRoot, pageRoot, files)\n\n const pages: PageRoute[] = []\n const layouts: LayoutRoute[] = []\n let notFound: string | null = null\n let error: string | null = null\n\n for (const abs of files) {\n const file = toPosix(root, abs)\n const rel = toPosix(pageRoot, abs)\n const base = path.posix.basename(rel)\n if (!hasExt(base, PAGE_EXTENSIONS)) continue\n\n const nameNoExt = stripExt(base, PAGE_EXTENSIONS)\n const dir = path.posix.dirname(rel)\n const dirPosix = dir === \".\" ? \"\" : dir\n\n // Reserved modules.\n if (nameNoExt === RESERVED_PAGE_NAMES.layout) {\n layouts.push({ file, absFile: abs, dir: dirPosix })\n continue\n }\n if (nameNoExt === RESERVED_PAGE_NAMES.notFound) {\n if (dirPosix === \"\") notFound = file\n continue\n }\n if (nameNoExt === RESERVED_PAGE_NAMES.error) {\n if (dirPosix === \"\") error = file\n continue\n }\n // Any other underscore-prefixed file is a private module, not a route.\n if (nameNoExt.startsWith(\"_\")) continue\n\n const relNoExt = stripExt(rel, PAGE_EXTENSIONS)\n const segments = fileToSegments(relNoExt)\n const routePath = displayPath(segments)\n const dynamic = segments.some((s) => s.kind !== \"static\")\n pages.push({ file, absFile: abs, routePath, segments, dir: dirPosix, dynamic })\n }\n\n // Stable ordering: shallow before deep, static before dynamic, alpha.\n pages.sort((a, b) => routeSortKey(a).localeCompare(routeSortKey(b)))\n layouts.sort((a, b) => a.dir.localeCompare(b.dir))\n return { pages, layouts, notFound, error }\n}\n\n/** Sort key that keeps static routes ahead of dynamic ones at each depth. */\nfunction routeSortKey(p: PageRoute): string {\n return p.segments\n .map((s) => (s.kind === \"static\" ? \"0\" + s.value : s.kind === \"param\" ? \"1\" : \"2\"))\n .join(\"/\")\n}\n\n/** Discover server API routes under `server/api`. */\nfunction scanApis(root: string): ApiRoute[] {\n const apiDir = path.join(root, \"server\", \"api\")\n if (!fs.existsSync(apiDir)) return []\n\n const files: string[] = []\n const walkApi = (dir: string) => {\n let entries: fs.Dirent[]\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true })\n } catch {\n return\n }\n for (const entry of entries) {\n const abs = path.join(dir, entry.name)\n if (entry.isDirectory()) walkApi(abs)\n else if (entry.isFile()) files.push(abs)\n }\n }\n walkApi(apiDir)\n\n const apis: ApiRoute[] = []\n for (const abs of files) {\n const base = path.basename(abs)\n if (!hasExt(base, API_EXTENSIONS)) continue\n const nameNoExt = stripExt(base, API_EXTENSIONS)\n // Type declaration files and private helpers are not routes.\n if (base.endsWith(\".d.ts\")) continue\n if (nameNoExt.startsWith(\"_\")) continue\n\n const relFromServer = toPosix(path.join(root, \"server\"), abs) // e.g. api/customers/[id].ts\n const relNoExt = stripExt(relFromServer, API_EXTENSIONS) // api/customers/[id]\n const withoutApiPrefix = relNoExt.replace(/^api\\/?/, \"\") // customers/[id] or \"\" for api/index\n const segTokens = withoutApiPrefix === \"\" ? [] : withoutApiPrefix.split(\"/\")\n if (segTokens[segTokens.length - 1] === \"index\") segTokens.pop()\n const segments = segTokens.map(parseRawSegment)\n const routePath = \"/api\" + (segments.length ? displayPath(segments) : \"\")\n const params = segments\n .filter((s) => s.kind !== \"static\")\n .map((s) => (s as { name: string }).name)\n\n apis.push({\n file: toPosix(root, abs),\n absFile: abs,\n routePath,\n pattern: routePath,\n segments,\n params,\n })\n }\n\n apis.sort((a, b) => a.routePath.localeCompare(b.routePath))\n return apis\n}\n\n/** Scan a project into a full route model. */\nexport function scanProject(root: string): RouteModel {\n const pageRoot = resolvePageRoot(root)\n const { pages, layouts, notFound, error } = scanPages(root, pageRoot.abs)\n // server/ is always at the project root: it is the other side of the\n // client/server boundary, not part of the client source tree.\n const hasServer = fs.existsSync(path.join(root, \"server\"))\n const apis = hasServer ? scanApis(root) : []\n return { pages, layouts, notFound, error, apis, hasServer, pageDir: pageRoot.dir }\n}\n\n/** Convert a display route path segment list into a TanStack Router path. */\nexport function toRouterPath(segments: Segment[]): string {\n if (segments.length === 0) return \"/\"\n const parts = segments.map((s) => {\n if (s.kind === \"static\") return s.value\n if (s.kind === \"param\") return `$${s.name}`\n return \"$\" // TanStack splat\n })\n return \"/\" + parts.join(\"/\")\n}\n","import { Hono } from \"hono\"\nimport { getRequestListener } from \"@hono/node-server\"\nimport type { IncomingMessage, ServerResponse } from \"node:http\"\nimport type { ViteDevServer } from \"vite\"\nimport type { RouteModel } from \"../core/types\"\nimport { corsMiddleware } from \"./cors\"\nimport {\n dispatchApi,\n matchApiRoute,\n sortApiRoutes,\n type ApiRouteEntry,\n} from \"./dispatch\"\nimport type { ApiModule } from \"./index\"\n\ntype Middleware = (req: IncomingMessage, res: ServerResponse, next: () => void) => void\n\n/**\n * Build a connect-style middleware that serves `server/api/**` in dev. Modules\n * are loaded through Vite's SSR pipeline so edits hot-reload, and the route list\n * is read fresh on every request so added/removed API files take effect without\n * a restart.\n */\nexport function createApiDevMiddleware(opts: {\n server: ViteDevServer\n getModel: () => RouteModel\n getEnv: () => Record<string, string | undefined>\n}): Middleware {\n const { server, getModel, getEnv } = opts\n\n const buildRoutes = (): ApiRouteEntry[] =>\n sortApiRoutes(\n getModel().apis.map((a) => ({\n routePath: a.routePath,\n segments: a.segments,\n hasCatchall: a.segments.some((s) => s.kind === \"catchall\"),\n staticCount: a.segments.filter((s) => s.kind === \"static\").length,\n load: () => server.ssrLoadModule(a.absFile) as Promise<ApiModule>,\n })),\n )\n\n const app = new Hono()\n\n // CORS for split deployments, matching prod. Off unless CORS_ORIGIN is set;\n // read once here from the current env (dev's CORS config is deploy-level).\n const cors = corsMiddleware(getEnv())\n if (cors) {\n app.use(\"/api\", cors)\n app.use(\"/api/*\", cors)\n }\n\n const handle = async (c: { req: { url: string; raw: Request } }) => {\n const url = new URL(c.req.url)\n const match = matchApiRoute(buildRoutes(), url.pathname)\n if (!match) {\n return Response.json({ error: \"Not Found\", path: url.pathname }, { status: 404 })\n }\n let mod: ApiModule\n try {\n mod = await match.route.load()\n } catch (err) {\n if (err instanceof Error) server.ssrFixStacktrace(err)\n throw err\n }\n return dispatchApi(mod, c.req.raw, match.params, getEnv())\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n app.all(\"/api\", handle as any)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n app.all(\"/api/*\", handle as any)\n\n const listener = getRequestListener(app.fetch)\n\n return (req, res, next) => {\n const url = req.url ?? \"/\"\n const path = url.split(\"?\")[0]!\n if (path === \"/api\" || path.startsWith(\"/api/\")) {\n Promise.resolve(listener(req, res)).catch((err) => {\n console.error(\"[vantage] API middleware failure:\", err)\n if (!res.headersSent) {\n res.statusCode = 500\n res.setHeader(\"content-type\", \"application/json\")\n res.end(JSON.stringify({ error: \"Internal Server Error\" }))\n }\n })\n } else {\n next()\n }\n }\n}\n","import fs from \"node:fs\"\nimport path from \"node:path\"\nimport react from \"@vitejs/plugin-react\"\nimport tailwindcss from \"@tailwindcss/vite\"\nimport type { HtmlTagDescriptor, Plugin, PluginOption, ViteDevServer } from \"vite\"\nimport pc from \"picocolors\"\nimport { NON_ROUTE_DIRS, PAGE_EXTENSIONS, VANTAGE_DIR } from \"../core/constants\"\nimport { generateArtifacts } from \"../core/generate\"\nimport { resolvePageRoot, scanProject } from \"../core/scan\"\nimport type { RouteModel } from \"../core/types\"\nimport { createApiDevMiddleware } from \"../server/dev\"\n\nexport interface VantagePluginOptions {\n root: string\n /** Server-side env (process.env + loaded .env), passed to API handlers. */\n env?: Record<string, string | undefined>\n}\n\nconst DEDUPE = [\"react\", \"react-dom\", \"@tanstack/react-router\", \"@tanstack/react-query\"]\n\n/** Page modules are scanned from the page root: `<root>/src` when it exists. */\nfunction isPageFile(pageRoot: string, file: string): boolean {\n const rel = path.relative(pageRoot, file)\n if (rel.startsWith(\"..\")) return false\n const segments = rel.split(path.sep)\n if (segments.some((s) => NON_ROUTE_DIRS.has(s) || (s.startsWith(\".\") && s !== \"..\"))) return false\n return PAGE_EXTENSIONS.some((ext) => file.endsWith(ext))\n}\n\nfunction isApiFile(root: string, file: string): boolean {\n const rel = path.relative(root, file)\n return rel.startsWith(`server${path.sep}api${path.sep}`) && /\\.(ts|tsx|js)$/.test(file) && !file.endsWith(\".d.ts\")\n}\n\nfunction isServerFile(root: string, file: string): boolean {\n const rel = path.relative(root, file)\n return rel === \"server\" || rel.startsWith(`server${path.sep}`)\n}\n\n/**\n * The single plugin that turns a plain Vite instance into Vantage: file-based\n * routing, generated entry/HTML, Tailwind, the server-import boundary, route\n * HMR and dev console forwarding.\n */\nexport function vantagePlugin(options: VantagePluginOptions): PluginOption {\n const root = path.resolve(options.root)\n const vantageDir = path.join(root, VANTAGE_DIR)\n let model: RouteModel = scanProject(root)\n\n /** Absolute page-scan root, kept in step with the last scan. */\n const pageRoot = (): string => (model.pageDir === \"\" ? root : path.join(root, model.pageDir))\n\n const regenerate = (): void => {\n model = scanProject(root)\n generateArtifacts({ root, model })\n }\n\n const core: Plugin = {\n name: \"vantage:core\",\n enforce: \"pre\",\n\n config() {\n return {\n root,\n appType: \"custom\",\n envPrefix: [\"PUBLIC_\"],\n resolve: { dedupe: DEDUPE },\n optimizeDeps: {\n // Only list deps resolvable from the project root here; the managed\n // @tanstack/* packages are discovered through the module graph.\n include: [\"react\", \"react-dom\", \"react-dom/client\", \"react/jsx-runtime\"],\n },\n build: {\n outDir: path.join(root, \"dist\", \"client\"),\n emptyOutDir: true,\n rollupOptions: {\n input: path.join(vantageDir, \"index.html\"),\n },\n },\n }\n },\n\n configResolved() {\n // Ensure .vantage exists before dev HTML serving or the build reads input.\n regenerate()\n },\n\n buildStart() {\n regenerate()\n },\n\n // --- Server-import boundary: client code may never import server/. ---\n resolveId(source, importer, opts) {\n if (opts?.ssr) return null\n if (!importer) return null\n const imp = importer.split(\"?\")[0]!\n if (!imp.startsWith(root)) return null\n const relImp = path.relative(root, imp)\n if (\n relImp.startsWith(`server${path.sep}`) ||\n relImp.startsWith(VANTAGE_DIR) ||\n relImp.includes(\"node_modules\")\n ) {\n return null\n }\n let target: string | null = null\n if (source.startsWith(\".\")) target = path.resolve(path.dirname(imp), source)\n else if (source.startsWith(\"/\")) target = path.join(root, source.slice(1))\n else if (source === \"server\" || source.startsWith(\"server/\")) target = path.join(root, source)\n if (!target) return null\n const relTarget = path.relative(root, target)\n if (relTarget === \"server\" || relTarget.startsWith(`server${path.sep}`)) {\n this.error(\n `Client module \"${relImp}\" imports from server/ (\"${source}\"). ` +\n `server/ code must never reach the client bundle — move shared code to lib/.`,\n )\n }\n return null\n },\n\n // --- Keep React Fast Refresh working on page modules. ---\n // `export const page = definePage(...)` is a non-component export, which\n // makes @vitejs/plugin-react bail out of Fast Refresh (full reload). The\n // runtime never reads this export (title/description are extracted at\n // generate time), so we drop the `export` keyword — turning it into a local\n // const — before the React plugin analyzes the module. Offsets are\n // preserved (6 spaces for \"export\") so sourcemaps stay accurate.\n transform(code, id) {\n const clean = id.split(\"?\")[0]!\n if (!isPageFile(pageRoot(), clean)) return null\n if (!/export\\s+const\\s+page\\b/.test(code)) return null\n // Anchor to line start so `export const page` inside a string/comment is\n // not rewritten. \"export\" (6 chars) becomes 6 spaces to keep offsets.\n const out = code.replace(\n /^([ \\t]*)export(\\s+const\\s+page\\b)/gm,\n (_m, indent: string, rest: string) => indent + \" \" + rest,\n )\n if (out === code) return null\n return { code: out, map: null }\n },\n\n // --- Dev console + runtime errors forwarded to the terminal. ---\n transformIndexHtml: {\n order: \"pre\",\n handler(_html, ctx): HtmlTagDescriptor[] {\n if (!ctx.server) return []\n return [\n {\n tag: \"script\",\n attrs: { type: \"module\" },\n injectTo: \"head-prepend\",\n children: CONSOLE_BRIDGE,\n },\n ]\n },\n },\n\n configureServer(server: ViteDevServer) {\n const getEnv = () => options.env ?? (process.env as Record<string, string | undefined>)\n\n // API requests handled before Vite's own middlewares.\n const apiMw = createApiDevMiddleware({ server, getModel: () => model, getEnv })\n server.middlewares.use((req, res, next) => {\n const url = (req.url ?? \"/\").split(\"?\")[0]\n if (url === \"/__vantage_console\" && req.method === \"POST\") {\n return handleConsoleBeacon(req, res)\n }\n // Without server/, /api/* is a normal client route: fall through to the\n // SPA shell instead of returning API 404s (matches production).\n if (model.hasServer) return apiMw(req, res, next)\n return next()\n })\n\n // Structural route changes -> regenerate manifest + reload. Adding or\n // removing styles.css also changes the generated runtime.css.\n const isStylesFile = (file: string) => path.relative(pageRoot(), file) === \"styles.css\"\n const onStructural = (file: string) => {\n // Creating or deleting src/ moves the page root itself, which changes\n // every generated import even though no page file was touched.\n const rootMoved = resolvePageRoot(root).dir !== model.pageDir\n if (rootMoved || isPageFile(pageRoot(), file) || isApiFile(root, file) || isStylesFile(file)) {\n regenerate()\n server.ws.send({ type: \"full-reload\" })\n }\n }\n server.watcher.on(\"add\", onStructural)\n server.watcher.on(\"unlink\", onStructural)\n server.watcher.on(\"addDir\", () => {\n regenerate()\n })\n server.watcher.on(\"unlinkDir\", () => {\n regenerate()\n server.ws.send({ type: \"full-reload\" })\n })\n server.watcher.on(\"change\", (file) => {\n if (isServerFile(root, file)) {\n const mods = server.moduleGraph.getModulesByFile(file)\n if (mods) for (const m of mods) server.moduleGraph.invalidateModule(m)\n }\n })\n\n // SPA fallback: serve the generated index.html for navigations.\n return () => {\n server.middlewares.use(async (req, res, next) => {\n if (req.method !== \"GET\" && req.method !== \"HEAD\") return next()\n // Standard SPA fallback: anything Vite's own middlewares didn't handle\n // (real modules, assets, /@vite, /@id) resolves to the app shell.\n try {\n const raw = fs.readFileSync(path.join(vantageDir, \"index.html\"), \"utf8\")\n // The first argument is the URL of the shell *document*, not of the\n // navigation being answered: Vite derives the ids of the scripts it\n // injects (the React Refresh preamble) from it, emitting\n // `<src>?html-proxy&index=0.js`. Passing `req.url` would make a page\n // load of /sales request \"/sales?html-proxy&index=0.js\", which\n // resolves to sales/index.tsx and errors. `originalUrl` still carries\n // the real navigation for plugins that want it.\n const shellUrl = `/${VANTAGE_DIR}/index.html`\n const html = await server.transformIndexHtml(shellUrl, raw, req.originalUrl)\n res.statusCode = 200\n res.setHeader(\"Content-Type\", \"text/html\")\n res.end(html)\n } catch (err) {\n next(err as Error)\n }\n })\n }\n },\n }\n\n // React Fast Refresh + Tailwind are owned by Vantage, never by the user.\n return [core, react(), tailwindcss() as PluginOption]\n}\n\nconst CONSOLE_BRIDGE = `\n(() => {\n const send = (level, message) => {\n try {\n const body = JSON.stringify({ level, message });\n if (navigator.sendBeacon) navigator.sendBeacon(\"/__vantage_console\", body);\n else fetch(\"/__vantage_console\", { method: \"POST\", body, keepalive: true });\n } catch (_) {}\n };\n const fmt = (args) => args.map((a) => {\n if (a instanceof Error) return a.stack || a.message;\n if (typeof a === \"object\") { try { return JSON.stringify(a); } catch { return String(a); } }\n return String(a);\n }).join(\" \");\n for (const lvl of [\"log\", \"info\", \"warn\", \"error\"]) {\n const orig = console[lvl].bind(console);\n console[lvl] = (...args) => { send(lvl, fmt(args)); orig(...args); };\n }\n window.addEventListener(\"error\", (e) => send(\"error\", (e.message || \"Error\") + \" @ \" + (e.filename || \"\") + \":\" + e.lineno));\n window.addEventListener(\"unhandledrejection\", (e) => send(\"error\", \"UnhandledRejection: \" + ((e.reason && e.reason.stack) || e.reason)));\n})();\n`\n\nfunction handleConsoleBeacon(req: import(\"node:http\").IncomingMessage, res: import(\"node:http\").ServerResponse): void {\n let body = \"\"\n req.on(\"data\", (chunk) => {\n body += chunk\n if (body.length > 1_000_000) req.destroy()\n })\n req.on(\"end\", () => {\n try {\n const { level, message } = JSON.parse(body) as { level: string; message: string }\n const tag = pc.dim(`[browser:${level}]`)\n const color =\n level === \"error\" ? pc.red : level === \"warn\" ? pc.yellow : (s: string) => s\n // eslint-disable-next-line no-console\n console.log(`${tag} ${color(String(message))}`)\n } catch {\n /* ignore malformed beacons */\n }\n res.statusCode = 204\n res.end()\n })\n}\n"]}
|