@squadbase/vantage 0.2.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/add-DWNDA57L.js +6 -0
- package/dist/add-DWNDA57L.js.map +1 -0
- package/dist/build-QP5BL3K7.js +108 -0
- package/dist/build-QP5BL3K7.js.map +1 -0
- package/dist/check-QPFERQLO.js +38 -0
- package/dist/check-QPFERQLO.js.map +1 -0
- package/dist/chunk-2KRCGXBY.js +56 -0
- package/dist/chunk-2KRCGXBY.js.map +1 -0
- package/dist/chunk-BAM33YZ6.js +202 -0
- package/dist/chunk-BAM33YZ6.js.map +1 -0
- package/dist/chunk-C4MQRWXS.js +81 -0
- package/dist/chunk-C4MQRWXS.js.map +1 -0
- package/dist/chunk-D4Y5RWJA.js +189 -0
- package/dist/chunk-D4Y5RWJA.js.map +1 -0
- package/dist/chunk-OFFJ3OL5.js +121 -0
- package/dist/chunk-OFFJ3OL5.js.map +1 -0
- package/dist/chunk-PSEYFYAP.js +276 -0
- package/dist/chunk-PSEYFYAP.js.map +1 -0
- package/dist/chunk-R2YYVCGS.js +345 -0
- package/dist/chunk-R2YYVCGS.js.map +1 -0
- package/dist/chunk-RA6Z3OX3.js +199 -0
- package/dist/chunk-RA6Z3OX3.js.map +1 -0
- package/dist/chunk-UTEKU3LG.js +267 -0
- package/dist/chunk-UTEKU3LG.js.map +1 -0
- package/dist/chunk-VXAV2435.js +142 -0
- package/dist/chunk-VXAV2435.js.map +1 -0
- package/dist/cli.js +24 -1604
- package/dist/cli.js.map +1 -1
- package/dist/dev-NX3PMYCT.js +55 -0
- package/dist/dev-NX3PMYCT.js.map +1 -0
- package/dist/docs-M5ZUI25V.js +114 -0
- package/dist/docs-M5ZUI25V.js.map +1 -0
- package/dist/doctor-N6JMEWKT.js +58 -0
- package/dist/doctor-N6JMEWKT.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/preview-CLALOEFE.js +49 -0
- package/dist/preview-CLALOEFE.js.map +1 -0
- package/dist/routes-YI25MKPF.js +119 -0
- package/dist/routes-YI25MKPF.js.map +1 -0
- package/dist/search-5TYAIQ7C.js +325 -0
- package/dist/search-5TYAIQ7C.js.map +1 -0
- package/dist/server/node.d.ts +1 -12
- package/dist/types-De3mo_hv.d.ts +59 -0
- package/dist/upgrade-3P5MBGE6.js +29 -0
- package/dist/upgrade-3P5MBGE6.js.map +1 -0
- package/dist/vite/index.d.ts +13 -0
- package/dist/vite/index.js +5 -1
- package/docs/en/changelog.md +82 -0
- package/docs/en/cli-reference.md +34 -4
- package/docs/en/components.md +2 -1
- package/docs/en/getting-started.md +6 -3
- package/docs/en/routing.md +27 -1
- package/docs/en/ui-and-theming.md +4 -2
- package/docs/ja/changelog.md +74 -0
- package/docs/ja/cli-reference.md +34 -4
- package/docs/ja/components.md +3 -2
- package/docs/ja/getting-started.md +6 -3
- package/docs/ja/routing.md +26 -1
- package/docs/ja/ui-and-theming.md +4 -2
- package/package.json +7 -4
- package/skills/vantage-add-feature/SKILL.md +14 -5
- package/skills/vantage-app/SKILL.md +9 -5
- package/templates/AGENTS.md +50 -6
- package/dist/chunk-3QKPNWKJ.js +0 -762
- package/dist/chunk-3QKPNWKJ.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,267 @@
|
|
|
1
|
+
import { resolvePageRoot } from './chunk-D4Y5RWJA.js';
|
|
2
|
+
import { log } from './chunk-OFFJ3OL5.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-UTEKU3LG.js.map
|
|
267
|
+
//# sourceMappingURL=chunk-UTEKU3LG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/add.ts"],"names":["require"],"mappings":";;;;;;;AAMA,IAAM,GAAA,GAAM,oBAAA;AAEZ,SAAS,aAAa,OAAA,EAAyB;AAC7C,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,CAAQ,WAAA,EAAa,EAAE,CAAA,CAAE,OAAA,CAAQ,WAAW,EAAE,CAAA;AACtE,EAAA,MAAM,QAAQ,OAAA,CAAQ,KAAA,CAAM,eAAe,CAAA,CAAE,OAAO,OAAO,CAAA;AAC3D,EAAA,MAAM,SAAS,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,KAAgB,CAAA,CAAE,KAAA,CAAM,CAAC,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AAC/E,EAAA,OAAO,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA,GAAI,MAAA,GAAS,MAAA;AAC7C;AAEA,SAAS,aAAa,IAAA,EAAsB;AAC1C,EAAA,MAAM,OAAO,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,CAAE,KAAI,IAAK,IAAA;AACtC,EAAA,MAAM,YAAY,IAAA,KAAS,OAAA,GAAU,YAAA,CAAa,IAAA,CAAK,MAAM,GAAG,CAAA,CAAE,KAAA,CAAM,EAAE,EAAE,CAAC,CAAA,IAAK,MAAM,CAAA,GAAI,aAAa,IAAI,CAAA;AAC7G,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAA,EAAS,CAAC,CAAA,KAAM,CAAA,CAAE,WAAA,EAAa,CAAA;AAC7E,EAAA,OAAO,+BAA+B,GAAG,CAAA;;AAAA,wCAAA,EAED,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;;AAAA,wBAAA,EAErC,SAAS,CAAA;AAAA;AAAA;AAAA,6CAAA,EAGY,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAKpD;AAEA,SAAS,WAAA,GAAsB;AAC7B,EAAA,OAAO,oCAAoC,GAAG,CAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAMhD;AAEA,SAAS,iBAAA,CAAkB,MAAc,GAAA,EAA4B;AACnE,EAAA,IAAI;AACF,IAAA,MAAMA,WAAU,aAAA,CAAc,IAAA,CAAK,IAAA,CAAK,IAAA,EAAM,SAAS,CAAC,CAAA;AACxD,IAAA,MAAM,OAAA,GAAUA,QAAAA,CAAQ,OAAA,CAAQ,CAAA,EAAG,GAAG,CAAA,aAAA,CAAe,CAAA;AACrD,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,OAAO,GAAG,GAAG,CAAA;AAAA,EAC7C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,SAAS,mBAAmB,IAAA,EAA6B;AACvD,EAAA,OAAO,iBAAA,CAAkB,MAAM,UAAU,CAAA;AAC3C;AAEA,IAAM,UAAA,GAAa,UAAA;AAGnB,IAAM,eAAA,uBAAsB,GAAA,CAAI;AAAA,EAC9B,cAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAC,CAAA;AAGD,IAAM,gBAAA,GAAmB,CAAA;AAGzB,SAAS,kBAAkB,SAAA,EAA6B;AACtD,EAAA,IAAI;AACF,IAAA,OAAO,EAAA,CACJ,WAAA,CAAY,SAAA,EAAW,EAAE,aAAA,EAAe,IAAA,EAAM,CAAA,CAC9C,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAY,IAAK,EAAA,CAAG,UAAA,CAAW,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,CAAA,CAAE,IAAA,EAAM,UAAU,CAAC,CAAC,CAAA,CACxF,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,EACjB,IAAA,EAAK;AAAA,EACV,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAGA,SAAS,WAAA,CAAY,MAAc,MAAA,EAAwB;AACzD,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,QAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AACtC,EAAA,OAAO,CAAC,GAAA,GAAM,GAAA,GAAM,IAAI,UAAA,CAAW,IAAI,IAAI,MAAA,GAAS,GAAA;AACtD;AAUA,SAAS,gBAAA,CACP,IAAA,EACA,KAAA,EACA,SAAA,EACuB;AACvB,EAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,KAAK,CAAA;AAC5B,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAsB;AAGxC,EAAA,MAAM,QAAA,GAAW,CAAC,CAAA,KAAc,CAAC,IAAA,CAAK,SAAS,SAAA,EAAW,CAAC,CAAA,CAAE,UAAA,CAAW,IAAI,CAAA;AAC5E,EAAA,MAAM,IAAA,GAAO,CAAC,GAAA,EAAa,KAAA,KAAwB;AACjD,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,OAAA,GAAU,GAAG,WAAA,CAAY,GAAA,EAAK,EAAE,aAAA,EAAe,MAAM,CAAA;AAAA,IACvD,CAAA,CAAA,MAAQ;AACN,MAAA;AAAA,IACF;AACA,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,IAAI,CAAC,MAAM,WAAA,EAAY,IAAK,gBAAgB,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,EAAG;AAC7D,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,MAAM,IAAI,CAAA;AACrC,MAAA,IAAI,MAAA,CAAO,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,IAAK,EAAA,CAAG,UAAA,CAAW,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,UAAU,CAAC,CAAA,EAAG;AACvE,QAAA,IAAI,CAAC,QAAA,CAAS,GAAG,GAAG,KAAA,CAAM,GAAA,CAAI,MAAM,IAAA,EAAM,CAAC,GAAI,KAAA,CAAM,IAAI,KAAA,CAAM,IAAI,KAAK,EAAC,EAAI,GAAG,CAAC,CAAA;AACjF,QAAA;AAAA,MACF;AACA,MAAA,IAAI,KAAA,GAAQ,gBAAA,EAAkB,IAAA,CAAK,GAAA,EAAK,QAAQ,CAAC,CAAA;AAAA,IACnD;AAAA,EACF,CAAA;AACA,EAAA,IAAA,CAAK,MAAM,CAAC,CAAA;AACZ,EAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,CAAM,MAAA,EAAO,OAAQ,IAAA,EAAK;AAC7C,EAAA,OAAO,KAAA;AACT;AAGA,SAAS,UAAA,CAAW,IAAA,EAAc,SAAA,EAAmB,IAAA,EAAc,MAAc,IAAA,EAAoB;AACnG,EAAA,EAAA,CAAG,SAAA,CAAU,KAAK,OAAA,CAAQ,IAAI,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACpD,EAAA,EAAA,CAAG,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,IAAI,CAAA,EAAG,IAAA,EAAM,EAAE,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,CAAA;AAC5E,EAAA,GAAA,CAAI,EAAA,CAAG,GAAG,IAAI,CAAA,OAAA,EAAU,YAAY,IAAA,EAAM,IAAI,CAAC,CAAA,CAAA,CAAG,CAAA;AACpD;AAGA,SAAS,cAAA,CAAe,IAAA,EAAc,SAAA,EAAqB,MAAA,EAAuC;AAChG,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,GAAG,SAAA,CAAU,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,MAAM,CAAC,CAAA;AACxD,EAAA,GAAA,CAAI,KAAK,iBAAiB,CAAA;AAC1B,EAAA,KAAA,MAAW,QAAQ,SAAA,EAAW;AAC5B,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA;AAC7B,IAAA,MAAM,MAAA,GAAS,KAAA,EAAO,MAAA,GAClB,KAAA,CAAM,IAAI,CAAC,CAAA,KAAM,WAAA,CAAY,IAAA,EAAM,CAAC,CAAA,GAAI,GAAG,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,GACtD,YAAA;AACJ,IAAA,GAAA,CAAI,IAAA,CAAK,KAAK,IAAA,CAAK,MAAA,CAAO,KAAK,CAAC,CAAA,EAAA,EAAK,MAAM,CAAA,CAAE,CAAA;AAAA,EAC/C;AACA,EAAA,MAAM,OAAA,GAAU,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,EAAG,MAAM,CAAA;AAC9D,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,GAAA,CAAI,KAAK,EAAE,CAAA;AACX,IAAA,GAAA,CAAI,KAAK,qEAAqE,CAAA;AAAA,EAChF;AACA,EAAA,OAAO,CAAA;AACT;AAaA,SAAS,QAAA,CACP,IAAA,EACA,IAAA,EACA,GAAA,EACA,OACA,GAAA,EACQ;AACR,EAAA,MAAM,SAAA,GAAY,iBAAA,CAAkB,IAAA,EAAM,QAAQ,CAAA;AAClD,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,GAAA,CAAI,MAAM,iDAAiD,CAAA;AAC3D,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,MAAM,SAAA,GAAY,kBAAkB,SAAS,CAAA;AAC7C,EAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC1B,IAAA,GAAA,CAAI,MAAM,qDAAqD,CAAA;AAC/D,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,MAAM,MAAA,GAAS,gBAAA,CAAiB,IAAA,EAAM,SAAA,EAAW,SAAS,CAAA;AAC1D,EAAA,IAAI,CAAC,OAAO,CAAC,IAAA,SAAa,cAAA,CAAe,IAAA,EAAM,WAAW,MAAM,CAAA;AAEhE,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,OAAO,GAAG,CAAA;AAC7C,EAAA,MAAM,OAAA,GAAU,GAAA,GAAM,SAAA,GAAY,CAAC,IAAc,CAAA;AACjD,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,CAAC,SAAA,CAAU,QAAA,CAAS,MAAM,CAAA,EAAG;AAC/B,MAAA,GAAA,CAAI,KAAA,CAAM,kBAAkB,MAAM,CAAA,cAAA,EAAiB,UAAU,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AACzE,MAAA,MAAA,EAAA;AACA,MAAA;AAAA,IACF;AACA,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,GAAA,CAAI,MAAM,KAAK,EAAC;AACxC,IAAA,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,IAAK,CAAC,KAAA,EAAO;AACjC,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,KAAM,WAAA,CAAY,IAAA,EAAM,CAAC,CAAA,GAAI,GAAG,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACvE,MAAA,GAAA,CAAI,IAAA,CAAK,CAAA,MAAA,EAAS,MAAM,CAAA,sBAAA,EAAyB,KAAK,CAAA,qCAAA,CAAkC,CAAA;AACxF,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,SAAA,GAAY,SAAS,MAAA,CAAO,CAAC,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA,KAAM,OAAO,CAAA;AACpE,IAAA,MAAM,OAAA,GAAU,GAAA,KAAQ,MAAA,GAAY,QAAA,GAAW,SAAA;AAC/C,IAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,MAAA,KAAA,MAAW,QAAQ,OAAA,EAAS,UAAA,CAAW,MAAM,SAAA,EAAW,MAAA,EAAQ,MAAM,SAAS,CAAA;AAC/E,MAAA;AAAA,IACF;AACA,IAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACvB,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,KAAM,WAAA,CAAY,IAAA,EAAM,CAAC,CAAA,GAAI,GAAG,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACvE,MAAA,GAAA,CAAI,IAAA,CAAK,CAAA,MAAA,EAAS,MAAM,CAAA,mBAAA,EAAsB,KAAK,CAAA,uBAAA,CAAoB,CAAA;AAAA,IACzE;AACA,IAAA,UAAA,CAAW,IAAA,EAAM,WAAW,MAAA,EAAQ,IAAA,CAAK,KAAK,OAAA,EAAS,MAAM,GAAG,OAAO,CAAA;AAAA,EACzE;AACA,EAAA,OAAO,MAAA,KAAW,IAAI,CAAA,GAAI,CAAA;AAC5B;AAEA,IAAM,WAAA,GAAc,WAAA;AAGpB,SAAS,kBAAkB,IAAA,EAA6B;AACtD,EAAA,MAAM,GAAA,GAAM,iBAAA,CAAkB,IAAA,EAAM,WAAW,CAAA;AAC/C,EAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AACjB,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,GAAA,EAAK,WAAW,CAAA;AACtC,EAAA,OAAO,EAAA,CAAG,UAAA,CAAW,GAAG,CAAA,GAAI,GAAA,GAAM,IAAA;AACpC;AAGA,SAAS,SAAA,CAAU,MAAc,KAAA,EAAwB;AACvD,EAAA,MAAM,GAAA,GAAM,kBAAkB,IAAI,CAAA;AAClC,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,GAAA,CAAI,MAAM,wDAAwD,CAAA;AAClE,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,IAAA,EAAM,WAAW,CAAA;AACxC,EAAA,IAAI,EAAA,CAAG,UAAA,CAAW,IAAI,CAAA,IAAK,CAAC,KAAA,EAAO;AACjC,IAAA,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,WAAW,CAAA,0CAAA,CAA4C,CAAA;AACpE,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,EAAA,CAAG,YAAA,CAAa,KAAK,IAAI,CAAA;AACzB,EAAA,GAAA,CAAI,EAAA,CAAG,SAAS,IAAA,CAAK,QAAA,CAAS,MAAM,IAAI,CAAA,IAAK,WAAW,CAAA,CAAE,CAAA;AAC1D,EAAA,OAAO,CAAA;AACT;AAQO,SAAS,eAAe,IAAA,EAAkD;AAC/E,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,IAAA,EAAM,WAAW,CAAA;AACxC,EAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,IAAI,GAAG,OAAO,QAAA;AACjC,EAAA,MAAM,GAAA,GAAM,kBAAkB,IAAI,CAAA;AAClC,EAAA,IAAI,CAAC,KAAK,OAAO,WAAA;AACjB,EAAA,MAAM,IAAA,GAAO,EAAA,CAAG,YAAA,CAAa,GAAA,EAAK,MAAM,CAAA;AACxC,EAAA,IAAI,GAAG,YAAA,CAAa,IAAA,EAAM,MAAM,CAAA,KAAM,MAAM,OAAO,WAAA;AACnD,EAAA,EAAA,CAAG,aAAA,CAAc,MAAM,IAAI,CAAA;AAC3B,EAAA,OAAO,SAAA;AACT;AAEA,SAAS,gBAAA,CAAiB,IAAA,EAAc,IAAA,EAAsB,IAAA,EAAc,KAAA,EAAwB;AAClG,EAAA,MAAM,QAAA,GAAW,mBAAmB,IAAI,CAAA;AACxC,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,GAAA,CAAI,MAAM,yCAAyC,CAAA;AACnD,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,MAAM,GAAA,GAAM,IAAA,KAAS,IAAA,GAAO,IAAA,GAAO,QAAA;AACnC,EAAA,MAAM,MAAM,IAAA,CAAK,IAAA,CAAK,UAAU,GAAA,EAAK,CAAA,EAAG,IAAI,CAAA,IAAA,CAAM,CAAA;AAClD,EAAA,IAAI,CAAC,EAAA,CAAG,UAAA,CAAW,GAAG,CAAA,EAAG;AACvB,IAAA,MAAM,SAAA,GAAY,EAAA,CAAG,UAAA,CAAW,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,GAAG,CAAC,CAAA,GACpD,EAAA,CAAG,WAAA,CAAY,IAAA,CAAK,IAAA,CAAK,UAAU,GAAG,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAC,CAAA,GAC3E,EAAC;AACL,IAAA,GAAA,CAAI,KAAA,CAAM,CAAA,QAAA,EAAW,IAAI,CAAA,EAAA,EAAK,IAAI,CAAA,cAAA,EAAiB,SAAA,CAAU,IAAA,CAAK,IAAI,CAAA,IAAK,QAAQ,CAAA,CAAE,CAAA;AACrF,IAAA,OAAO,CAAA;AAAA,EACT;AAGA,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,eAAA,CAAgB,IAAI,CAAA,CAAE,GAAA,EAAK,YAAA,EAAc,IAAA,KAAS,IAAA,GAAO,IAAA,GAAO,QAAQ,CAAA;AAClG,EAAA,MAAM,OAAO,IAAA,CAAK,IAAA,CAAK,OAAA,EAAS,CAAA,EAAG,IAAI,CAAA,IAAA,CAAM,CAAA;AAC7C,EAAA,IAAI,EAAA,CAAG,UAAA,CAAW,IAAI,CAAA,IAAK,CAAC,KAAA,EAAO;AACjC,IAAA,GAAA,CAAI,MAAM,CAAA,EAAG,IAAA,CAAK,SAAS,IAAA,EAAM,IAAI,CAAC,CAAA,0CAAA,CAA4C,CAAA;AAClF,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,EAAA,CAAG,SAAA,CAAU,OAAA,EAAS,EAAE,SAAA,EAAW,MAAM,CAAA;AACzC,EAAA,EAAA,CAAG,YAAA,CAAa,KAAK,IAAI,CAAA;AACzB,EAAA,GAAA,CAAI,GAAG,CAAA,MAAA,EAAS,IAAA,CAAK,SAAS,IAAA,EAAM,IAAI,CAAC,CAAA,CAAE,CAAA;AAC3C,EAAA,OAAO,CAAA;AACT;AAGA,eAAsB,GAAA,CAAI,MAAc,IAAA,EAAmC;AACzE,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,WAAA,CAAY,CAAC,CAAA;AAC/B,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,WAAA,CAAY,CAAC,CAAA;AAC/B,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AACtC,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAIlC,EAAA,IAAI,SAAS,OAAA,EAAS;AACpB,IAAA,MAAM,GAAA,GAAM,OAAO,IAAA,CAAK,KAAA,CAAM,QAAQ,QAAA,GAAW,IAAA,CAAK,MAAM,GAAA,GAAM,MAAA;AAClE,IAAA,OAAO,QAAA,CAAS,IAAA,EAAM,IAAA,EAAM,GAAA,EAAK,OAAO,GAAG,CAAA;AAAA,EAC7C;AACA,EAAA,IAAI,IAAA,KAAS,QAAA,EAAU,OAAO,SAAA,CAAU,MAAM,KAAK,CAAA;AAEnD,EAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,IAAA,EAAM;AAClB,IAAA,GAAA,CAAI,MAAM,4DAA4D,CAAA;AACtE,IAAA,OAAO,CAAA;AAAA,EACT;AAEA,EAAA,IAAI,SAAS,MAAA,EAAQ;AAGnB,IAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,IAAI,CAAA,CAAE,GAAA;AACvC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,GAAI,IAAA,GAAO,CAAA,EAAG,IAAI,CAAA,IAAA,CAAM,CAAA;AAC7E,IAAA,IAAI,EAAA,CAAG,UAAA,CAAW,IAAI,CAAA,IAAK,CAAC,KAAA,EAAO;AACjC,MAAA,GAAA,CAAI,MAAM,CAAA,EAAG,IAAA,CAAK,SAAS,IAAA,EAAM,IAAI,CAAC,CAAA,0CAAA,CAA4C,CAAA;AAClF,MAAA,OAAO,CAAA;AAAA,IACT;AACA,IAAA,EAAA,CAAG,SAAA,CAAU,KAAK,OAAA,CAAQ,IAAI,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACpD,IAAA,EAAA,CAAG,aAAA,CAAc,IAAA,EAAM,YAAA,CAAa,IAAI,CAAC,CAAA;AACzC,IAAA,GAAA,CAAI,GAAG,CAAA,WAAA,EAAc,IAAA,CAAK,SAAS,IAAA,EAAM,IAAI,CAAC,CAAA,CAAE,CAAA;AAChD,IAAA,OAAO,CAAA;AAAA,EACT;AAEA,EAAA,IAAI,SAAS,KAAA,EAAO;AAClB,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,UAAA,CAAW,aAAa,CAAA,GAAI,OAAO,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,KAAA,EAAO,IAAI,CAAA;AACnF,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,IAAA,EAAM,GAAA,CAAI,QAAA,CAAS,KAAK,CAAA,GAAI,GAAA,GAAM,CAAA,EAAG,GAAG,CAAA,GAAA,CAAK,CAAA;AACpE,IAAA,IAAI,EAAA,CAAG,UAAA,CAAW,IAAI,CAAA,IAAK,CAAC,KAAA,EAAO;AACjC,MAAA,GAAA,CAAI,MAAM,CAAA,EAAG,IAAA,CAAK,SAAS,IAAA,EAAM,IAAI,CAAC,CAAA,0CAAA,CAA4C,CAAA;AAClF,MAAA,OAAO,CAAA;AAAA,IACT;AACA,IAAA,EAAA,CAAG,SAAA,CAAU,KAAK,OAAA,CAAQ,IAAI,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACpD,IAAA,EAAA,CAAG,aAAA,CAAc,IAAA,EAAM,WAAA,EAAa,CAAA;AACpC,IAAA,GAAA,CAAI,GAAG,CAAA,UAAA,EAAa,IAAA,CAAK,SAAS,IAAA,EAAM,IAAI,CAAC,CAAA,CAAE,CAAA;AAC/C,IAAA,OAAO,CAAA;AAAA,EACT;AAEA,EAAA,IAAI,SAAS,IAAA,EAAM,OAAO,iBAAiB,IAAA,EAAM,IAAA,EAAM,MAAM,KAAK,CAAA;AAClE,EAAA,IAAI,SAAS,OAAA,EAAS,OAAO,iBAAiB,IAAA,EAAM,OAAA,EAAS,MAAM,KAAK,CAAA;AAExE,EAAA,GAAA,CAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,IAAI,CAAA,mDAAA,CAAqD,CAAA;AAC1F,EAAA,OAAO,CAAA;AACT","file":"chunk-UTEKU3LG.js","sourcesContent":["import fs from \"node:fs\"\nimport path from \"node:path\"\nimport { createRequire } from \"node:module\"\nimport { resolvePageRoot } from \"../core/scan\"\nimport { log, type ParsedArgs } from \"./util\"\n\nconst PKG = \"@squadbase/vantage\"\n\nfunction toPascalCase(segment: string): string {\n const cleaned = segment.replace(/\\[|\\]|\\./g, \"\").replace(/\\.\\.\\./g, \"\")\n const words = cleaned.split(/[^a-zA-Z0-9]+/).filter(Boolean)\n const pascal = words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(\"\")\n return /^[A-Za-z]/.test(pascal) ? pascal : \"Page\"\n}\n\nfunction pageTemplate(name: string): string {\n const last = name.split(\"/\").pop() ?? name\n const component = last === \"index\" ? toPascalCase(name.split(\"/\").slice(-2)[0] ?? \"Home\") : toPascalCase(last)\n const title = last.replace(/-/g, \" \").replace(/\\b\\w/g, (c) => c.toUpperCase())\n return `import { definePage } from \"${PKG}\"\n\nexport const page = definePage({ title: ${JSON.stringify(title)} })\n\nexport default function ${component}() {\n return (\n <main className=\"p-6\">\n <h1 className=\"text-2xl font-semibold\">${title}</h1>\n </main>\n )\n}\n`\n}\n\nfunction apiTemplate(): string {\n return `import type { ApiContext } from \"${PKG}/server\"\n\nexport async function GET({ request, params }: ApiContext) {\n return Response.json({ ok: true, params })\n}\n`\n}\n\nfunction resolvePackageDir(root: string, sub: string): string | null {\n try {\n const require = createRequire(path.join(root, \"noop.js\"))\n const pkgJson = require.resolve(`${PKG}/package.json`)\n return path.join(path.dirname(pkgJson), sub)\n } catch {\n return null\n }\n}\n\nfunction resolveRegistryDir(root: string): string | null {\n return resolvePackageDir(root, \"registry\")\n}\n\nconst SKILL_FILE = \"SKILL.md\"\n\n/** Directories a placed skill never lives in — skipped while scanning. */\nconst SKILL_SCAN_SKIP = new Set([\n \"node_modules\",\n \".git\",\n \".vantage\",\n \"dist\",\n \"build\",\n \"out\",\n \"coverage\",\n \".next\",\n \".turbo\",\n \".cache\",\n \".vercel\",\n])\n\n/** How deep below the root the scan goes (`.claude/skills/<name>` is depth 3). */\nconst SKILL_SCAN_DEPTH = 4\n\n/** List the skill directories bundled with the installed framework. */\nfunction listBundledSkills(skillsDir: string): string[] {\n try {\n return fs\n .readdirSync(skillsDir, { withFileTypes: true })\n .filter((e) => e.isDirectory() && fs.existsSync(path.join(skillsDir, e.name, SKILL_FILE)))\n .map((e) => e.name)\n .sort()\n } catch {\n return []\n }\n}\n\n/** Paths outside the project read better absolute than as a pile of `../`. */\nfunction displayPath(root: string, target: string): string {\n const rel = path.relative(root, target)\n return !rel ? \".\" : rel.startsWith(\"..\") ? target : rel\n}\n\n/**\n * Find where the bundled skills already live in this project.\n *\n * Placement is a convention, not a fixed path: apps keep them under the root,\n * under `.claude/skills/`, under `.squadbase/skills/`, … so `add skill` looks\n * for the skill *directories* rather than guessing one destination and adding a\n * second copy next to the one that is already there.\n */\nfunction findPlacedSkills(\n root: string,\n names: readonly string[],\n skillsDir: string,\n): Map<string, string[]> {\n const wanted = new Set(names)\n const found = new Map<string, string[]>()\n // A workspace that links the framework by path (not through node_modules)\n // would otherwise report the framework's own `skills/` as a placement.\n const isSource = (p: string) => !path.relative(skillsDir, p).startsWith(\"..\")\n const walk = (dir: string, depth: number): 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 if (!entry.isDirectory() || SKILL_SCAN_SKIP.has(entry.name)) continue\n const abs = path.join(dir, entry.name)\n if (wanted.has(entry.name) && fs.existsSync(path.join(abs, SKILL_FILE))) {\n if (!isSource(abs)) found.set(entry.name, [...(found.get(entry.name) ?? []), abs])\n continue // skills never nest inside one another\n }\n if (depth < SKILL_SCAN_DEPTH) walk(abs, depth + 1)\n }\n }\n walk(root, 1)\n for (const list of found.values()) list.sort()\n return found\n}\n\n/** Copy one bundled skill directory to `dest`, creating parents as needed. */\nfunction writeSkill(root: string, skillsDir: string, name: string, dest: string, verb: string): void {\n fs.mkdirSync(path.dirname(dest), { recursive: true })\n fs.cpSync(path.join(skillsDir, name), dest, { recursive: true, force: true })\n log.ok(`${verb} skill ${displayPath(root, dest)}/`)\n}\n\n/** `vantage add skill` with no name — the bundled list plus where each one sits. */\nfunction printSkillList(root: string, available: string[], placed: Map<string, string[]>): number {\n const width = Math.max(...available.map((n) => n.length))\n log.info(\"Bundled skills:\")\n for (const name of available) {\n const where = placed.get(name)\n const status = where?.length\n ? where.map((p) => displayPath(root, p) + \"/\").join(\", \")\n : \"not placed\"\n log.info(` ${name.padEnd(width)} ${status}`)\n }\n const missing = available.filter((n) => !placed.get(n)?.length)\n if (missing.length) {\n log.info(\"\")\n log.info(\"Place the missing ones with: vantage add skill --all [--dir <path>]\")\n }\n return 0\n}\n\n/**\n * `vantage add skill [<name>|--all] [--dir <path>]` — copy Claude Code skills\n * out of the package.\n *\n * The command scans the project first: a skill that is already placed anywhere\n * (root, `.claude/skills/`, `.squadbase/skills/`, …) is a no-op and its location\n * is reported, so re-running never produces a second copy. `--force` refreshes\n * the placements that were found, in place. Only when nothing is found does the\n * destination matter — the project root, or `--dir` when given (an explicit\n * `--dir` also wins over refreshing somewhere else).\n */\nfunction addSkill(\n root: string,\n name: string | undefined,\n all: boolean,\n force: boolean,\n dir: string | undefined,\n): number {\n const skillsDir = resolvePackageDir(root, \"skills\")\n if (!skillsDir) {\n log.error(\"Could not resolve the Vantage skills directory.\")\n return 1\n }\n const available = listBundledSkills(skillsDir)\n if (available.length === 0) {\n log.error(\"No skills are bundled with this version of Vantage.\")\n return 1\n }\n const placed = findPlacedSkills(root, available, skillsDir)\n if (!all && !name) return printSkillList(root, available, placed)\n\n const destDir = path.resolve(root, dir ?? \".\")\n const targets = all ? available : [name as string]\n let failed = 0\n for (const target of targets) {\n if (!available.includes(target)) {\n log.error(`Unknown skill \"${target}\". Available: ${available.join(\", \")}`)\n failed++\n continue\n }\n const existing = placed.get(target) ?? []\n if (existing.length > 0 && !force) {\n const where = existing.map((p) => displayPath(root, p) + \"/\").join(\", \")\n log.info(`Skill ${target} is already placed at ${where} — skipped (--force to refresh).`)\n continue\n }\n // `--dir` names a destination explicitly, so it wins over refreshing copies\n // that live somewhere else; without it, `--force` updates them where they are.\n const inDestDir = existing.filter((p) => path.dirname(p) === destDir)\n const refresh = dir === undefined ? existing : inDestDir\n if (refresh.length > 0) {\n for (const dest of refresh) writeSkill(root, skillsDir, target, dest, \"Updated\")\n continue\n }\n if (existing.length > 0) {\n const where = existing.map((p) => displayPath(root, p) + \"/\").join(\", \")\n log.warn(`Skill ${target} is also placed at ${where} — left untouched.`)\n }\n writeSkill(root, skillsDir, target, path.join(destDir, target), \"Added\")\n }\n return failed === 0 ? 0 : 1\n}\n\nconst AGENTS_FILE = \"AGENTS.md\"\n\n/** Path to the framework's canonical AGENTS.md, or null if unresolved/absent. */\nfunction bundledAgentsPath(root: string): string | null {\n const dir = resolvePackageDir(root, \"templates\")\n if (!dir) return null\n const src = path.join(dir, AGENTS_FILE)\n return fs.existsSync(src) ? src : null\n}\n\n/** `vantage add agents` — copy the app-author AGENTS.md map into the app root. */\nfunction addAgents(root: string, force: boolean): number {\n const src = bundledAgentsPath(root)\n if (!src) {\n log.error(\"AGENTS.md is not bundled with this version of Vantage.\")\n return 1\n }\n const dest = path.join(root, AGENTS_FILE)\n if (fs.existsSync(dest) && !force) {\n log.error(`${AGENTS_FILE} already exists. Use --force to overwrite.`)\n return 1\n }\n fs.copyFileSync(src, dest)\n log.ok(`Added ${path.relative(root, dest) || AGENTS_FILE}`)\n return 0\n}\n\n/**\n * Re-sync a managed AGENTS.md from the framework's canonical copy. Only touches\n * the app when AGENTS.md is already present (opt-in via `vantage add agents`),\n * and only rewrites when the content actually changed. Used by `vantage upgrade`\n * so a single source-of-truth update reflects into apps that adopted the guide.\n */\nexport function syncAgentsFile(root: string): \"updated\" | \"unchanged\" | \"absent\" {\n const dest = path.join(root, AGENTS_FILE)\n if (!fs.existsSync(dest)) return \"absent\"\n const src = bundledAgentsPath(root)\n if (!src) return \"unchanged\"\n const next = fs.readFileSync(src, \"utf8\")\n if (fs.readFileSync(dest, \"utf8\") === next) return \"unchanged\"\n fs.writeFileSync(dest, next)\n return \"updated\"\n}\n\nfunction copyFromRegistry(root: string, kind: \"ui\" | \"block\", name: string, force: boolean): number {\n const registry = resolveRegistryDir(root)\n if (!registry) {\n log.error(\"Could not resolve the Vantage registry.\")\n return 1\n }\n const sub = kind === \"ui\" ? \"ui\" : \"blocks\"\n const src = path.join(registry, sub, `${name}.tsx`)\n if (!fs.existsSync(src)) {\n const available = fs.existsSync(path.join(registry, sub))\n ? fs.readdirSync(path.join(registry, sub)).map((f) => f.replace(/\\.tsx$/, \"\"))\n : []\n log.error(`Unknown ${kind} \"${name}\". Available: ${available.join(\", \") || \"(none)\"}`)\n return 1\n }\n // Copies land next to the pages that import them (src/components/… when the\n // project has a src/ layout).\n const destDir = path.join(resolvePageRoot(root).abs, \"components\", kind === \"ui\" ? \"ui\" : \"blocks\")\n const dest = path.join(destDir, `${name}.tsx`)\n if (fs.existsSync(dest) && !force) {\n log.error(`${path.relative(root, dest)} already exists. Use --force to overwrite.`)\n return 1\n }\n fs.mkdirSync(destDir, { recursive: true })\n fs.copyFileSync(src, dest)\n log.ok(`Added ${path.relative(root, dest)}`)\n return 0\n}\n\n/** `vantage add <page|api|ui|block|skill> <name>` */\nexport async function add(root: string, args: ParsedArgs): Promise<number> {\n const kind = args.positionals[1]\n const name = args.positionals[2]\n const force = Boolean(args.flags.force)\n const all = Boolean(args.flags.all)\n\n // `skill` accepts `--all` in place of a name, and `agents` takes no name at\n // all; handle both before the name guard.\n if (kind === \"skill\") {\n const dir = typeof args.flags.dir === \"string\" ? args.flags.dir : undefined\n return addSkill(root, name, all, force, dir)\n }\n if (kind === \"agents\") return addAgents(root, force)\n\n if (!kind || !name) {\n log.error(\"Usage: vantage add <page|api|ui|block|skill|agents> <name>\")\n return 1\n }\n\n if (kind === \"page\") {\n // Pages are named by their route, so they go under the page root — src/\n // when the project has one, the project root otherwise.\n const pageRoot = resolvePageRoot(root).abs\n const file = path.join(pageRoot, name.endsWith(\".tsx\") ? name : `${name}.tsx`)\n if (fs.existsSync(file) && !force) {\n log.error(`${path.relative(root, file)} already exists. Use --force to overwrite.`)\n return 1\n }\n fs.mkdirSync(path.dirname(file), { recursive: true })\n fs.writeFileSync(file, pageTemplate(name))\n log.ok(`Added page ${path.relative(root, file)}`)\n return 0\n }\n\n if (kind === \"api\") {\n const rel = name.startsWith(\"server/api/\") ? name : path.join(\"server\", \"api\", name)\n const file = path.join(root, rel.endsWith(\".ts\") ? rel : `${rel}.ts`)\n if (fs.existsSync(file) && !force) {\n log.error(`${path.relative(root, file)} already exists. Use --force to overwrite.`)\n return 1\n }\n fs.mkdirSync(path.dirname(file), { recursive: true })\n fs.writeFileSync(file, apiTemplate())\n log.ok(`Added API ${path.relative(root, file)}`)\n return 0\n }\n\n if (kind === \"ui\") return copyFromRegistry(root, \"ui\", name, force)\n if (kind === \"block\") return copyFromRegistry(root, \"block\", name, force)\n\n log.error(`Unknown add target \"${kind}\". Use one of: page, api, ui, block, skill, agents.`)\n return 1\n}\n"]}
|