@squadbase/vantage 0.5.3 → 0.6.1-dev.2d25e94

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.
Files changed (134) hide show
  1. package/NOTICE +73 -0
  2. package/README.md +6 -5
  3. package/dist/add-DY4AXANK.js +6 -0
  4. package/dist/add-DY4AXANK.js.map +1 -0
  5. package/dist/{build-756WIEVI.js → build-JB4VOMUI.js} +10 -10
  6. package/dist/{build-756WIEVI.js.map → build-JB4VOMUI.js.map} +1 -1
  7. package/dist/{check-KZ5PHCA6.js → check-ZJYK6RLG.js} +8 -8
  8. package/dist/{check-KZ5PHCA6.js.map → check-ZJYK6RLG.js.map} +1 -1
  9. package/dist/chunk-5ZOP4SQR.js +47 -0
  10. package/dist/chunk-5ZOP4SQR.js.map +1 -0
  11. package/dist/{chunk-EHPJXDJU.js → chunk-6S4BAIGV.js} +4 -2
  12. package/dist/chunk-6S4BAIGV.js.map +1 -0
  13. package/dist/chunk-BCE22JSM.js +510 -0
  14. package/dist/chunk-BCE22JSM.js.map +1 -0
  15. package/dist/{chunk-C4MQRWXS.js → chunk-C2CX6GLX.js} +17 -3
  16. package/dist/chunk-C2CX6GLX.js.map +1 -0
  17. package/dist/{chunk-RA6Z3OX3.js → chunk-EP6JHXSR.js} +61 -9
  18. package/dist/chunk-EP6JHXSR.js.map +1 -0
  19. package/dist/{chunk-BAM33YZ6.js → chunk-JGRMRXXZ.js} +45 -6
  20. package/dist/chunk-JGRMRXXZ.js.map +1 -0
  21. package/dist/{chunk-VXAV2435.js → chunk-KLEIVDUV.js} +30 -7
  22. package/dist/chunk-KLEIVDUV.js.map +1 -0
  23. package/dist/{chunk-JC6MT5UU.js → chunk-MXI3PZFT.js} +3 -3
  24. package/dist/{chunk-JC6MT5UU.js.map → chunk-MXI3PZFT.js.map} +1 -1
  25. package/dist/chunk-PLST5Q7T.js +2221 -0
  26. package/dist/chunk-PLST5Q7T.js.map +1 -0
  27. package/dist/chunk-PVTHHV7X.js +105 -0
  28. package/dist/chunk-PVTHHV7X.js.map +1 -0
  29. package/dist/{chunk-HQDEYCDP.js → chunk-QI3XQKHS.js} +40 -4
  30. package/dist/chunk-QI3XQKHS.js.map +1 -0
  31. package/dist/{chunk-L3TW4FNA.js → chunk-T3FLAGI6.js} +34 -13
  32. package/dist/chunk-T3FLAGI6.js.map +1 -0
  33. package/dist/{chunk-X44ZTKID.js → chunk-U2M6HGKQ.js} +61 -9
  34. package/dist/chunk-U2M6HGKQ.js.map +1 -0
  35. package/dist/chunk-ZO62C6T4.js +91 -0
  36. package/dist/chunk-ZO62C6T4.js.map +1 -0
  37. package/dist/{chunk-D4Y5RWJA.js → chunk-ZVANIULZ.js} +81 -21
  38. package/dist/chunk-ZVANIULZ.js.map +1 -0
  39. package/dist/cli.js +18 -14
  40. package/dist/cli.js.map +1 -1
  41. package/dist/client/index.d.ts +5 -35
  42. package/dist/client/index.js +1 -1
  43. package/dist/components/index.js +3 -2212
  44. package/dist/components/index.js.map +1 -1
  45. package/dist/{dev-EILX2VTF.js → dev-FCEC3UKQ.js} +24 -13
  46. package/dist/dev-FCEC3UKQ.js.map +1 -0
  47. package/dist/doc/index.d.ts +39 -0
  48. package/dist/doc/index.js +38 -0
  49. package/dist/doc/index.js.map +1 -0
  50. package/dist/{docs-GP2ZHIQF.js → docs-EJJ3BECT.js} +4 -4
  51. package/dist/{docs-GP2ZHIQF.js.map → docs-EJJ3BECT.js.map} +1 -1
  52. package/dist/{doctor-FXZLMGC3.js → doctor-WHZXPERA.js} +9 -9
  53. package/dist/doctor-WHZXPERA.js.map +1 -0
  54. package/dist/manifest-DiOjyinq.d.ts +43 -0
  55. package/dist/{preview-WBQPCTTT.js → preview-OGMCNQUO.js} +13 -5
  56. package/dist/preview-OGMCNQUO.js.map +1 -0
  57. package/dist/query/index.js +1 -102
  58. package/dist/query/index.js.map +1 -1
  59. package/dist/router/index.d.ts +10 -0
  60. package/dist/router/index.js +2 -89
  61. package/dist/router/index.js.map +1 -1
  62. package/dist/{routes-WCN4KSZY.js → routes-GTFO5PUF.js} +17 -8
  63. package/dist/routes-GTFO5PUF.js.map +1 -0
  64. package/dist/{search-GLKCJXSI.js → search-6Y422SV6.js} +4 -4
  65. package/dist/{search-GLKCJXSI.js.map → search-6Y422SV6.js.map} +1 -1
  66. package/dist/server/node.d.ts +1 -1
  67. package/dist/server/node.js +6 -1
  68. package/dist/server/node.js.map +1 -1
  69. package/dist/slide/index.d.ts +230 -0
  70. package/dist/slide/index.js +1571 -0
  71. package/dist/slide/index.js.map +1 -0
  72. package/dist/table/index.d.ts +107 -0
  73. package/dist/table/index.js +680 -0
  74. package/dist/table/index.js.map +1 -0
  75. package/dist/types-CXFlMl8S.d.ts +121 -0
  76. package/dist/ui/index.js +3 -41
  77. package/dist/ui/index.js.map +1 -1
  78. package/dist/{upgrade-S64IXL42.js → upgrade-AL4KZZR4.js} +9 -9
  79. package/dist/upgrade-AL4KZZR4.js.map +1 -0
  80. package/dist/vite/index.d.ts +1 -1
  81. package/dist/vite/index.js +5 -5
  82. package/docs/en/agent-skills.md +22 -12
  83. package/docs/en/changelog.md +107 -0
  84. package/docs/en/cli-reference.md +42 -4
  85. package/docs/en/pages-and-metadata.md +17 -0
  86. package/docs/en/routing.md +102 -3
  87. package/docs/en/ui-and-theming.md +102 -0
  88. package/docs/index.json +2 -2
  89. package/docs/ja/agent-skills.md +21 -11
  90. package/docs/ja/changelog.md +105 -0
  91. package/docs/ja/cli-reference.md +41 -4
  92. package/docs/ja/pages-and-metadata.md +17 -0
  93. package/docs/ja/routing.md +98 -3
  94. package/docs/ja/ui-and-theming.md +100 -0
  95. package/package.json +33 -9
  96. package/skills/vantage-app/SKILL.md +4 -0
  97. package/skills/vantage-design/SKILL.md +137 -0
  98. package/skills/vantage-design/references/extract.md +110 -0
  99. package/skills/vantage-design/references/format.md +172 -0
  100. package/skills/vantage-design/references/presets.md +110 -0
  101. package/skills/vantage-design/scripts/contrast.mjs +166 -0
  102. package/skills/vantage-pitfalls/SKILL.md +41 -1
  103. package/skills/vantage-slide/SKILL.md +264 -0
  104. package/skills/vantage-slide/references/morph.md +102 -0
  105. package/skills/vantage-slide/references/steps.md +57 -0
  106. package/skills/vantage-slide/references/tokens.md +87 -0
  107. package/skills/vantage-slide/references/transitions.md +196 -0
  108. package/templates/AGENTS.md +43 -228
  109. package/templates/agents/api.md +49 -0
  110. package/templates/agents/csv.md +32 -0
  111. package/templates/agents/doc.md +73 -0
  112. package/templates/agents/page.md +187 -0
  113. package/templates/agents/slide.md +41 -0
  114. package/templates/agents/xlsx.md +33 -0
  115. package/theme.css +169 -0
  116. package/dist/add-PPCBMWEN.js +0 -6
  117. package/dist/add-PPCBMWEN.js.map +0 -1
  118. package/dist/chunk-BAM33YZ6.js.map +0 -1
  119. package/dist/chunk-C4MQRWXS.js.map +0 -1
  120. package/dist/chunk-D4Y5RWJA.js.map +0 -1
  121. package/dist/chunk-EHPJXDJU.js.map +0 -1
  122. package/dist/chunk-HQDEYCDP.js.map +0 -1
  123. package/dist/chunk-L3TW4FNA.js.map +0 -1
  124. package/dist/chunk-PSEYFYAP.js +0 -276
  125. package/dist/chunk-PSEYFYAP.js.map +0 -1
  126. package/dist/chunk-RA6Z3OX3.js.map +0 -1
  127. package/dist/chunk-VXAV2435.js.map +0 -1
  128. package/dist/chunk-X44ZTKID.js.map +0 -1
  129. package/dist/dev-EILX2VTF.js.map +0 -1
  130. package/dist/doctor-FXZLMGC3.js.map +0 -1
  131. package/dist/preview-WBQPCTTT.js.map +0 -1
  132. package/dist/routes-WCN4KSZY.js.map +0 -1
  133. package/dist/types-De3mo_hv.d.ts +0 -59
  134. package/dist/upgrade-S64IXL42.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/profile.ts","../src/core/scan.ts"],"names":[],"mappings":"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","file":"chunk-D4Y5RWJA.js","sourcesContent":["/**\n * Opt-in phase timing, enabled with `VANTAGE_PROFILE=1`.\n *\n * Every line goes to **stderr**, so turning it on never corrupts the `--json`\n * payloads other commands write to stdout. Disabled, `timed()` is a direct call\n * through — no timers, no allocation.\n */\n\nconst ENABLED = Boolean(process.env.VANTAGE_PROFILE)\n\n/** Whether profiling output is on. Cheap enough to branch on in hot paths. */\nexport const profiling = ENABLED\n\nfunction report(label: string, ms: number): void {\n const since = (performance.now() / 1000).toFixed(3)\n process.stderr.write(`[vantage:profile] ${label.padEnd(24)} ${ms.toFixed(1).padStart(8)}ms @${since}s\\n`)\n}\n\n/** Time a synchronous phase. */\nexport function timed<T>(label: string, fn: () => T): T {\n if (!ENABLED) return fn()\n const t0 = performance.now()\n try {\n return fn()\n } finally {\n report(label, performance.now() - t0)\n }\n}\n\n/** Time an asynchronous phase. */\nexport async function timedAsync<T>(label: string, fn: () => Promise<T>): Promise<T> {\n if (!ENABLED) return fn()\n const t0 = performance.now()\n try {\n return await fn()\n } finally {\n report(label, performance.now() - t0)\n }\n}\n\n/** Record a one-off duration measured by the caller. */\nexport function note(label: string, ms: number): void {\n if (ENABLED) report(label, ms)\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 { timed } from \"./profile\"\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 return timed(\"scan\", () => {\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\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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/router/registry.ts"],"names":[],"mappings":";;;AAqCA,SAAS,UAAU,IAAA,EAAwB;AACzC,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,CAAE,OAAO,OAAO,CAAA;AACvC;AAEA,SAAS,YAAY,IAAA,EAAwB;AAC3C,EAAA,OAAO,SAAA,CAAU,IAAI,CAAA,CAAE,OAAA,CAAQ,CAAC,KAAA,KAAU;AACxC,IAAA,IAAI,KAAA,CAAM,WAAW,GAAG,CAAA,SAAU,CAAC,KAAA,CAAM,KAAA,CAAM,CAAC,CAAC,CAAA;AAGjD,IAAA,IAAI,KAAA,KAAU,GAAA,EAAK,OAAO,CAAC,QAAQ,CAAA;AACnC,IAAA,OAAO,EAAC;AAAA,EACV,CAAC,CAAA;AACH;AAGA,SAAS,WAAW,IAAA,EAAsB;AACxC,EAAA,MAAM,SAAS,SAAA,CAAU,IAAI,CAAA,CAAE,GAAA,CAAI,CAAC,KAAA,KAAU;AAC5C,IAAA,IAAI,KAAA,CAAM,WAAW,GAAG,CAAA,SAAU,CAAA,CAAA,EAAI,KAAA,CAAM,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AACpD,IAAA,IAAI,KAAA,KAAU,KAAK,OAAO,GAAA;AAC1B,IAAA,OAAO,KAAA;AAAA,EACT,CAAC,CAAA;AACD,EAAA,OAAO,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA;AAC9B;AAEA,SAAS,YAAY,IAAA,EAA6B;AAChD,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,IAAA,CAAK,SAAS,CAAA;AACzC,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,CAAK,SAAA;AAAA,IACX,EAAA,EAAI,UAAA,CAAW,IAAA,CAAK,SAAS,CAAA;AAAA,IAC7B,MAAA;AAAA,IACA,OAAA,EAAS,OAAO,MAAA,GAAS,CAAA;AAAA,IACzB,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,KAAA,EAAO,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,SAAS,IAAA,CAAK,SAAA;AAAA,IAC3C,GAAI,KAAK,KAAA,GAAQ,EAAE,OAAO,IAAA,CAAK,KAAA,KAAU,EAAC;AAAA,IAC1C,GAAI,KAAK,WAAA,GAAc,EAAE,aAAa,IAAA,CAAK,WAAA,KAAgB,EAAC;AAAA,IAC5D,GAAI,KAAK,QAAA,GAAW,EAAE,UAAU,IAAA,CAAK,QAAA,KAAa;AAAC,GACrD;AACF;AAEA,IAAI,SAAsB,EAAC;AAC3B,IAAI,MAAA,uBAAa,GAAA,EAAuB;AAGjC,SAAS,UAAU,QAAA,EAAgC;AACxD,EAAA,MAAA,GAAS,QAAA,CAAS,KAAA,CAAM,GAAA,CAAI,WAAW,CAAA;AACvC,EAAA,MAAA,GAAS,IAAI,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU,CAAC,KAAA,CAAM,IAAA,EAAM,KAAK,CAAC,CAAC,CAAA;AAC7D;AAGO,SAAS,SAAA,GAAkC;AAChD,EAAA,OAAO,MAAA;AACT;AAGO,SAAS,UAAU,IAAA,EAAqC;AAC7D,EAAA,OAAO,MAAA,CAAO,IAAI,IAAI,CAAA;AACxB","file":"chunk-EHPJXDJU.js","sourcesContent":["/**\n * The app's route list, published once by the client bootstrap and read by the\n * route hooks. A module-level store rather than React context: the list is\n * fixed for the lifetime of the bundle — the generated route tree is imported\n * by `.vantage/client-entry.tsx`, which accepts no HMR update, so adding a page\n * full-reloads the dev server — and pages can read it without a provider.\n *\n * `client/bootstrap` and `router/` are separate published subpaths but tsup\n * hoists this module into a shared chunk, so both see the same instance.\n */\nimport type { ClientManifest, ClientPage } from \"../client/manifest\"\n\n/** One page route, as described by the generated manifest. */\nexport interface RouteInfo {\n /** Display path with `:param` placeholders — e.g. `/sales/:customerId`. */\n path: string\n /** The same path in `Link`'s token form — e.g. `/sales/$customerId`. */\n to: string\n /** Dynamic parameter names in order; a catch-all is reported as `_splat`. */\n params: string[]\n /** True when the route carries at least one dynamic parameter. */\n dynamic: boolean\n /** True for a directory's index route (`index.tsx`). */\n index: boolean\n /**\n * Ready-to-render nav label: `navLabel`, else `title`, else the path. Always\n * a string, so a nav needs no fallback of its own.\n */\n label: string\n /** `definePage({ title })`, extracted statically at generate time. */\n title?: string\n /** `definePage({ description })`. */\n description?: string\n /** `definePage({ navLabel })`. */\n navLabel?: string\n}\n\nfunction splitPath(path: string): string[] {\n return path.split(\"/\").filter(Boolean)\n}\n\nfunction parseParams(path: string): string[] {\n return splitPath(path).flatMap((token) => {\n if (token.startsWith(\":\")) return [token.slice(1)]\n // A catch-all loses its name in the display path; TanStack exposes it as\n // `_splat`, which is the name `useParams()` will actually return.\n if (token === \"*\") return [\"_splat\"]\n return []\n })\n}\n\n/** `/sales/:customerId` -> `/sales/$customerId` (what `Link`'s `to` expects). */\nfunction toLinkPath(path: string): string {\n const tokens = splitPath(path).map((token) => {\n if (token.startsWith(\":\")) return `$${token.slice(1)}`\n if (token === \"*\") return \"$\"\n return token\n })\n return \"/\" + tokens.join(\"/\")\n}\n\nfunction toRouteInfo(page: ClientPage): RouteInfo {\n const params = parseParams(page.routePath)\n return {\n path: page.routePath,\n to: toLinkPath(page.routePath),\n params,\n dynamic: params.length > 0,\n index: page.index,\n label: page.navLabel ?? page.title ?? page.routePath,\n ...(page.title ? { title: page.title } : {}),\n ...(page.description ? { description: page.description } : {}),\n ...(page.navLabel ? { navLabel: page.navLabel } : {}),\n }\n}\n\nlet routes: RouteInfo[] = []\nlet byPath = new Map<string, RouteInfo>()\n\n/** Publish the route list. Called by `bootstrap()`; not part of the app API. */\nexport function setRoutes(manifest: ClientManifest): void {\n routes = manifest.pages.map(toRouteInfo)\n byPath = new Map(routes.map((route) => [route.path, route]))\n}\n\n/** The published route list, in the framework's stable scan order. */\nexport function getRoutes(): readonly RouteInfo[] {\n return routes\n}\n\n/** Look up a route by its display path (`/sales/:customerId`). */\nexport function findRoute(path: string): RouteInfo | undefined {\n return byPath.get(path)\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/util.ts"],"names":[],"mappings":"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","file":"chunk-HQDEYCDP.js","sourcesContent":["import fs from \"node:fs\"\nimport path from \"node:path\"\nimport pc from \"picocolors\"\nimport { PAGE_EXTENSIONS } from \"../core/constants\"\nimport type { Diagnostic } from \"../core/types\"\n\n/** Parsed CLI arguments. */\nexport interface ParsedArgs {\n positionals: string[]\n flags: Record<string, string | boolean>\n}\n\n/** Flags that never take a value, so they don't swallow the next token. */\nconst BOOLEAN_FLAGS = new Set([\n \"json\",\n \"help\",\n \"force\",\n \"verbose\",\n \"version\",\n \"all\",\n \"list\",\n \"regex\",\n \"pages\",\n \"apis\",\n \"detail\",\n \"strict-port\",\n \"no-strict-port\",\n \"overlay\",\n \"no-overlay\",\n \"h\",\n \"v\",\n])\n\n/** Minimal argv parser: `--json`, `--port 3000`, `--port=3000`, `-v`, positionals. */\nexport function parseArgs(argv: string[]): ParsedArgs {\n const positionals: string[] = []\n const flags: Record<string, string | boolean> = {}\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!\n if (arg.startsWith(\"--\")) {\n const eq = arg.indexOf(\"=\")\n if (eq !== -1) {\n flags[arg.slice(2, eq)] = arg.slice(eq + 1)\n continue\n }\n const key = arg.slice(2)\n if (BOOLEAN_FLAGS.has(key)) {\n flags[key] = true\n continue\n }\n const next = argv[i + 1]\n if (next !== undefined && !next.startsWith(\"-\")) {\n flags[key] = next\n i++\n } else {\n flags[key] = true\n }\n } else if (arg.length > 1 && arg.startsWith(\"-\") && !/^-\\d/.test(arg)) {\n // Single-dash short flags, e.g. `-v`, `-h` (each char is a boolean).\n for (const ch of arg.slice(1)) flags[ch] = true\n } else {\n positionals.push(arg)\n }\n }\n return { positionals, flags }\n}\n\n/**\n * Apply a `--api-base-url <url>` flag by setting `process.env.PUBLIC_API_BASE_URL`\n * so Vite inlines it into the client bundle (via envPrefix). Setting it on\n * process.env gives the flag precedence over any `.env` file value. No-op when\n * the flag is absent, leaving any `.env` value in effect.\n */\nexport function applyApiBaseUrlFlag(args: ParsedArgs): void {\n const value = args.flags[\"api-base-url\"]\n if (typeof value === \"string\" && value.length) {\n process.env.PUBLIC_API_BASE_URL = value\n }\n}\n\n/** A resolved `--port`, or the reason it could not be resolved. */\nexport type PortResolution =\n | { ok: true; port: number; strictPort: boolean }\n | { ok: false; error: string }\n\n/**\n * Resolve `--port` / `--strict-port` / `--no-strict-port` into Vite's server\n * options.\n *\n * An explicit `--port` is strict by default: writing `--port 3000` means the\n * port is a contract with something outside this process — a reverse proxy, a\n * container port mapping, an OAuth redirect URI — so binding 3001 instead is a\n * silent failure, not a recovery (a supervisor that only checks \"is anything\n * listening on 3000\" will happily report a server that nobody can reach).\n * Without the flag the default is merely \"some free port\", so Vite keeps\n * walking to the next one as it always has, and running two projects at once\n * needs no ceremony. `--strict-port` / `--no-strict-port` override either way.\n *\n * A bad value is an error rather than a silent fallback, for the same reason:\n * a typo'd `--port` that quietly became 5173 is exactly the failure strictness\n * exists to prevent.\n */\nexport function resolvePortOptions(\n flags: Record<string, string | boolean>,\n fallback: number,\n): PortResolution {\n const raw = flags.port\n let port = fallback\n if (raw !== undefined) {\n if (typeof raw !== \"string\") return { ok: false, error: \"--port needs a number, e.g. --port 3000\" }\n const n = Number(raw)\n if (!Number.isInteger(n) || n < 1 || n > 65535) {\n return { ok: false, error: `Invalid --port \"${raw}\" — use an integer between 1 and 65535.` }\n }\n port = n\n }\n const strictPort = flags[\"no-strict-port\"]\n ? false\n : Boolean(flags[\"strict-port\"]) || raw !== undefined\n return { ok: true, port, strictPort }\n}\n\n/**\n * Resolve `--overlay` / `--no-overlay` into Vite's `server.hmr.overlay`.\n *\n * The overlay stays on by default — it is the fastest way for a human to see a\n * runtime error. `--no-overlay` is for the cases where a full-screen error card\n * is in the way rather than helpful: screenshots and demos, and agent-driven\n * sessions where the error already arrives in the terminal through console\n * forwarding and the overlay only obscures the page being inspected.\n */\nexport function resolveHmrOverlay(flags: Record<string, string | boolean>): boolean {\n if (flags.overlay) return true\n return !flags[\"no-overlay\"]\n}\n\n/**\n * Report a strict bind that lost the port, in the one shape dev and preview\n * share. Returns false when `err` is anything else, so the caller rethrows.\n * Vite throws a plain Error (no `code`) for this, hence the message match — a\n * reworded Vite message degrades to the generic handler, not to a wrong one.\n */\nexport function reportPortInUse(err: unknown, port: number, strictPort: boolean): boolean {\n if (!strictPort || !(err instanceof Error) || !/already in use/.test(err.message)) return false\n log.error(`Port ${port} is already in use.`)\n log.info(\" free that port, pass a different --port, or --no-strict-port to take the next one\")\n return true\n}\n\n/** Resolve the project root, honoring `--root`, defaulting to cwd. */\nexport function resolveRoot(flags: Record<string, string | boolean>): string {\n const raw = typeof flags.root === \"string\" ? flags.root : process.cwd()\n return path.resolve(raw)\n}\n\n/** How far up from a page file to look for the package root. */\nconst QUICK_ROOT_MAX_DEPTH = 5\n\n/**\n * Resolve a positional path to a quick-run project root.\n * A directory → itself; a page file (.tsx/.jsx) → its project; else null.\n */\nexport function resolveQuickRoot(target: string): string | null {\n try {\n const abs = path.resolve(target)\n const stat = fs.statSync(abs)\n if (stat.isDirectory()) return abs\n if (stat.isFile() && PAGE_EXTENSIONS.some((ext) => abs.endsWith(ext))) {\n // Walk up to the nearest package.json so `vantage ./demo/src/index.tsx`\n // starts in ./demo — the directory holding the page is not the project\n // root once pages live under src/ (or in any nested route directory).\n let dir = path.dirname(abs)\n for (let i = 0; i <= QUICK_ROOT_MAX_DEPTH; i++) {\n if (fs.existsSync(path.join(dir, \"package.json\"))) return dir\n const parent = path.dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n return path.dirname(abs)\n }\n } catch {\n // statSync throws when the path does not exist → null (not a quick target)\n }\n return null\n}\n\nexport const log = {\n info: (msg: string) => console.log(msg),\n step: (msg: string) => console.log(pc.cyan(\"→ \") + msg),\n ok: (msg: string) => console.log(pc.green(\"✓ \") + msg),\n warn: (msg: string) => console.log(pc.yellow(\"! \") + msg),\n error: (msg: string) => console.error(pc.red(\"✗ \") + msg),\n brand: (msg: string) => console.log(pc.bold(pc.magenta(\"vantage \")) + msg),\n}\n\n/** Print diagnostics as human-readable text. */\nexport function printDiagnostics(diags: Diagnostic[]): void {\n for (const d of diags) {\n const badge =\n d.severity === \"error\" ? pc.red(pc.bold(\" ERROR \")) : pc.yellow(pc.bold(\" WARN \"))\n console.log(`${badge} ${pc.dim(d.code)} ${d.message}`)\n if (d.files?.length) console.log(` ${pc.dim(\"files:\")} ${d.files.join(\", \")}`)\n if (d.fix) console.log(` ${pc.dim(\"fix:\")} ${d.fix}`)\n }\n}\n\n/** Emit a JSON payload to stdout (for agent consumption). */\nexport function printJson(payload: unknown): void {\n process.stdout.write(JSON.stringify(payload, null, 2) + \"\\n\")\n}\n\n/** Read the vantage package version. */\nexport function frameworkVersion(): string {\n try {\n // dist/cli.js (and shared chunks) live in dist/, so package.json is one up.\n const url = new URL(\"../package.json\", import.meta.url)\n const pkg = JSON.parse(fs.readFileSync(url, \"utf8\")) as { version: string }\n return pkg.version\n } catch {\n return \"0.0.0\"\n }\n}\n\nexport function fileExists(p: string): boolean {\n try {\n return fs.existsSync(p)\n } catch {\n return false\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/server/dev.ts","../src/vite/index.ts"],"names":["path"],"mappings":"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","file":"chunk-L3TW4FNA.js","sourcesContent":["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 { Plugin, PluginOption, ViteDevServer } from \"vite\"\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 * A route model the caller already scanned. `dev`/`build` run diagnostics\n * before starting Vite, so without this the project would be walked a second\n * time for an answer that is milliseconds old.\n */\n model?: RouteModel\n /**\n * Set when the caller has already written `.vantage/` for `model`. `build`\n * does, so that the server bundle — which reads `server-routes.gen.ts` — can\n * be produced at the same time as the client instead of after it.\n */\n artifactsWritten?: boolean\n}\n\nconst DEDUPE = [\"react\", \"react-dom\", \"@tanstack/react-router\", \"@tanstack/react-query\"]\n\n/** Always prebundled: the generated client entry imports these on every start. */\nconst RUNTIME_DEPS = [\n \"react\",\n \"react-dom\",\n \"react-dom/client\",\n \"react/jsx-runtime\",\n \"@tanstack/react-router\",\n \"@tanstack/react-query\",\n]\n\n/**\n * The rest of the managed stack — everything `@squadbase/vantage/ui` and\n * `/components` pull in. Apps import framework subpaths, never these directly,\n * so Vantage knows the full set up front and Vite does not have to rediscover\n * it. Declaring them removes the second optimize wave (and the full page reload\n * it forces) the first time a page reaches for a new kit component.\n */\nconst KIT_DEPS = [\n \"@tanstack/react-table\",\n \"class-variance-authority\",\n \"clsx\",\n \"cmdk\",\n \"date-fns\",\n \"date-fns/locale\",\n \"echarts\",\n \"lucide-react\",\n \"react-day-picker\",\n \"tailwind-merge\",\n \"@base-ui/react/accordion\",\n \"@base-ui/react/button\",\n \"@base-ui/react/checkbox\",\n \"@base-ui/react/collapsible\",\n \"@base-ui/react/dialog\",\n \"@base-ui/react/input\",\n \"@base-ui/react/menu\",\n \"@base-ui/react/merge-props\",\n \"@base-ui/react/popover\",\n \"@base-ui/react/progress\",\n \"@base-ui/react/scroll-area\",\n \"@base-ui/react/select\",\n \"@base-ui/react/separator\",\n \"@base-ui/react/slider\",\n \"@base-ui/react/switch\",\n \"@base-ui/react/tabs\",\n \"@base-ui/react/toggle\",\n \"@base-ui/react/toggle-group\",\n \"@base-ui/react/tooltip\",\n \"@base-ui/react/use-render\",\n]\n\n/** The package part of a specifier: `@base-ui/react/select` → `@base-ui/react`. */\nfunction packageName(spec: string): string {\n const parts = spec.split(\"/\")\n return spec.startsWith(\"@\") ? parts.slice(0, 2).join(\"/\") : parts[0]!\n}\n\n/** Walk up `node_modules` chains looking for a package directory. */\nfunction hasPackage(fromDir: string, pkg: string): boolean {\n let dir = fromDir\n for (;;) {\n if (fs.existsSync(path.join(dir, \"node_modules\", pkg))) return true\n const parent = path.dirname(dir)\n if (parent === dir) return false\n dir = parent\n }\n}\n\n/**\n * Build `optimizeDeps.include`, keeping only specifiers that actually resolve\n * from the project root.\n *\n * Two constraints pin this down. Vite hard-errors on an include entry it cannot\n * resolve, so guessing is not an option. And Vite's own dependency discovery\n * names these packages *plainly* — so the `parent > child` form, which would\n * reach the copy inside the framework's own node_modules, does not merge with\n * what discovery finds: it prebundles a second, never-requested copy of every\n * entry (measured: 156 files instead of 78).\n *\n * The practical effect is that a hoisted install (npm/yarn, and pnpm with\n * hoisting) declares the whole managed stack up front and skips the second\n * optimize wave — the one that forces a full page reload the first time a page\n * reaches for a new kit component. Under a strict pnpm layout the kit resolves\n * only from the framework package, nothing extra is declared, and behaviour is\n * exactly what it was before.\n */\nfunction optimizeInclude(root: string): string[] {\n return [...RUNTIME_DEPS, ...KIT_DEPS].filter((spec) => hasPackage(root, packageName(spec)))\n}\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 the dev-server defaults (including 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 = options.model ?? scanProject(root)\n /** Written once per start: `configResolved` and `buildStart` both need it. */\n let generated = Boolean(options.artifactsWritten)\n /** Cached dev shell, invalidated whenever the artifacts are rewritten. */\n let shellHtml: string | null = null\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 emit = (): void => {\n generateArtifacts({ root, model })\n generated = true\n shellHtml = null\n }\n\n /** Write the artifacts for the model we already have, at most once per start. */\n const ensureGenerated = (): void => {\n if (!generated) emit()\n }\n\n const regenerate = (): void => {\n model = scanProject(root)\n emit()\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: { include: optimizeInclude(root) },\n server: {\n // Browser console + runtime errors belong in the dev terminal: it is\n // the feedback surface both humans and agents already watch. Vite 8\n // forwards them natively — with source-mapped stacks and code frames,\n // which the hand-rolled beacon bridge this replaces could not do — but\n // only turns itself on when it detects an agent. Vantage wants it\n // always. warn/error only: forwarding `log`/`info` too lets one chatty\n // render loop bury the server's own output.\n forwardConsole: { unhandledErrors: true, logLevels: [\"warn\", \"error\"] },\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 ensureGenerated()\n },\n\n buildStart() {\n // configResolved already ran in the normal path; this is the safety net\n // for embedders that construct the plugin without a full config pass.\n ensureGenerated()\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 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 // 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 // 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 const onStructural = (file: string) => {\n if (rootMoved() || isPageFile(pageRoot(), file) || isApiFile(root, file) || isStylesFile(file)) {\n regenerate()\n server.ws.send({ type: \"full-reload\" })\n }\n }\n /**\n * A new directory can introduce route segments, so it has to be scanned —\n * but only when it could actually hold pages or API modules. Rescanning on\n * every mkdir (node_modules churn, build output, dot-dirs) walks the whole\n * project for nothing.\n */\n const isRouteDir = (dir: string) => {\n if (isServerFile(root, dir)) return true\n const rel = path.relative(pageRoot(), dir)\n if (rel === \"\" || rel.startsWith(\"..\")) return false\n return !rel.split(path.sep).some((s) => NON_ROUTE_DIRS.has(s) || s.startsWith(\".\"))\n }\n server.watcher.on(\"add\", onStructural)\n server.watcher.on(\"unlink\", onStructural)\n server.watcher.on(\"addDir\", (dir) => {\n if (rootMoved() || isRouteDir(dir)) regenerate()\n })\n server.watcher.on(\"unlinkDir\", (dir) => {\n if (!rootMoved() && !isRouteDir(dir)) return\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 // The shell is generated, not authored, and the plugin set that\n // transforms it is fixed — so the result only changes when the\n // artifacts are rewritten. Caching it keeps every navigation from\n // re-running the whole HTML transform chain.\n if (shellHtml === null) {\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 shellHtml = await server.transformIndexHtml(shellUrl, raw, req.originalUrl)\n }\n res.statusCode = 200\n res.setHeader(\"Content-Type\", \"text/html\")\n res.end(shellHtml)\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"]}
@@ -1,276 +0,0 @@
1
- import { detectApiMethods, stripComments } from './chunk-BAM33YZ6.js';
2
- import { timed } from './chunk-D4Y5RWJA.js';
3
- import { PUBLIC_ENV_PREFIX, FORBIDDEN_FILES, PAGE_EXTENSIONS, SRC_DIR, SUSPICIOUS_ROUTE_DIRS, API_METHODS } from './chunk-C4MQRWXS.js';
4
- import fs from 'fs';
5
- import path from 'path';
6
-
7
- // @squadbase/vantage — generated build. Do not edit.
8
- var ALLOWED_ENV_KEYS = /* @__PURE__ */ new Set(["MODE", "DEV", "PROD", "SSR", "BASE_URL", "PUBLIC_"]);
9
- function hasDefaultExport(src) {
10
- return /\bexport\s+default\b/.test(src) || /\bexport\s*\{[^}]*\bas\s+default\b[^}]*\}/.test(src) || /\bexport\s*\{[^}]*\bdefault\b[^}]*\}\s*from\b/.test(src);
11
- }
12
- function collectClientFiles(root) {
13
- const out = [];
14
- const skipDirs = /* @__PURE__ */ new Set(["node_modules", ".vantage", "dist", "server", "public"]);
15
- const walk = (dir) => {
16
- let entries;
17
- try {
18
- entries = fs.readdirSync(dir, { withFileTypes: true });
19
- } catch {
20
- return;
21
- }
22
- for (const entry of entries) {
23
- if (entry.name.startsWith(".")) continue;
24
- const abs = path.join(dir, entry.name);
25
- if (entry.isDirectory()) {
26
- if (skipDirs.has(entry.name)) continue;
27
- walk(abs);
28
- } else if (/\.(tsx?|jsx?)$/.test(entry.name)) {
29
- out.push(abs);
30
- }
31
- }
32
- };
33
- walk(root);
34
- return out;
35
- }
36
- function createCtx(root, model) {
37
- const sources = /* @__PURE__ */ new Map();
38
- let clientFiles = null;
39
- let rootEntries = null;
40
- return {
41
- root,
42
- model,
43
- source(abs) {
44
- const hit = sources.get(abs);
45
- if (hit !== void 0) return hit;
46
- let src;
47
- try {
48
- src = stripComments(fs.readFileSync(abs, "utf8"));
49
- } catch {
50
- src = null;
51
- }
52
- sources.set(abs, src);
53
- return src;
54
- },
55
- clientFiles() {
56
- return clientFiles ??= collectClientFiles(root);
57
- },
58
- rootEntries() {
59
- if (rootEntries) return rootEntries;
60
- try {
61
- rootEntries = fs.readdirSync(root);
62
- } catch {
63
- rootEntries = [];
64
- }
65
- return rootEntries;
66
- }
67
- };
68
- }
69
- function rel(root, abs) {
70
- return path.relative(root, abs).split(path.sep).join("/");
71
- }
72
- function checkForbiddenFiles(ctx) {
73
- const diags = [];
74
- for (const name of ctx.rootEntries()) {
75
- for (const rule of FORBIDDEN_FILES) {
76
- if (rule.pattern.test(name)) {
77
- diags.push({
78
- code: "FORBIDDEN_FILE",
79
- severity: "error",
80
- message: `${rule.label} file "${name}" is not allowed in a Vantage project.`,
81
- files: [name],
82
- fix: rule.remedy
83
- });
84
- }
85
- }
86
- }
87
- return diags;
88
- }
89
- function checkSrcLayout(ctx) {
90
- const { root, model } = ctx;
91
- if (model.pageDir === "") return [];
92
- const diags = [];
93
- const entries = ctx.rootEntries();
94
- const strayPages = entries.filter((name) => PAGE_EXTENSIONS.some((ext) => name.endsWith(ext)));
95
- if (strayPages.length > 0) {
96
- diags.push({
97
- code: "SRC_DIR_SPLIT",
98
- severity: "error",
99
- message: `${strayPages.length} page module(s) sit at the project root, but ${SRC_DIR}/ exists so pages are only scanned from ${SRC_DIR}/.`,
100
- files: strayPages.sort(),
101
- fix: `Move them into ${SRC_DIR}/, or delete ${SRC_DIR}/ to keep a root-level layout.`
102
- });
103
- }
104
- if (entries.includes("styles.css")) {
105
- diags.push({
106
- code: "SRC_DIR_SPLIT",
107
- severity: "error",
108
- message: `styles.css sits at the project root, but ${SRC_DIR}/ exists so the global stylesheet is read from ${SRC_DIR}/styles.css.`,
109
- files: ["styles.css"],
110
- fix: `Move it to ${SRC_DIR}/styles.css.`
111
- });
112
- }
113
- if (fs.existsSync(path.join(root, SRC_DIR, "server"))) {
114
- diags.push({
115
- code: "SRC_DIR_SPLIT",
116
- severity: "error",
117
- message: `${SRC_DIR}/server/ is never scanned: server code lives at the project root, outside the client source tree.`,
118
- files: [`${SRC_DIR}/server`],
119
- fix: `Move it to server/ at the project root.`
120
- });
121
- }
122
- return diags;
123
- }
124
- function checkSuspiciousRouteDirs(model) {
125
- const byDir = /* @__PURE__ */ new Map();
126
- for (const page of model.pages) {
127
- const top = page.dir.split("/")[0] ?? "";
128
- if (top === "" || !SUSPICIOUS_ROUTE_DIRS.has(top)) continue;
129
- const hit = byDir.get(top) ?? { files: [], routes: [] };
130
- hit.files.push(page.file);
131
- hit.routes.push(page.routePath);
132
- byDir.set(top, hit);
133
- }
134
- const diags = [];
135
- for (const [dir, hit] of byDir) {
136
- diags.push({
137
- code: "SUSPICIOUS_ROUTE_DIR",
138
- severity: "warning",
139
- message: `${dir}/ is part of the URL: ${hit.routes.slice(0, 3).join(", ")}${hit.routes.length > 3 ? ", \u2026" : ""}`,
140
- files: hit.files,
141
- fix: `Directory names become route segments. Non-page modules belong in components/, hooks/ or lib/ (never scanned); if ${dir}/ really is meant to be a URL segment, ignore this warning.`
142
- });
143
- }
144
- return diags;
145
- }
146
- function checkRouteConflicts(model) {
147
- const byPath = /* @__PURE__ */ new Map();
148
- for (const page of model.pages) {
149
- const list = byPath.get(page.routePath) ?? [];
150
- list.push(page.file);
151
- byPath.set(page.routePath, list);
152
- }
153
- const diags = [];
154
- for (const [routePath, files] of byPath) {
155
- if (files.length > 1) {
156
- diags.push({
157
- code: "ROUTE_CONFLICT",
158
- severity: "error",
159
- message: `${files.length} files resolve to ${routePath}`,
160
- files,
161
- fix: "Rename or remove one route file so each route is unique."
162
- });
163
- }
164
- }
165
- return diags;
166
- }
167
- function checkPageExports(ctx) {
168
- const { root, model } = ctx;
169
- const diags = [];
170
- const pageFiles = [
171
- ...model.pages.map((p) => p.absFile),
172
- ...model.layouts.map((l) => l.absFile),
173
- model.notFound && path.join(root, model.notFound),
174
- model.error && path.join(root, model.error)
175
- ].filter((x) => Boolean(x));
176
- for (const abs of pageFiles) {
177
- const src = ctx.source(abs);
178
- if (src === null) continue;
179
- if (!hasDefaultExport(src)) {
180
- diags.push({
181
- code: "MISSING_DEFAULT_EXPORT",
182
- severity: "error",
183
- message: `Page module has no default export.`,
184
- files: [rel(root, abs)],
185
- fix: "A page/layout must `export default` a React component."
186
- });
187
- }
188
- }
189
- return diags;
190
- }
191
- function checkApiExports(ctx) {
192
- const diags = [];
193
- for (const api of ctx.model.apis) {
194
- const src = ctx.source(api.absFile);
195
- if (src === null) continue;
196
- const exported = detectApiMethods(src);
197
- if (exported.length === 0) {
198
- const lower = ["get", "post", "put", "patch", "delete", "options"].filter(
199
- (m) => new RegExp(`export\\s+(async\\s+)?function\\s+${m}\\b`).test(src)
200
- );
201
- diags.push({
202
- code: "INVALID_API_EXPORT",
203
- severity: "error",
204
- message: `API module exports no HTTP method handler${lower.length ? ` (found lowercase "${lower.join(", ")}")` : ""}.`,
205
- files: [api.file],
206
- fix: `Export one of: ${API_METHODS.join(", ")} (uppercase).`
207
- });
208
- }
209
- }
210
- return diags;
211
- }
212
- function checkClientSources(ctx) {
213
- const { root } = ctx;
214
- const boundary = [];
215
- const env = [];
216
- const importRe = /(?:import|export)[^'"]*?from\s+["']([^"']+)["']|import\s*\(\s*["']([^"']+)["']\s*\)/g;
217
- const envRe = /import\.meta\.env\.([A-Za-z_][A-Za-z0-9_]*)/g;
218
- for (const abs of ctx.clientFiles()) {
219
- const src = ctx.source(abs);
220
- if (src === null) continue;
221
- let m;
222
- importRe.lastIndex = 0;
223
- while (m = importRe.exec(src)) {
224
- const spec = m[1] ?? m[2];
225
- if (!spec) continue;
226
- const isServer = spec === "server" || spec.startsWith("server/") || /(^|\/)\.\.?\/server(\/|$)/.test(spec) || /\/server\//.test(spec);
227
- if (isServer) {
228
- boundary.push({
229
- code: "CLIENT_IMPORTS_SERVER",
230
- severity: "error",
231
- message: `Client module imports from server/ ("${spec}").`,
232
- files: [rel(root, abs)],
233
- fix: "server/ code must never be imported by the client. Move shared code to lib/."
234
- });
235
- }
236
- }
237
- envRe.lastIndex = 0;
238
- const bad = /* @__PURE__ */ new Set();
239
- while (m = envRe.exec(src)) {
240
- const key = m[1];
241
- if (ALLOWED_ENV_KEYS.has(key)) continue;
242
- if (key.startsWith(PUBLIC_ENV_PREFIX)) continue;
243
- bad.add(key);
244
- }
245
- for (const key of bad) {
246
- env.push({
247
- code: "PUBLIC_ENV_MISUSE",
248
- severity: "warning",
249
- message: `Client reads non-public env "import.meta.env.${key}".`,
250
- files: [rel(root, abs)],
251
- fix: `Only ${PUBLIC_ENV_PREFIX}* vars reach the client. Read secrets via ApiContext.env in server/.`
252
- });
253
- }
254
- }
255
- return { boundary, env };
256
- }
257
- function runDiagnostics(root, model) {
258
- return timed("diagnostics", () => {
259
- const ctx = createCtx(root, model);
260
- const client = checkClientSources(ctx);
261
- return [
262
- ...checkForbiddenFiles(ctx),
263
- ...checkSrcLayout(ctx),
264
- ...checkSuspiciousRouteDirs(model),
265
- ...checkRouteConflicts(model),
266
- ...checkPageExports(ctx),
267
- ...checkApiExports(ctx),
268
- ...client.boundary,
269
- ...client.env
270
- ];
271
- });
272
- }
273
-
274
- export { runDiagnostics };
275
- //# sourceMappingURL=chunk-PSEYFYAP.js.map
276
- //# sourceMappingURL=chunk-PSEYFYAP.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/diagnostics.ts"],"names":[],"mappings":"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","file":"chunk-PSEYFYAP.js","sourcesContent":["import fs from \"node:fs\"\nimport path from \"node:path\"\nimport {\n API_METHODS,\n FORBIDDEN_FILES,\n PAGE_EXTENSIONS,\n PUBLIC_ENV_PREFIX,\n SRC_DIR,\n SUSPICIOUS_ROUTE_DIRS,\n} from \"./constants\"\nimport { timed } from \"./profile\"\nimport { detectApiMethods } from \"./route-spec\"\nimport { stripComments } from \"./source\"\nimport type { Diagnostic, RouteModel } from \"./types\"\n\n/** Vite/env identifiers that are always allowed on `import.meta.env`. */\nconst ALLOWED_ENV_KEYS = new Set([\"MODE\", \"DEV\", \"PROD\", \"SSR\", \"BASE_URL\", \"PUBLIC_\"])\n\n/** Whether a module has a default export (direct, aliased, or re-exported). */\nfunction hasDefaultExport(src: string): boolean {\n return (\n /\\bexport\\s+default\\b/.test(src) ||\n /\\bexport\\s*\\{[^}]*\\bas\\s+default\\b[^}]*\\}/.test(src) ||\n /\\bexport\\s*\\{[^}]*\\bdefault\\b[^}]*\\}\\s*from\\b/.test(src)\n )\n}\n\n/** Collect client-side source files (everything outside server/ and generated dirs). */\nfunction collectClientFiles(root: string): string[] {\n const out: string[] = []\n const skipDirs = new Set([\"node_modules\", \".vantage\", \"dist\", \"server\", \"public\"])\n const walk = (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 if (entry.name.startsWith(\".\")) continue\n const abs = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n if (skipDirs.has(entry.name)) continue\n walk(abs)\n } else if (/\\.(tsx?|jsx?)$/.test(entry.name)) {\n out.push(abs)\n }\n }\n }\n walk(root)\n return out\n}\n\n/**\n * Per-run scratch space. Every checker reads the filesystem through this, so a\n * `check` walks the project once and reads (and `stripComments`) each source\n * file at most once — page modules used to be read three times over, and the\n * client tree used to be walked twice.\n */\ninterface Ctx {\n root: string\n model: RouteModel\n /** Comment-stripped source for an absolute path; null when unreadable. */\n source(abs: string): string | null\n /** Client-side source files, walked lazily and only once. */\n clientFiles(): string[]\n /** `readdir` of the project root, read lazily and only once. */\n rootEntries(): string[]\n}\n\nfunction createCtx(root: string, model: RouteModel): Ctx {\n const sources = new Map<string, string | null>()\n let clientFiles: string[] | null = null\n let rootEntries: string[] | null = null\n\n return {\n root,\n model,\n source(abs) {\n const hit = sources.get(abs)\n if (hit !== undefined) return hit\n let src: string | null\n try {\n src = stripComments(fs.readFileSync(abs, \"utf8\"))\n } catch {\n src = null\n }\n sources.set(abs, src)\n return src\n },\n clientFiles() {\n return (clientFiles ??= collectClientFiles(root))\n },\n rootEntries() {\n if (rootEntries) return rootEntries\n try {\n rootEntries = fs.readdirSync(root)\n } catch {\n rootEntries = []\n }\n return rootEntries\n },\n }\n}\n\nfunction rel(root: string, abs: string): string {\n return path.relative(root, abs).split(path.sep).join(\"/\")\n}\n\n/** Detect forbidden config files at the project root. */\nfunction checkForbiddenFiles(ctx: Ctx): Diagnostic[] {\n const diags: Diagnostic[] = []\n for (const name of ctx.rootEntries()) {\n for (const rule of FORBIDDEN_FILES) {\n if (rule.pattern.test(name)) {\n diags.push({\n code: \"FORBIDDEN_FILE\",\n severity: \"error\",\n message: `${rule.label} file \"${name}\" is not allowed in a Vantage project.`,\n files: [name],\n fix: rule.remedy,\n })\n }\n }\n }\n return diags\n}\n\n/**\n * Detect a project split between `src/` and the project root. Once `src/`\n * exists it is the only page-scan root, so anything left behind at the root is\n * silently dead — and `server/` moved *into* `src/` is silently unserved.\n */\nfunction checkSrcLayout(ctx: Ctx): Diagnostic[] {\n const { root, model } = ctx\n if (model.pageDir === \"\") return []\n const diags: Diagnostic[] = []\n\n const entries = ctx.rootEntries()\n const strayPages = entries.filter((name) => PAGE_EXTENSIONS.some((ext) => name.endsWith(ext)))\n if (strayPages.length > 0) {\n diags.push({\n code: \"SRC_DIR_SPLIT\",\n severity: \"error\",\n message: `${strayPages.length} page module(s) sit at the project root, but ${SRC_DIR}/ exists so pages are only scanned from ${SRC_DIR}/.`,\n files: strayPages.sort(),\n fix: `Move them into ${SRC_DIR}/, or delete ${SRC_DIR}/ to keep a root-level layout.`,\n })\n }\n\n if (entries.includes(\"styles.css\")) {\n diags.push({\n code: \"SRC_DIR_SPLIT\",\n severity: \"error\",\n message: `styles.css sits at the project root, but ${SRC_DIR}/ exists so the global stylesheet is read from ${SRC_DIR}/styles.css.`,\n files: [\"styles.css\"],\n fix: `Move it to ${SRC_DIR}/styles.css.`,\n })\n }\n\n if (fs.existsSync(path.join(root, SRC_DIR, \"server\"))) {\n diags.push({\n code: \"SRC_DIR_SPLIT\",\n severity: \"error\",\n message: `${SRC_DIR}/server/ is never scanned: server code lives at the project root, outside the client source tree.`,\n files: [`${SRC_DIR}/server`],\n fix: `Move it to server/ at the project root.`,\n })\n }\n\n return diags\n}\n\n/** Flag routes generated from directories that are almost certainly scaffolding. */\nfunction checkSuspiciousRouteDirs(model: RouteModel): Diagnostic[] {\n const byDir = new Map<string, { files: string[]; routes: string[] }>()\n for (const page of model.pages) {\n const top = page.dir.split(\"/\")[0] ?? \"\"\n if (top === \"\" || !SUSPICIOUS_ROUTE_DIRS.has(top)) continue\n const hit = byDir.get(top) ?? { files: [], routes: [] }\n hit.files.push(page.file)\n hit.routes.push(page.routePath)\n byDir.set(top, hit)\n }\n\n const diags: Diagnostic[] = []\n for (const [dir, hit] of byDir) {\n diags.push({\n code: \"SUSPICIOUS_ROUTE_DIR\",\n severity: \"warning\",\n message: `${dir}/ is part of the URL: ${hit.routes.slice(0, 3).join(\", \")}${\n hit.routes.length > 3 ? \", …\" : \"\"\n }`,\n files: hit.files,\n fix: `Directory names become route segments. Non-page modules belong in components/, hooks/ or lib/ (never scanned); if ${dir}/ really is meant to be a URL segment, ignore this warning.`,\n })\n }\n return diags\n}\n\n/** Detect two page files resolving to the same route path. */\nfunction checkRouteConflicts(model: RouteModel): Diagnostic[] {\n const byPath = new Map<string, string[]>()\n for (const page of model.pages) {\n const list = byPath.get(page.routePath) ?? []\n list.push(page.file)\n byPath.set(page.routePath, list)\n }\n const diags: Diagnostic[] = []\n for (const [routePath, files] of byPath) {\n if (files.length > 1) {\n diags.push({\n code: \"ROUTE_CONFLICT\",\n severity: \"error\",\n message: `${files.length} files resolve to ${routePath}`,\n files,\n fix: \"Rename or remove one route file so each route is unique.\",\n })\n }\n }\n return diags\n}\n\n/** Ensure every page module has a default export. */\nfunction checkPageExports(ctx: Ctx): Diagnostic[] {\n const { root, model } = ctx\n const diags: Diagnostic[] = []\n const pageFiles = [\n ...model.pages.map((p) => p.absFile),\n ...model.layouts.map((l) => l.absFile),\n model.notFound && path.join(root, model.notFound),\n model.error && path.join(root, model.error),\n ].filter((x): x is string => Boolean(x))\n\n for (const abs of pageFiles) {\n const src = ctx.source(abs)\n if (src === null) continue\n if (!hasDefaultExport(src)) {\n diags.push({\n code: \"MISSING_DEFAULT_EXPORT\",\n severity: \"error\",\n message: `Page module has no default export.`,\n files: [rel(root, abs)],\n fix: \"A page/layout must `export default` a React component.\",\n })\n }\n }\n return diags\n}\n\n/** Ensure every API module exports at least one valid HTTP method handler. */\nfunction checkApiExports(ctx: Ctx): Diagnostic[] {\n const diags: Diagnostic[] = []\n for (const api of ctx.model.apis) {\n const src = ctx.source(api.absFile)\n if (src === null) continue\n const exported = detectApiMethods(src)\n if (exported.length === 0) {\n // Common mistake: lowercase method names.\n const lower = [\"get\", \"post\", \"put\", \"patch\", \"delete\", \"options\"].filter((m) =>\n new RegExp(`export\\\\s+(async\\\\s+)?function\\\\s+${m}\\\\b`).test(src),\n )\n diags.push({\n code: \"INVALID_API_EXPORT\",\n severity: \"error\",\n message: `API module exports no HTTP method handler${\n lower.length ? ` (found lowercase \"${lower.join(\", \")}\")` : \"\"\n }.`,\n files: [api.file],\n fix: `Export one of: ${API_METHODS.join(\", \")} (uppercase).`,\n })\n }\n }\n return diags\n}\n\n/**\n * The two source-level client checks — the server-import boundary and non-public\n * env reads — in a single pass over the client tree. They used to walk and read\n * the whole tree once each; the diagnostics are still emitted grouped by code so\n * the reported order is unchanged.\n */\nfunction checkClientSources(ctx: Ctx): { boundary: Diagnostic[]; env: Diagnostic[] } {\n const { root } = ctx\n const boundary: Diagnostic[] = []\n const env: Diagnostic[] = []\n const importRe = /(?:import|export)[^'\"]*?from\\s+[\"']([^\"']+)[\"']|import\\s*\\(\\s*[\"']([^\"']+)[\"']\\s*\\)/g\n const envRe = /import\\.meta\\.env\\.([A-Za-z_][A-Za-z0-9_]*)/g\n\n for (const abs of ctx.clientFiles()) {\n const src = ctx.source(abs)\n if (src === null) continue\n\n let m: RegExpExecArray | null\n importRe.lastIndex = 0\n while ((m = importRe.exec(src))) {\n const spec = m[1] ?? m[2]\n if (!spec) continue\n const isServer =\n spec === \"server\" ||\n spec.startsWith(\"server/\") ||\n /(^|\\/)\\.\\.?\\/server(\\/|$)/.test(spec) ||\n /\\/server\\//.test(spec)\n if (isServer) {\n boundary.push({\n code: \"CLIENT_IMPORTS_SERVER\",\n severity: \"error\",\n message: `Client module imports from server/ (\"${spec}\").`,\n files: [rel(root, abs)],\n fix: \"server/ code must never be imported by the client. Move shared code to lib/.\",\n })\n }\n }\n\n envRe.lastIndex = 0\n const bad = new Set<string>()\n while ((m = envRe.exec(src))) {\n const key = m[1]!\n if (ALLOWED_ENV_KEYS.has(key)) continue\n if (key.startsWith(PUBLIC_ENV_PREFIX)) continue\n bad.add(key)\n }\n for (const key of bad) {\n env.push({\n code: \"PUBLIC_ENV_MISUSE\",\n severity: \"warning\",\n message: `Client reads non-public env \"import.meta.env.${key}\".`,\n files: [rel(root, abs)],\n fix: `Only ${PUBLIC_ENV_PREFIX}* vars reach the client. Read secrets via ApiContext.env in server/.`,\n })\n }\n }\n return { boundary, env }\n}\n\n/** Run all static diagnostics for a project. */\nexport function runDiagnostics(root: string, model: RouteModel): Diagnostic[] {\n return timed(\"diagnostics\", () => {\n const ctx = createCtx(root, model)\n const client = checkClientSources(ctx)\n return [\n ...checkForbiddenFiles(ctx),\n ...checkSrcLayout(ctx),\n ...checkSuspiciousRouteDirs(model),\n ...checkRouteConflicts(model),\n ...checkPageExports(ctx),\n ...checkApiExports(ctx),\n ...client.boundary,\n ...client.env,\n ]\n })\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/generate.ts"],"names":["require"],"mappings":"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","file":"chunk-RA6Z3OX3.js","sourcesContent":["import fs from \"node:fs\"\nimport path from \"node:path\"\nimport { createRequire } from \"node:module\"\nimport { MANIFEST_SCHEMA_VERSION, VANTAGE_DIR } from \"./constants\"\nimport { timed } from \"./profile\"\nimport { buildRouteTree } from \"./route-tree\"\nimport type { RouteModel, Segment } from \"./types\"\n\nconst PKG = \"@squadbase/vantage\"\n\n/**\n * Resolve the absolute directory of the installed @squadbase/vantage package.\n * Memoized per root: module resolution is comparatively expensive and the answer\n * cannot change while the process lives.\n */\nconst vantageDirCache = new Map<string, string | null>()\n\nfunction resolveVantageDir(root: string): string | null {\n const hit = vantageDirCache.get(root)\n if (hit !== undefined) return hit\n let dir: string | null\n try {\n const require = createRequire(path.join(root, \"noop.js\"))\n dir = path.dirname(require.resolve(`${PKG}/package.json`))\n } catch {\n dir = null\n }\n vantageDirCache.set(root, dir)\n return dir\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 return timed(\"generate\", () => {\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}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/route-tree.ts"],"names":["depth"],"mappings":"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","file":"chunk-VXAV2435.js","sourcesContent":["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\ninterface PageMeta {\n title?: string\n description?: string\n navLabel?: string\n}\n\n/**\n * Cache keyed on mtime+size. A long-lived dev server regenerates the route tree\n * on every structural change, and re-reading + re-parsing every page module for\n * metadata that almost never changes is pure waste. `statSync` is an order of\n * magnitude cheaper than the read plus the brace scan it feeds.\n */\nconst metaCache = new Map<string, { mtimeMs: number; size: number; meta: PageMeta }>()\n\nfunction parsePageMeta(src: string): PageMeta {\n const args = extractDefinePageArgs(src)\n if (args == null) return {}\n const meta: PageMeta = {}\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/** Best-effort static extraction of definePage title/description/navLabel. */\nexport function extractPageMeta(absFile: string): PageMeta {\n let stat: fs.Stats\n try {\n stat = fs.statSync(absFile)\n } catch {\n return {}\n }\n const hit = metaCache.get(absFile)\n if (hit && hit.mtimeMs === stat.mtimeMs && hit.size === stat.size) return hit.meta\n\n let src: string\n try {\n src = fs.readFileSync(absFile, \"utf8\")\n } catch {\n return {}\n }\n const meta = parsePageMeta(src)\n metaCache.set(absFile, { mtimeMs: stat.mtimeMs, size: stat.size, meta })\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"]}