@squadbase/vantage 0.3.0 → 0.4.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.
Files changed (59) hide show
  1. package/README.md +1 -1
  2. package/dist/add-GQEXRQSI.js +6 -0
  3. package/dist/add-GQEXRQSI.js.map +1 -0
  4. package/dist/build-77KHIRWR.js +108 -0
  5. package/dist/build-77KHIRWR.js.map +1 -0
  6. package/dist/check-26U4O5UW.js +38 -0
  7. package/dist/check-26U4O5UW.js.map +1 -0
  8. package/dist/chunk-2KRCGXBY.js +56 -0
  9. package/dist/chunk-2KRCGXBY.js.map +1 -0
  10. package/dist/chunk-BAM33YZ6.js +202 -0
  11. package/dist/chunk-BAM33YZ6.js.map +1 -0
  12. package/dist/chunk-C4MQRWXS.js +81 -0
  13. package/dist/chunk-C4MQRWXS.js.map +1 -0
  14. package/dist/chunk-D4Y5RWJA.js +189 -0
  15. package/dist/chunk-D4Y5RWJA.js.map +1 -0
  16. package/dist/chunk-N6HAGEUA.js +136 -0
  17. package/dist/chunk-N6HAGEUA.js.map +1 -0
  18. package/dist/chunk-PSEYFYAP.js +276 -0
  19. package/dist/chunk-PSEYFYAP.js.map +1 -0
  20. package/dist/chunk-R2YYVCGS.js +345 -0
  21. package/dist/chunk-R2YYVCGS.js.map +1 -0
  22. package/dist/chunk-RA6Z3OX3.js +199 -0
  23. package/dist/chunk-RA6Z3OX3.js.map +1 -0
  24. package/dist/chunk-VXAV2435.js +142 -0
  25. package/dist/chunk-VXAV2435.js.map +1 -0
  26. package/dist/chunk-ZIM745WE.js +267 -0
  27. package/dist/chunk-ZIM745WE.js.map +1 -0
  28. package/dist/cli.js +27 -1677
  29. package/dist/cli.js.map +1 -1
  30. package/dist/dev-5K2PNSXT.js +67 -0
  31. package/dist/dev-5K2PNSXT.js.map +1 -0
  32. package/dist/docs-XEPM66VI.js +114 -0
  33. package/dist/docs-XEPM66VI.js.map +1 -0
  34. package/dist/doctor-6UMWKG6L.js +58 -0
  35. package/dist/doctor-6UMWKG6L.js.map +1 -0
  36. package/dist/index.d.ts +1 -1
  37. package/dist/index.js +1 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/preview-VXERMTHP.js +61 -0
  40. package/dist/preview-VXERMTHP.js.map +1 -0
  41. package/dist/routes-3JUXAYQJ.js +119 -0
  42. package/dist/routes-3JUXAYQJ.js.map +1 -0
  43. package/dist/search-NJJW4PXG.js +325 -0
  44. package/dist/search-NJJW4PXG.js.map +1 -0
  45. package/dist/server/node.d.ts +1 -12
  46. package/dist/types-De3mo_hv.d.ts +59 -0
  47. package/dist/upgrade-4XAY447F.js +29 -0
  48. package/dist/upgrade-4XAY447F.js.map +1 -0
  49. package/dist/vite/index.d.ts +13 -0
  50. package/dist/vite/index.js +5 -1
  51. package/docs/en/changelog.md +71 -0
  52. package/docs/en/cli-reference.md +60 -0
  53. package/docs/ja/changelog.md +65 -0
  54. package/docs/ja/cli-reference.md +60 -0
  55. package/package.json +7 -4
  56. package/skills/vantage-app/SKILL.md +1 -1
  57. package/templates/AGENTS.md +1 -1
  58. package/dist/chunk-5UGRNXHC.js +0 -802
  59. package/dist/chunk-5UGRNXHC.js.map +0 -1
@@ -0,0 +1,199 @@
1
+ import { buildRouteTree } from './chunk-VXAV2435.js';
2
+ import { timed } from './chunk-D4Y5RWJA.js';
3
+ import { VANTAGE_DIR, MANIFEST_SCHEMA_VERSION } from './chunk-C4MQRWXS.js';
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ import { createRequire } from 'module';
7
+
8
+ // @squadbase/vantage — generated build. Do not edit.
9
+ var PKG = "@squadbase/vantage";
10
+ var vantageDirCache = /* @__PURE__ */ new Map();
11
+ function resolveVantageDir(root) {
12
+ const hit = vantageDirCache.get(root);
13
+ if (hit !== void 0) return hit;
14
+ let dir;
15
+ try {
16
+ const require2 = createRequire(path.join(root, "noop.js"));
17
+ dir = path.dirname(require2.resolve(`${PKG}/package.json`));
18
+ } catch {
19
+ dir = null;
20
+ }
21
+ vantageDirCache.set(root, dir);
22
+ return dir;
23
+ }
24
+ function importFromVantage(relFile) {
25
+ return `../${relFile}`;
26
+ }
27
+ function ensureDir(dir) {
28
+ fs.mkdirSync(dir, { recursive: true });
29
+ }
30
+ function writeIfChanged(file, content) {
31
+ try {
32
+ if (fs.existsSync(file) && fs.readFileSync(file, "utf8") === content) return;
33
+ } catch {
34
+ }
35
+ fs.writeFileSync(file, content);
36
+ }
37
+ function serializeSegments(segments) {
38
+ return "[" + segments.map((s) => {
39
+ if (s.kind === "static") return `{ kind: "static", value: ${JSON.stringify(s.value)} }`;
40
+ if (s.kind === "param") return `{ kind: "param", name: ${JSON.stringify(s.name)} }`;
41
+ return `{ kind: "catchall", name: ${JSON.stringify(s.name)} }`;
42
+ }).join(", ") + "]";
43
+ }
44
+ var BANNER = "// AUTO-GENERATED by @squadbase/vantage. Do not edit \u2014 regenerated on every run.\n";
45
+ function renderRouteTree(model) {
46
+ const tree = buildRouteTree(model);
47
+ const lines = [];
48
+ lines.push(BANNER);
49
+ lines.push(`import type { ClientManifest } from "${PKG}/client"`);
50
+ lines.push("");
51
+ lines.push("export const manifest: ClientManifest = {");
52
+ lines.push(
53
+ ` rootLayout: ${tree.rootLayout ? `() => import(${JSON.stringify(importFromVantage(tree.rootLayout))})` : "null"},`
54
+ );
55
+ lines.push(
56
+ ` notFound: ${tree.notFound ? `() => import(${JSON.stringify(importFromVantage(tree.notFound))})` : "null"},`
57
+ );
58
+ lines.push(
59
+ ` error: ${tree.error ? `() => import(${JSON.stringify(importFromVantage(tree.error))})` : "null"},`
60
+ );
61
+ lines.push(" layouts: [");
62
+ for (const l of tree.layouts) {
63
+ lines.push(
64
+ ` { id: ${JSON.stringify(l.id)}, parentId: ${JSON.stringify(l.parentId)}, path: ${JSON.stringify(
65
+ l.path
66
+ )}, load: () => import(${JSON.stringify(importFromVantage(l.file))}) },`
67
+ );
68
+ }
69
+ lines.push(" ],");
70
+ lines.push(" pages: [");
71
+ for (const p of tree.pages) {
72
+ const extra = [];
73
+ if (p.title) extra.push(`title: ${JSON.stringify(p.title)}`);
74
+ if (p.description) extra.push(`description: ${JSON.stringify(p.description)}`);
75
+ if (p.navLabel) extra.push(`navLabel: ${JSON.stringify(p.navLabel)}`);
76
+ lines.push(
77
+ ` { parentLayoutId: ${JSON.stringify(p.parentLayoutId)}, path: ${JSON.stringify(
78
+ p.path
79
+ )}, index: ${p.index}, routePath: ${JSON.stringify(p.routePath)}${extra.length ? ", " + extra.join(", ") : ""}, load: () => import(${JSON.stringify(importFromVantage(p.file))}) },`
80
+ );
81
+ }
82
+ lines.push(" ],");
83
+ lines.push("}");
84
+ lines.push("");
85
+ return lines.join("\n");
86
+ }
87
+ function renderServerRoutes(model) {
88
+ const lines = [];
89
+ lines.push(BANNER);
90
+ lines.push(`import type { ProdApiRoute } from "${PKG}/server/node"`);
91
+ model.apis.forEach((a, i) => {
92
+ lines.push(`import * as m${i} from ${JSON.stringify(importFromVantage(a.file))}`);
93
+ });
94
+ lines.push("");
95
+ lines.push("export const apiRoutes: ProdApiRoute[] = [");
96
+ model.apis.forEach((a, i) => {
97
+ lines.push(
98
+ ` { routePath: ${JSON.stringify(a.routePath)}, segments: ${serializeSegments(
99
+ a.segments
100
+ )}, module: m${i} },`
101
+ );
102
+ });
103
+ lines.push("]");
104
+ lines.push("");
105
+ return lines.join("\n");
106
+ }
107
+ function renderIndexHtml() {
108
+ return `<!doctype html>
109
+ <html lang="en">
110
+ <head>
111
+ <meta charset="UTF-8" />
112
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
113
+ <title>Vantage</title>
114
+ </head>
115
+ <body>
116
+ <div id="root"></div>
117
+ <script type="module" src="/.vantage/client-entry.tsx"></script>
118
+ </body>
119
+ </html>
120
+ `;
121
+ }
122
+ function renderClientEntry() {
123
+ return `${BANNER}import { bootstrap } from "${PKG}/client"
124
+ import { manifest } from "./route-tree.gen"
125
+ import "./runtime.css"
126
+
127
+ bootstrap(manifest)
128
+ `;
129
+ }
130
+ function renderRuntimeCss(root, pageDir) {
131
+ const parts = [];
132
+ parts.push('@import "tailwindcss";');
133
+ parts.push(`@import "${PKG}/theme.css";`);
134
+ const stylesRel = pageDir === "" ? "styles.css" : `${pageDir}/styles.css`;
135
+ if (fs.existsSync(path.join(root, stylesRel))) {
136
+ parts.push(`@import "../${stylesRel}";`);
137
+ }
138
+ const vantageDir = resolveVantageDir(root);
139
+ if (vantageDir) {
140
+ parts.push(`@source ${JSON.stringify(path.join(vantageDir, "dist"))};`);
141
+ }
142
+ return parts.join("\n") + "\n";
143
+ }
144
+ function renderEnvTypes() {
145
+ return `${BANNER}
146
+ interface ImportMetaEnv {
147
+ readonly MODE: string
148
+ readonly DEV: boolean
149
+ readonly PROD: boolean
150
+ readonly SSR: boolean
151
+ readonly BASE_URL: string
152
+ readonly [key: \`PUBLIC_\${string}\`]: string | undefined
153
+ }
154
+
155
+ interface ImportMeta {
156
+ readonly env: ImportMetaEnv
157
+ }
158
+
159
+ declare module "*.css" {
160
+ const content: string
161
+ export default content
162
+ }
163
+ `;
164
+ }
165
+ function renderInternalManifest(model) {
166
+ return JSON.stringify(
167
+ {
168
+ schemaVersion: MANIFEST_SCHEMA_VERSION,
169
+ pageDir: model.pageDir,
170
+ pages: model.pages.map((p) => ({ file: p.file, route: p.routePath })),
171
+ apis: model.apis.map((a) => ({ file: a.file, route: a.routePath })),
172
+ hasServer: model.hasServer
173
+ },
174
+ null,
175
+ 2
176
+ ) + "\n";
177
+ }
178
+ function generateArtifacts({ root, model }) {
179
+ return timed("generate", () => {
180
+ const vantageDir = path.join(root, VANTAGE_DIR);
181
+ ensureDir(vantageDir);
182
+ ensureDir(path.join(vantageDir, "types"));
183
+ writeIfChanged(path.join(vantageDir, ".gitignore"), "*\n");
184
+ writeIfChanged(path.join(vantageDir, "index.html"), renderIndexHtml());
185
+ writeIfChanged(path.join(vantageDir, "client-entry.tsx"), renderClientEntry());
186
+ writeIfChanged(path.join(vantageDir, "route-tree.gen.ts"), renderRouteTree(model));
187
+ writeIfChanged(path.join(vantageDir, "runtime.css"), renderRuntimeCss(root, model.pageDir));
188
+ writeIfChanged(path.join(vantageDir, "types", "env.d.ts"), renderEnvTypes());
189
+ writeIfChanged(path.join(vantageDir, "manifest.json"), renderInternalManifest(model));
190
+ if (model.hasServer) {
191
+ writeIfChanged(path.join(vantageDir, "server-routes.gen.ts"), renderServerRoutes(model));
192
+ }
193
+ return vantageDir;
194
+ });
195
+ }
196
+
197
+ export { generateArtifacts };
198
+ //# sourceMappingURL=chunk-RA6Z3OX3.js.map
199
+ //# sourceMappingURL=chunk-RA6Z3OX3.js.map
@@ -0,0 +1 @@
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"]}
@@ -0,0 +1,142 @@
1
+ import fs from 'fs';
2
+
3
+ // @squadbase/vantage — generated build. Do not edit.
4
+
5
+ function segToRouter(s) {
6
+ if (s.kind === "static") return s.value;
7
+ if (s.kind === "param") return `$${s.name}`;
8
+ return "$";
9
+ }
10
+ function dirToRouterPath(relDir) {
11
+ return relDir.split("/").filter(Boolean).map((token) => {
12
+ const catchall = token.match(/^\[\.\.\.(.+)\]$/);
13
+ if (catchall) return "$";
14
+ const param = token.match(/^\[(.+)\]$/);
15
+ if (param) return `$${param[1]}`;
16
+ return token;
17
+ }).join("/");
18
+ }
19
+ function isAncestorDir(ancestor, dir) {
20
+ if (ancestor === "") return true;
21
+ return dir === ancestor || dir.startsWith(ancestor + "/");
22
+ }
23
+ function isStrictAncestorDir(ancestor, dir) {
24
+ return dir.startsWith(ancestor + "/");
25
+ }
26
+ function depth(dir) {
27
+ return dir === "" ? 0 : dir.split("/").length;
28
+ }
29
+ function extractDefinePageArgs(src) {
30
+ const call = src.match(/\bdefinePage\s*\(/);
31
+ if (!call) return null;
32
+ let i = (call.index ?? 0) + call[0].length;
33
+ while (i < src.length && /\s/.test(src[i])) i++;
34
+ if (src[i] !== "{") return null;
35
+ const start = i;
36
+ let depth2 = 0;
37
+ for (; i < src.length; i++) {
38
+ const c = src[i];
39
+ if (c === "{") depth2++;
40
+ else if (c === "}" && --depth2 === 0) return src.slice(start + 1, i);
41
+ }
42
+ return null;
43
+ }
44
+ function matchStringField(scope, key) {
45
+ const re = new RegExp(
46
+ `\\b${key}\\s*:\\s*(?:"((?:\\\\.|[^"\\\\])*)"|'((?:\\\\.|[^'\\\\])*)'|\`((?:\\\\.|[^\`\\\\])*)\`)`
47
+ );
48
+ const m = scope.match(re);
49
+ if (!m) return void 0;
50
+ return (m[1] ?? m[2] ?? m[3] ?? "").replace(/\\(.)/g, "$1");
51
+ }
52
+ var metaCache = /* @__PURE__ */ new Map();
53
+ function parsePageMeta(src) {
54
+ const args = extractDefinePageArgs(src);
55
+ if (args == null) return {};
56
+ const meta = {};
57
+ const title = matchStringField(args, "title");
58
+ const description = matchStringField(args, "description");
59
+ const navLabel = matchStringField(args, "navLabel");
60
+ if (title) meta.title = title;
61
+ if (description) meta.description = description;
62
+ if (navLabel) meta.navLabel = navLabel;
63
+ return meta;
64
+ }
65
+ function extractPageMeta(absFile) {
66
+ let stat;
67
+ try {
68
+ stat = fs.statSync(absFile);
69
+ } catch {
70
+ return {};
71
+ }
72
+ const hit = metaCache.get(absFile);
73
+ if (hit && hit.mtimeMs === stat.mtimeMs && hit.size === stat.size) return hit.meta;
74
+ let src;
75
+ try {
76
+ src = fs.readFileSync(absFile, "utf8");
77
+ } catch {
78
+ return {};
79
+ }
80
+ const meta = parsePageMeta(src);
81
+ metaCache.set(absFile, { mtimeMs: stat.mtimeMs, size: stat.size, meta });
82
+ return meta;
83
+ }
84
+ function buildRouteTree(model) {
85
+ const rootLayoutRoute = model.layouts.find((l) => l.dir === "") ?? null;
86
+ const nestedLayouts = model.layouts.filter((l) => l.dir !== "").sort((a, b) => depth(a.dir) - depth(b.dir));
87
+ const built = [];
88
+ const dirToId = /* @__PURE__ */ new Map();
89
+ nestedLayouts.forEach((layout, i) => {
90
+ const id = `L${i}`;
91
+ let parent = null;
92
+ for (const cand of built) {
93
+ if (isStrictAncestorDir(cand.dir, layout.dir)) {
94
+ if (!parent || depth(cand.dir) > depth(parent.dir)) parent = { id: cand.id, dir: cand.dir };
95
+ }
96
+ }
97
+ const parentDir = parent ? parent.dir : "";
98
+ const relDir = parentDir === "" ? layout.dir : layout.dir.slice(parentDir.length + 1);
99
+ built.push({
100
+ id,
101
+ dir: layout.dir,
102
+ parentId: parent ? parent.id : null,
103
+ path: dirToRouterPath(relDir),
104
+ file: layout.file
105
+ });
106
+ dirToId.set(layout.dir, id);
107
+ });
108
+ const pages = model.pages.map((page) => {
109
+ let owner = null;
110
+ for (const l of built) {
111
+ if (isAncestorDir(l.dir, page.dir)) {
112
+ if (!owner || depth(l.dir) > depth(owner.dir)) owner = l;
113
+ }
114
+ }
115
+ const ownerSegCount = owner ? depth(owner.dir) : 0;
116
+ const remaining = page.segments.slice(ownerSegCount);
117
+ const index = remaining.length === 0;
118
+ const path = index ? "/" : remaining.map(segToRouter).join("/");
119
+ const meta = extractPageMeta(page.absFile);
120
+ return {
121
+ file: page.file,
122
+ routePath: page.routePath,
123
+ parentLayoutId: owner ? owner.id : null,
124
+ path,
125
+ index,
126
+ ...meta.title ? { title: meta.title } : {},
127
+ ...meta.description ? { description: meta.description } : {},
128
+ ...meta.navLabel ? { navLabel: meta.navLabel } : {}
129
+ };
130
+ });
131
+ return {
132
+ rootLayout: rootLayoutRoute ? rootLayoutRoute.file : null,
133
+ notFound: model.notFound,
134
+ error: model.error,
135
+ layouts: built,
136
+ pages
137
+ };
138
+ }
139
+
140
+ export { buildRouteTree, extractPageMeta };
141
+ //# sourceMappingURL=chunk-VXAV2435.js.map
142
+ //# sourceMappingURL=chunk-VXAV2435.js.map
@@ -0,0 +1 @@
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"]}
@@ -0,0 +1,267 @@
1
+ import { resolvePageRoot } from './chunk-D4Y5RWJA.js';
2
+ import { log } from './chunk-N6HAGEUA.js';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { createRequire } from 'module';
6
+
7
+ // @squadbase/vantage — generated build. Do not edit.
8
+ var PKG = "@squadbase/vantage";
9
+ function toPascalCase(segment) {
10
+ const cleaned = segment.replace(/\[|\]|\./g, "").replace(/\.\.\./g, "");
11
+ const words = cleaned.split(/[^a-zA-Z0-9]+/).filter(Boolean);
12
+ const pascal = words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
13
+ return /^[A-Za-z]/.test(pascal) ? pascal : "Page";
14
+ }
15
+ function pageTemplate(name) {
16
+ const last = name.split("/").pop() ?? name;
17
+ const component = last === "index" ? toPascalCase(name.split("/").slice(-2)[0] ?? "Home") : toPascalCase(last);
18
+ const title = last.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
19
+ return `import { definePage } from "${PKG}"
20
+
21
+ export const page = definePage({ title: ${JSON.stringify(title)} })
22
+
23
+ export default function ${component}() {
24
+ return (
25
+ <main className="p-6">
26
+ <h1 className="text-2xl font-semibold">${title}</h1>
27
+ </main>
28
+ )
29
+ }
30
+ `;
31
+ }
32
+ function apiTemplate() {
33
+ return `import type { ApiContext } from "${PKG}/server"
34
+
35
+ export async function GET({ request, params }: ApiContext) {
36
+ return Response.json({ ok: true, params })
37
+ }
38
+ `;
39
+ }
40
+ function resolvePackageDir(root, sub) {
41
+ try {
42
+ const require2 = createRequire(path.join(root, "noop.js"));
43
+ const pkgJson = require2.resolve(`${PKG}/package.json`);
44
+ return path.join(path.dirname(pkgJson), sub);
45
+ } catch {
46
+ return null;
47
+ }
48
+ }
49
+ function resolveRegistryDir(root) {
50
+ return resolvePackageDir(root, "registry");
51
+ }
52
+ var SKILL_FILE = "SKILL.md";
53
+ var SKILL_SCAN_SKIP = /* @__PURE__ */ new Set([
54
+ "node_modules",
55
+ ".git",
56
+ ".vantage",
57
+ "dist",
58
+ "build",
59
+ "out",
60
+ "coverage",
61
+ ".next",
62
+ ".turbo",
63
+ ".cache",
64
+ ".vercel"
65
+ ]);
66
+ var SKILL_SCAN_DEPTH = 4;
67
+ function listBundledSkills(skillsDir) {
68
+ try {
69
+ return fs.readdirSync(skillsDir, { withFileTypes: true }).filter((e) => e.isDirectory() && fs.existsSync(path.join(skillsDir, e.name, SKILL_FILE))).map((e) => e.name).sort();
70
+ } catch {
71
+ return [];
72
+ }
73
+ }
74
+ function displayPath(root, target) {
75
+ const rel = path.relative(root, target);
76
+ return !rel ? "." : rel.startsWith("..") ? target : rel;
77
+ }
78
+ function findPlacedSkills(root, names, skillsDir) {
79
+ const wanted = new Set(names);
80
+ const found = /* @__PURE__ */ new Map();
81
+ const isSource = (p) => !path.relative(skillsDir, p).startsWith("..");
82
+ const walk = (dir, depth) => {
83
+ let entries;
84
+ try {
85
+ entries = fs.readdirSync(dir, { withFileTypes: true });
86
+ } catch {
87
+ return;
88
+ }
89
+ for (const entry of entries) {
90
+ if (!entry.isDirectory() || SKILL_SCAN_SKIP.has(entry.name)) continue;
91
+ const abs = path.join(dir, entry.name);
92
+ if (wanted.has(entry.name) && fs.existsSync(path.join(abs, SKILL_FILE))) {
93
+ if (!isSource(abs)) found.set(entry.name, [...found.get(entry.name) ?? [], abs]);
94
+ continue;
95
+ }
96
+ if (depth < SKILL_SCAN_DEPTH) walk(abs, depth + 1);
97
+ }
98
+ };
99
+ walk(root, 1);
100
+ for (const list of found.values()) list.sort();
101
+ return found;
102
+ }
103
+ function writeSkill(root, skillsDir, name, dest, verb) {
104
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
105
+ fs.cpSync(path.join(skillsDir, name), dest, { recursive: true, force: true });
106
+ log.ok(`${verb} skill ${displayPath(root, dest)}/`);
107
+ }
108
+ function printSkillList(root, available, placed) {
109
+ const width = Math.max(...available.map((n) => n.length));
110
+ log.info("Bundled skills:");
111
+ for (const name of available) {
112
+ const where = placed.get(name);
113
+ const status = where?.length ? where.map((p) => displayPath(root, p) + "/").join(", ") : "not placed";
114
+ log.info(` ${name.padEnd(width)} ${status}`);
115
+ }
116
+ const missing = available.filter((n) => !placed.get(n)?.length);
117
+ if (missing.length) {
118
+ log.info("");
119
+ log.info("Place the missing ones with: vantage add skill --all [--dir <path>]");
120
+ }
121
+ return 0;
122
+ }
123
+ function addSkill(root, name, all, force, dir) {
124
+ const skillsDir = resolvePackageDir(root, "skills");
125
+ if (!skillsDir) {
126
+ log.error("Could not resolve the Vantage skills directory.");
127
+ return 1;
128
+ }
129
+ const available = listBundledSkills(skillsDir);
130
+ if (available.length === 0) {
131
+ log.error("No skills are bundled with this version of Vantage.");
132
+ return 1;
133
+ }
134
+ const placed = findPlacedSkills(root, available, skillsDir);
135
+ if (!all && !name) return printSkillList(root, available, placed);
136
+ const destDir = path.resolve(root, dir ?? ".");
137
+ const targets = all ? available : [name];
138
+ let failed = 0;
139
+ for (const target of targets) {
140
+ if (!available.includes(target)) {
141
+ log.error(`Unknown skill "${target}". Available: ${available.join(", ")}`);
142
+ failed++;
143
+ continue;
144
+ }
145
+ const existing = placed.get(target) ?? [];
146
+ if (existing.length > 0 && !force) {
147
+ const where = existing.map((p) => displayPath(root, p) + "/").join(", ");
148
+ log.info(`Skill ${target} is already placed at ${where} \u2014 skipped (--force to refresh).`);
149
+ continue;
150
+ }
151
+ const inDestDir = existing.filter((p) => path.dirname(p) === destDir);
152
+ const refresh = dir === void 0 ? existing : inDestDir;
153
+ if (refresh.length > 0) {
154
+ for (const dest of refresh) writeSkill(root, skillsDir, target, dest, "Updated");
155
+ continue;
156
+ }
157
+ if (existing.length > 0) {
158
+ const where = existing.map((p) => displayPath(root, p) + "/").join(", ");
159
+ log.warn(`Skill ${target} is also placed at ${where} \u2014 left untouched.`);
160
+ }
161
+ writeSkill(root, skillsDir, target, path.join(destDir, target), "Added");
162
+ }
163
+ return failed === 0 ? 0 : 1;
164
+ }
165
+ var AGENTS_FILE = "AGENTS.md";
166
+ function bundledAgentsPath(root) {
167
+ const dir = resolvePackageDir(root, "templates");
168
+ if (!dir) return null;
169
+ const src = path.join(dir, AGENTS_FILE);
170
+ return fs.existsSync(src) ? src : null;
171
+ }
172
+ function addAgents(root, force) {
173
+ const src = bundledAgentsPath(root);
174
+ if (!src) {
175
+ log.error("AGENTS.md is not bundled with this version of Vantage.");
176
+ return 1;
177
+ }
178
+ const dest = path.join(root, AGENTS_FILE);
179
+ if (fs.existsSync(dest) && !force) {
180
+ log.error(`${AGENTS_FILE} already exists. Use --force to overwrite.`);
181
+ return 1;
182
+ }
183
+ fs.copyFileSync(src, dest);
184
+ log.ok(`Added ${path.relative(root, dest) || AGENTS_FILE}`);
185
+ return 0;
186
+ }
187
+ function syncAgentsFile(root) {
188
+ const dest = path.join(root, AGENTS_FILE);
189
+ if (!fs.existsSync(dest)) return "absent";
190
+ const src = bundledAgentsPath(root);
191
+ if (!src) return "unchanged";
192
+ const next = fs.readFileSync(src, "utf8");
193
+ if (fs.readFileSync(dest, "utf8") === next) return "unchanged";
194
+ fs.writeFileSync(dest, next);
195
+ return "updated";
196
+ }
197
+ function copyFromRegistry(root, kind, name, force) {
198
+ const registry = resolveRegistryDir(root);
199
+ if (!registry) {
200
+ log.error("Could not resolve the Vantage registry.");
201
+ return 1;
202
+ }
203
+ const sub = kind === "ui" ? "ui" : "blocks";
204
+ const src = path.join(registry, sub, `${name}.tsx`);
205
+ if (!fs.existsSync(src)) {
206
+ const available = fs.existsSync(path.join(registry, sub)) ? fs.readdirSync(path.join(registry, sub)).map((f) => f.replace(/\.tsx$/, "")) : [];
207
+ log.error(`Unknown ${kind} "${name}". Available: ${available.join(", ") || "(none)"}`);
208
+ return 1;
209
+ }
210
+ const destDir = path.join(resolvePageRoot(root).abs, "components", kind === "ui" ? "ui" : "blocks");
211
+ const dest = path.join(destDir, `${name}.tsx`);
212
+ if (fs.existsSync(dest) && !force) {
213
+ log.error(`${path.relative(root, dest)} already exists. Use --force to overwrite.`);
214
+ return 1;
215
+ }
216
+ fs.mkdirSync(destDir, { recursive: true });
217
+ fs.copyFileSync(src, dest);
218
+ log.ok(`Added ${path.relative(root, dest)}`);
219
+ return 0;
220
+ }
221
+ async function add(root, args) {
222
+ const kind = args.positionals[1];
223
+ const name = args.positionals[2];
224
+ const force = Boolean(args.flags.force);
225
+ const all = Boolean(args.flags.all);
226
+ if (kind === "skill") {
227
+ const dir = typeof args.flags.dir === "string" ? args.flags.dir : void 0;
228
+ return addSkill(root, name, all, force, dir);
229
+ }
230
+ if (kind === "agents") return addAgents(root, force);
231
+ if (!kind || !name) {
232
+ log.error("Usage: vantage add <page|api|ui|block|skill|agents> <name>");
233
+ return 1;
234
+ }
235
+ if (kind === "page") {
236
+ const pageRoot = resolvePageRoot(root).abs;
237
+ const file = path.join(pageRoot, name.endsWith(".tsx") ? name : `${name}.tsx`);
238
+ if (fs.existsSync(file) && !force) {
239
+ log.error(`${path.relative(root, file)} already exists. Use --force to overwrite.`);
240
+ return 1;
241
+ }
242
+ fs.mkdirSync(path.dirname(file), { recursive: true });
243
+ fs.writeFileSync(file, pageTemplate(name));
244
+ log.ok(`Added page ${path.relative(root, file)}`);
245
+ return 0;
246
+ }
247
+ if (kind === "api") {
248
+ const rel = name.startsWith("server/api/") ? name : path.join("server", "api", name);
249
+ const file = path.join(root, rel.endsWith(".ts") ? rel : `${rel}.ts`);
250
+ if (fs.existsSync(file) && !force) {
251
+ log.error(`${path.relative(root, file)} already exists. Use --force to overwrite.`);
252
+ return 1;
253
+ }
254
+ fs.mkdirSync(path.dirname(file), { recursive: true });
255
+ fs.writeFileSync(file, apiTemplate());
256
+ log.ok(`Added API ${path.relative(root, file)}`);
257
+ return 0;
258
+ }
259
+ if (kind === "ui") return copyFromRegistry(root, "ui", name, force);
260
+ if (kind === "block") return copyFromRegistry(root, "block", name, force);
261
+ log.error(`Unknown add target "${kind}". Use one of: page, api, ui, block, skill, agents.`);
262
+ return 1;
263
+ }
264
+
265
+ export { add, syncAgentsFile };
266
+ //# sourceMappingURL=chunk-ZIM745WE.js.map
267
+ //# sourceMappingURL=chunk-ZIM745WE.js.map