@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
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ You write `index.tsx`. Vantage owns routing, React, TanStack Query, Tailwind v4,
|
|
|
7
7
|
the UI kit, the dev server, the optional API server, and the build. There is no
|
|
8
8
|
config file.
|
|
9
9
|
|
|
10
|
-
> **Status: prototype (v0.
|
|
10
|
+
> **Status: prototype (v0.3.1).** APIs may still change between releases.
|
|
11
11
|
|
|
12
12
|
## Install
|
|
13
13
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"add-DWNDA57L.js"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { vantagePlugin } from './chunk-R2YYVCGS.js';
|
|
2
|
+
import { generateArtifacts } from './chunk-RA6Z3OX3.js';
|
|
3
|
+
import './chunk-46QI6GFC.js';
|
|
4
|
+
import { runDiagnostics } from './chunk-PSEYFYAP.js';
|
|
5
|
+
import './chunk-BAM33YZ6.js';
|
|
6
|
+
import './chunk-VXAV2435.js';
|
|
7
|
+
import { scanProject, timedAsync } from './chunk-D4Y5RWJA.js';
|
|
8
|
+
import { printDiagnostics, log, applyApiBaseUrlFlag } from './chunk-OFFJ3OL5.js';
|
|
9
|
+
import { VANTAGE_DIR, MANIFEST_SCHEMA_VERSION } from './chunk-C4MQRWXS.js';
|
|
10
|
+
import './chunk-B7LLBNLV.js';
|
|
11
|
+
import fs from 'fs';
|
|
12
|
+
import path from 'path';
|
|
13
|
+
import { loadEnv, build as build$1 } from 'vite';
|
|
14
|
+
|
|
15
|
+
// @squadbase/vantage — generated build. Do not edit.
|
|
16
|
+
var SERVER_ENTRY = `// AUTO-GENERATED by @squadbase/vantage.
|
|
17
|
+
import path from "node:path"
|
|
18
|
+
import { fileURLToPath } from "node:url"
|
|
19
|
+
import { startNodeServer } from "@squadbase/vantage/server/node"
|
|
20
|
+
import { apiRoutes } from "./server-routes.gen"
|
|
21
|
+
|
|
22
|
+
const clientDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../client")
|
|
23
|
+
startNodeServer({ apiRoutes, clientDir })
|
|
24
|
+
`;
|
|
25
|
+
async function build(root, args) {
|
|
26
|
+
const model = scanProject(root);
|
|
27
|
+
const errors = runDiagnostics(root, model).filter((d) => d.severity === "error");
|
|
28
|
+
if (errors.length) {
|
|
29
|
+
printDiagnostics(errors);
|
|
30
|
+
log.error("Fix the errors above before building.");
|
|
31
|
+
return 1;
|
|
32
|
+
}
|
|
33
|
+
const mode = "production";
|
|
34
|
+
applyApiBaseUrlFlag(args);
|
|
35
|
+
const env = { ...process.env, ...loadEnv(mode, root, "") };
|
|
36
|
+
const quiet = Boolean(args.flags.json);
|
|
37
|
+
generateArtifacts({ root, model });
|
|
38
|
+
if (!quiet) log.step(model.hasServer ? "Building client and server\u2026" : "Building client\u2026");
|
|
39
|
+
const clientBuild = timedAsync("build:client", async () => {
|
|
40
|
+
await build$1({
|
|
41
|
+
configFile: false,
|
|
42
|
+
root,
|
|
43
|
+
mode,
|
|
44
|
+
plugins: [vantagePlugin({ root, env, model, artifactsWritten: true })],
|
|
45
|
+
logLevel: quiet ? "silent" : args.flags.verbose ? "info" : "warn"
|
|
46
|
+
});
|
|
47
|
+
relocateClientHtml(root);
|
|
48
|
+
});
|
|
49
|
+
const serverBuild = model.hasServer ? timedAsync("build:server", () => buildServer(root)) : Promise.resolve();
|
|
50
|
+
await Promise.all([clientBuild, serverBuild]);
|
|
51
|
+
writeDeployManifest(root, model);
|
|
52
|
+
if (!quiet) log.ok(`Build complete \u2192 ${path.relative(process.cwd(), path.join(root, "dist")) || "dist"}/`);
|
|
53
|
+
if (args.flags.json) {
|
|
54
|
+
process.stdout.write(
|
|
55
|
+
JSON.stringify({
|
|
56
|
+
ok: true,
|
|
57
|
+
mode: model.hasServer ? "fullstack" : "spa",
|
|
58
|
+
output: "dist",
|
|
59
|
+
pages: model.pages.length,
|
|
60
|
+
apis: model.apis.length
|
|
61
|
+
}) + "\n"
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
function relocateClientHtml(root) {
|
|
67
|
+
const clientDir = path.join(root, "dist", "client");
|
|
68
|
+
const nested = path.join(clientDir, VANTAGE_DIR, "index.html");
|
|
69
|
+
const target = path.join(clientDir, "index.html");
|
|
70
|
+
if (fs.existsSync(nested)) {
|
|
71
|
+
fs.mkdirSync(clientDir, { recursive: true });
|
|
72
|
+
fs.renameSync(nested, target);
|
|
73
|
+
fs.rmSync(path.join(clientDir, VANTAGE_DIR), { recursive: true, force: true });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function buildServer(root) {
|
|
77
|
+
const { build: esbuildBuild } = await import('esbuild');
|
|
78
|
+
const vantageDir = path.join(root, VANTAGE_DIR);
|
|
79
|
+
const entry = path.join(vantageDir, "server-entry.ts");
|
|
80
|
+
fs.writeFileSync(entry, SERVER_ENTRY);
|
|
81
|
+
await esbuildBuild({
|
|
82
|
+
entryPoints: [entry],
|
|
83
|
+
outfile: path.join(root, "dist", "server", "index.mjs"),
|
|
84
|
+
bundle: true,
|
|
85
|
+
platform: "node",
|
|
86
|
+
format: "esm",
|
|
87
|
+
target: "node20",
|
|
88
|
+
logLevel: "warning",
|
|
89
|
+
banner: { js: "// @squadbase/vantage server bundle" }
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function writeDeployManifest(root, model) {
|
|
93
|
+
const dist = path.join(root, "dist");
|
|
94
|
+
fs.mkdirSync(dist, { recursive: true });
|
|
95
|
+
const manifest = {
|
|
96
|
+
schemaVersion: MANIFEST_SCHEMA_VERSION,
|
|
97
|
+
mode: model.hasServer ? "fullstack" : "spa",
|
|
98
|
+
client: "./client",
|
|
99
|
+
...model.hasServer ? { server: "./server/index.mjs" } : {},
|
|
100
|
+
spaFallback: "./client/index.html",
|
|
101
|
+
runtime: "node"
|
|
102
|
+
};
|
|
103
|
+
fs.writeFileSync(path.join(dist, "vantage-manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export { build };
|
|
107
|
+
//# sourceMappingURL=build-QP5BL3K7.js.map
|
|
108
|
+
//# sourceMappingURL=build-QP5BL3K7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/build.ts"],"names":["viteBuild"],"mappings":"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","file":"build-QP5BL3K7.js","sourcesContent":["import fs from \"node:fs\"\nimport path from \"node:path\"\nimport { build as viteBuild, loadEnv } from \"vite\"\nimport { MANIFEST_SCHEMA_VERSION, VANTAGE_DIR } from \"../core/constants\"\nimport { runDiagnostics } from \"../core/diagnostics\"\nimport { generateArtifacts } from \"../core/generate\"\nimport { timedAsync } from \"../core/profile\"\nimport { scanProject } from \"../core/scan\"\nimport type { RouteModel } from \"../core/types\"\nimport { vantagePlugin } from \"../vite/index\"\nimport { applyApiBaseUrlFlag, log, printDiagnostics, type ParsedArgs } from \"./util\"\n\nconst SERVER_ENTRY = `// AUTO-GENERATED by @squadbase/vantage.\nimport path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\nimport { startNodeServer } from \"@squadbase/vantage/server/node\"\nimport { apiRoutes } from \"./server-routes.gen\"\n\nconst clientDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), \"../client\")\nstartNodeServer({ apiRoutes, clientDir })\n`\n\n/** `vantage build` — build client and (optionally) server into dist/. */\nexport async function build(root: string, args: ParsedArgs): Promise<number> {\n const model = scanProject(root)\n const errors = runDiagnostics(root, model).filter((d) => d.severity === \"error\")\n if (errors.length) {\n printDiagnostics(errors)\n log.error(\"Fix the errors above before building.\")\n return 1\n }\n\n const mode = \"production\"\n // `--api-base-url` feeds the client's PUBLIC_API_BASE_URL. Setting it on\n // process.env (before loadEnv/Vite read env) makes the flag win over any .env\n // value and keeps the single env-prefix mechanism — no Vite `define`.\n applyApiBaseUrlFlag(args)\n const env = { ...process.env, ...loadEnv(mode, root, \"\") }\n const quiet = Boolean(args.flags.json)\n\n // Write .vantage/ up front instead of letting the plugin do it at\n // configResolved: the server bundle reads server-routes.gen.ts, so once the\n // artifacts exist the two builds no longer depend on each other and can run\n // at the same time (they write to dist/client and dist/server respectively).\n generateArtifacts({ root, model })\n\n if (!quiet) log.step(model.hasServer ? \"Building client and server…\" : \"Building client…\")\n\n const clientBuild = timedAsync(\"build:client\", async () => {\n await viteBuild({\n configFile: false,\n root,\n mode,\n plugins: [vantagePlugin({ root, env, model, artifactsWritten: true })],\n logLevel: quiet ? \"silent\" : args.flags.verbose ? \"info\" : \"warn\",\n })\n // The HTML input lives in .vantage/, so Vite emits it to dist/client/.vantage/.\n // Hoist it to dist/client/index.html (asset URLs are already root-absolute).\n relocateClientHtml(root)\n })\n\n const serverBuild = model.hasServer\n ? timedAsync(\"build:server\", () => buildServer(root))\n : Promise.resolve()\n\n await Promise.all([clientBuild, serverBuild])\n\n writeDeployManifest(root, model)\n if (!quiet) log.ok(`Build complete → ${path.relative(process.cwd(), path.join(root, \"dist\")) || \"dist\"}/`)\n\n if (args.flags.json) {\n process.stdout.write(\n JSON.stringify({\n ok: true,\n mode: model.hasServer ? \"fullstack\" : \"spa\",\n output: \"dist\",\n pages: model.pages.length,\n apis: model.apis.length,\n }) + \"\\n\",\n )\n }\n return 0\n}\n\nfunction relocateClientHtml(root: string): void {\n const clientDir = path.join(root, \"dist\", \"client\")\n const nested = path.join(clientDir, VANTAGE_DIR, \"index.html\")\n const target = path.join(clientDir, \"index.html\")\n if (fs.existsSync(nested)) {\n fs.mkdirSync(clientDir, { recursive: true })\n fs.renameSync(nested, target)\n fs.rmSync(path.join(clientDir, VANTAGE_DIR), { recursive: true, force: true })\n }\n}\n\nasync function buildServer(root: string): Promise<void> {\n // Loaded here, not at module scope: an SPA project never builds a server and\n // should not pay for esbuild's binary being brought up.\n const { build: esbuildBuild } = await import(\"esbuild\")\n const vantageDir = path.join(root, VANTAGE_DIR)\n const entry = path.join(vantageDir, \"server-entry.ts\")\n fs.writeFileSync(entry, SERVER_ENTRY)\n await esbuildBuild({\n entryPoints: [entry],\n outfile: path.join(root, \"dist\", \"server\", \"index.mjs\"),\n bundle: true,\n platform: \"node\",\n format: \"esm\",\n target: \"node20\",\n logLevel: \"warning\",\n banner: { js: \"// @squadbase/vantage server bundle\" },\n })\n}\n\nfunction writeDeployManifest(root: string, model: RouteModel): void {\n const dist = path.join(root, \"dist\")\n fs.mkdirSync(dist, { recursive: true })\n const manifest = {\n schemaVersion: MANIFEST_SCHEMA_VERSION,\n mode: model.hasServer ? \"fullstack\" : \"spa\",\n client: \"./client\",\n ...(model.hasServer ? { server: \"./server/index.mjs\" } : {}),\n spaFallback: \"./client/index.html\",\n runtime: \"node\",\n }\n fs.writeFileSync(path.join(dist, \"vantage-manifest.json\"), JSON.stringify(manifest, null, 2) + \"\\n\")\n}\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { runDiagnostics } from './chunk-PSEYFYAP.js';
|
|
2
|
+
import './chunk-BAM33YZ6.js';
|
|
3
|
+
import './chunk-VXAV2435.js';
|
|
4
|
+
import { scanProject } from './chunk-D4Y5RWJA.js';
|
|
5
|
+
import { printJson, log, printDiagnostics } from './chunk-OFFJ3OL5.js';
|
|
6
|
+
import './chunk-C4MQRWXS.js';
|
|
7
|
+
|
|
8
|
+
// @squadbase/vantage — generated build. Do not edit.
|
|
9
|
+
|
|
10
|
+
// src/cli/check.ts
|
|
11
|
+
async function check(root, args) {
|
|
12
|
+
const model = scanProject(root);
|
|
13
|
+
const diags = runDiagnostics(root, model);
|
|
14
|
+
const errors = diags.filter((d) => d.severity === "error");
|
|
15
|
+
const warnings = diags.filter((d) => d.severity === "warning");
|
|
16
|
+
if (args.flags.json) {
|
|
17
|
+
printJson({
|
|
18
|
+
ok: errors.length === 0,
|
|
19
|
+
errorCount: errors.length,
|
|
20
|
+
warningCount: warnings.length,
|
|
21
|
+
diagnostics: diags
|
|
22
|
+
});
|
|
23
|
+
return errors.length ? 1 : 0;
|
|
24
|
+
}
|
|
25
|
+
if (diags.length === 0) {
|
|
26
|
+
log.ok("No problems found.");
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
printDiagnostics(diags);
|
|
30
|
+
console.log("");
|
|
31
|
+
if (errors.length) log.error(`${errors.length} error(s), ${warnings.length} warning(s).`);
|
|
32
|
+
else log.warn(`${warnings.length} warning(s).`);
|
|
33
|
+
return errors.length ? 1 : 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { check };
|
|
37
|
+
//# sourceMappingURL=check-QPFERQLO.js.map
|
|
38
|
+
//# sourceMappingURL=check-QPFERQLO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/check.ts"],"names":[],"mappings":";;;;;;;;;;AAKA,eAAsB,KAAA,CAAM,MAAc,IAAA,EAAmC;AAC3E,EAAA,MAAM,KAAA,GAAQ,YAAY,IAAI,CAAA;AAC9B,EAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,IAAA,EAAM,KAAK,CAAA;AACxC,EAAA,MAAM,SAAS,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,OAAO,CAAA;AACzD,EAAA,MAAM,WAAW,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,SAAS,CAAA;AAE7D,EAAA,IAAI,IAAA,CAAK,MAAM,IAAA,EAAM;AACnB,IAAA,SAAA,CAAU;AAAA,MACR,EAAA,EAAI,OAAO,MAAA,KAAW,CAAA;AAAA,MACtB,YAAY,MAAA,CAAO,MAAA;AAAA,MACnB,cAAc,QAAA,CAAS,MAAA;AAAA,MACvB,WAAA,EAAa;AAAA,KACd,CAAA;AACD,IAAA,OAAO,MAAA,CAAO,SAAS,CAAA,GAAI,CAAA;AAAA,EAC7B;AAEA,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,GAAA,CAAI,GAAG,oBAAoB,CAAA;AAC3B,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,gBAAA,CAAiB,KAAK,CAAA;AACtB,EAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,EAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,OAAO,MAAM,CAAA,WAAA,EAAc,QAAA,CAAS,MAAM,CAAA,YAAA,CAAc,CAAA;AAAA,OACnF,GAAA,CAAI,IAAA,CAAK,CAAA,EAAG,QAAA,CAAS,MAAM,CAAA,YAAA,CAAc,CAAA;AAC9C,EAAA,OAAO,MAAA,CAAO,SAAS,CAAA,GAAI,CAAA;AAC7B","file":"check-QPFERQLO.js","sourcesContent":["import { runDiagnostics } from \"../core/diagnostics\"\nimport { scanProject } from \"../core/scan\"\nimport { log, printDiagnostics, printJson, type ParsedArgs } from \"./util\"\n\n/** `vantage check` — static verification of the project. */\nexport async function check(root: string, args: ParsedArgs): Promise<number> {\n const model = scanProject(root)\n const diags = runDiagnostics(root, model)\n const errors = diags.filter((d) => d.severity === \"error\")\n const warnings = diags.filter((d) => d.severity === \"warning\")\n\n if (args.flags.json) {\n printJson({\n ok: errors.length === 0,\n errorCount: errors.length,\n warningCount: warnings.length,\n diagnostics: diags,\n })\n return errors.length ? 1 : 0\n }\n\n if (diags.length === 0) {\n log.ok(\"No problems found.\")\n return 0\n }\n printDiagnostics(diags)\n console.log(\"\")\n if (errors.length) log.error(`${errors.length} error(s), ${warnings.length} warning(s).`)\n else log.warn(`${warnings.length} warning(s).`)\n return errors.length ? 1 : 0\n}\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
// @squadbase/vantage — generated build. Do not edit.
|
|
6
|
+
|
|
7
|
+
var SUPPORTED_SCHEMA_VERSION = 2;
|
|
8
|
+
var DOC_LANGS = ["ja", "en"];
|
|
9
|
+
var DEFAULT_DOC_LANG = "ja";
|
|
10
|
+
function isDocLang(value) {
|
|
11
|
+
return typeof value === "string" && DOC_LANGS.includes(value);
|
|
12
|
+
}
|
|
13
|
+
function docsDir() {
|
|
14
|
+
return fileURLToPath(new URL("../docs/", import.meta.url));
|
|
15
|
+
}
|
|
16
|
+
function loadCatalog() {
|
|
17
|
+
try {
|
|
18
|
+
const raw = fs.readFileSync(path.join(docsDir(), "index.json"), "utf8");
|
|
19
|
+
const parsed = JSON.parse(raw);
|
|
20
|
+
if (parsed.schemaVersion !== SUPPORTED_SCHEMA_VERSION) return null;
|
|
21
|
+
return Array.isArray(parsed.docs) ? parsed.docs : null;
|
|
22
|
+
} catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function docsForLang(catalog, lang) {
|
|
27
|
+
return catalog.filter((doc) => doc.lang === lang);
|
|
28
|
+
}
|
|
29
|
+
function readDoc(entry) {
|
|
30
|
+
return fs.readFileSync(path.join(docsDir(), entry.file), "utf8");
|
|
31
|
+
}
|
|
32
|
+
function resolveDoc(entries, query) {
|
|
33
|
+
const needle = query.toLowerCase().replace(/^\/+|\/+$/g, "").replace(/\.mdx?$/, "");
|
|
34
|
+
const exact = entries.filter((doc) => doc.slug.toLowerCase() === needle);
|
|
35
|
+
if (exact.length === 1) return { kind: "found", doc: exact[0] };
|
|
36
|
+
const byLeaf = entries.filter((doc) => (doc.slug.split("/").pop() ?? "").toLowerCase() === needle);
|
|
37
|
+
if (byLeaf.length === 1) return { kind: "found", doc: byLeaf[0] };
|
|
38
|
+
if (byLeaf.length > 1) return { kind: "ambiguous", matches: byLeaf };
|
|
39
|
+
const partial = entries.filter(
|
|
40
|
+
(doc) => doc.slug.toLowerCase().includes(needle) || doc.title.toLowerCase().includes(needle)
|
|
41
|
+
);
|
|
42
|
+
return { kind: "missing", suggestions: partial };
|
|
43
|
+
}
|
|
44
|
+
function groupBySection(entries) {
|
|
45
|
+
const groups = [];
|
|
46
|
+
for (const doc of entries) {
|
|
47
|
+
const last = groups[groups.length - 1];
|
|
48
|
+
if (last && last.section === doc.section) last.docs.push(doc);
|
|
49
|
+
else groups.push({ section: doc.section, title: doc.sectionTitle, docs: [doc] });
|
|
50
|
+
}
|
|
51
|
+
return groups;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { DEFAULT_DOC_LANG, DOC_LANGS, docsForLang, groupBySection, isDocLang, loadCatalog, readDoc, resolveDoc };
|
|
55
|
+
//# sourceMappingURL=chunk-2KRCGXBY.js.map
|
|
56
|
+
//# sourceMappingURL=chunk-2KRCGXBY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/docs-catalog.ts"],"names":[],"mappings":";;;;;;AAiCA,IAAM,wBAAA,GAA2B,CAAA;AAE1B,IAAM,SAAA,GAAY,CAAC,IAAA,EAAM,IAAI;AAE7B,IAAM,gBAAA,GAA4B;AAElC,SAAS,UAAU,KAAA,EAAkC;AAC1D,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAa,SAAA,CAAgC,SAAS,KAAK,CAAA;AACrF;AAMO,SAAS,OAAA,GAAkB;AAChC,EAAA,OAAO,cAAc,IAAI,GAAA,CAAI,UAAA,EAAY,MAAA,CAAA,IAAA,CAAY,GAAG,CAAC,CAAA;AAC3D;AAGO,SAAS,WAAA,GAAiC;AAC/C,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,GAAG,YAAA,CAAa,IAAA,CAAK,KAAK,OAAA,EAAQ,EAAG,YAAY,CAAA,EAAG,MAAM,CAAA;AACtE,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,IAAI,MAAA,CAAO,aAAA,KAAkB,wBAAA,EAA0B,OAAO,IAAA;AAC9D,IAAA,OAAO,MAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,GAAI,OAAO,IAAA,GAAO,IAAA;AAAA,EACpD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAGO,SAAS,WAAA,CAAY,SAAqB,IAAA,EAA2B;AAC1E,EAAA,OAAO,QAAQ,MAAA,CAAO,CAAC,GAAA,KAAQ,GAAA,CAAI,SAAS,IAAI,CAAA;AAClD;AAGO,SAAS,QAAQ,KAAA,EAAyB;AAC/C,EAAA,OAAO,EAAA,CAAG,aAAa,IAAA,CAAK,IAAA,CAAK,SAAQ,EAAG,KAAA,CAAM,IAAI,CAAA,EAAG,MAAM,CAAA;AACjE;AAYO,SAAS,UAAA,CAAW,SAAqB,KAAA,EAA0B;AACxE,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,WAAA,EAAY,CAAE,OAAA,CAAQ,cAAc,EAAE,CAAA,CAAE,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA;AAElF,EAAA,MAAM,KAAA,GAAQ,QAAQ,MAAA,CAAO,CAAC,QAAQ,GAAA,CAAI,IAAA,CAAK,WAAA,EAAY,KAAM,MAAM,CAAA;AACvE,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,EAAE,MAAM,OAAA,EAAS,GAAA,EAAK,KAAA,CAAM,CAAC,CAAA,EAAG;AAE/D,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,CAAC,SAAS,GAAA,CAAI,IAAA,CAAK,KAAA,CAAM,GAAG,EAAE,GAAA,EAAI,IAAK,EAAA,EAAI,WAAA,OAAkB,MAAM,CAAA;AACjG,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,EAAE,MAAM,OAAA,EAAS,GAAA,EAAK,MAAA,CAAO,CAAC,CAAA,EAAG;AACjE,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG,OAAO,EAAE,IAAA,EAAM,WAAA,EAAa,SAAS,MAAA,EAAO;AAEnE,EAAA,MAAM,UAAU,OAAA,CAAQ,MAAA;AAAA,IACtB,CAAC,GAAA,KAAQ,GAAA,CAAI,IAAA,CAAK,aAAY,CAAE,QAAA,CAAS,MAAM,CAAA,IAAK,GAAA,CAAI,KAAA,CAAM,WAAA,EAAY,CAAE,SAAS,MAAM;AAAA,GAC7F;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,WAAA,EAAa,OAAA,EAAQ;AACjD;AAGO,SAAS,eAAe,OAAA,EAA6E;AAC1G,EAAA,MAAM,SAAiE,EAAC;AACxE,EAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AACzB,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAC,CAAA;AACrC,IAAA,IAAI,IAAA,IAAQ,KAAK,OAAA,KAAY,GAAA,CAAI,SAAS,IAAA,CAAK,IAAA,CAAK,KAAK,GAAG,CAAA;AAAA,SACvD,MAAA,CAAO,IAAA,CAAK,EAAE,OAAA,EAAS,GAAA,CAAI,OAAA,EAAS,KAAA,EAAO,GAAA,CAAI,YAAA,EAAc,IAAA,EAAM,CAAC,GAAG,GAAG,CAAA;AAAA,EACjF;AACA,EAAA,OAAO,MAAA;AACT","file":"chunk-2KRCGXBY.js","sourcesContent":["import fs from \"node:fs\"\nimport path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\n\n/**\n * Reader for the documentation bundled with the package. The bundle is produced\n * by `scripts/build-docs.mjs` from `docs/content` at build time — plain Markdown\n * plus an `index.json` catalog. Kept separate from the `docs` command so other\n * commands (search) can consume the same corpus.\n */\n\n/** One entry of the bundled catalog (`docs/index.json`). */\nexport interface DocEntry {\n slug: string\n lang: string\n section: string\n sectionTitle: string\n title: string\n description: string\n /** Path of the Markdown file, relative to the docs bundle root. */\n file: string\n order: number\n /** Absent means searchable; `false` opts the page out of `vantage search`. */\n searchable?: boolean\n}\n\ninterface DocsIndex {\n schemaVersion: number\n generatedFrom: string\n docs: DocEntry[]\n}\n\n/** Shape of `docs/index.json` this CLI understands. */\nconst SUPPORTED_SCHEMA_VERSION = 2\n\nexport const DOC_LANGS = [\"ja\", \"en\"] as const\nexport type DocLang = (typeof DOC_LANGS)[number]\nexport const DEFAULT_DOC_LANG: DocLang = \"ja\"\n\nexport function isDocLang(value: unknown): value is DocLang {\n return typeof value === \"string\" && (DOC_LANGS as readonly string[]).includes(value)\n}\n\n/**\n * Directory of the bundled docs. `dist/cli.js` lives in `dist/`, so the bundle\n * is one level up — the same relative anchor `frameworkVersion()` uses.\n */\nexport function docsDir(): string {\n return fileURLToPath(new URL(\"../docs/\", import.meta.url))\n}\n\n/** Read the catalog, or null when the bundle is missing or unreadable. */\nexport function loadCatalog(): DocEntry[] | null {\n try {\n const raw = fs.readFileSync(path.join(docsDir(), \"index.json\"), \"utf8\")\n const parsed = JSON.parse(raw) as DocsIndex\n if (parsed.schemaVersion !== SUPPORTED_SCHEMA_VERSION) return null\n return Array.isArray(parsed.docs) ? parsed.docs : null\n } catch {\n return null\n }\n}\n\n/** Catalog entries for one language, in bundle order (sections then pages). */\nexport function docsForLang(catalog: DocEntry[], lang: DocLang): DocEntry[] {\n return catalog.filter((doc) => doc.lang === lang)\n}\n\n/** Read one entry's Markdown body. */\nexport function readDoc(entry: DocEntry): string {\n return fs.readFileSync(path.join(docsDir(), entry.file), \"utf8\")\n}\n\nexport type DocLookup =\n | { kind: \"found\"; doc: DocEntry }\n | { kind: \"ambiguous\"; matches: DocEntry[] }\n | { kind: \"missing\"; suggestions: DocEntry[] }\n\n/**\n * Resolve a user-typed name to one doc. Exact slugs win, then the short form\n * (`button` → `ui/button`, unique across the bundle today), then a substring\n * match that only reports candidates.\n */\nexport function resolveDoc(entries: DocEntry[], query: string): DocLookup {\n const needle = query.toLowerCase().replace(/^\\/+|\\/+$/g, \"\").replace(/\\.mdx?$/, \"\")\n\n const exact = entries.filter((doc) => doc.slug.toLowerCase() === needle)\n if (exact.length === 1) return { kind: \"found\", doc: exact[0]! }\n\n const byLeaf = entries.filter((doc) => (doc.slug.split(\"/\").pop() ?? \"\").toLowerCase() === needle)\n if (byLeaf.length === 1) return { kind: \"found\", doc: byLeaf[0]! }\n if (byLeaf.length > 1) return { kind: \"ambiguous\", matches: byLeaf }\n\n const partial = entries.filter(\n (doc) => doc.slug.toLowerCase().includes(needle) || doc.title.toLowerCase().includes(needle),\n )\n return { kind: \"missing\", suggestions: partial }\n}\n\n/** Group entries by section, preserving the catalog's order. */\nexport function groupBySection(entries: DocEntry[]): { section: string; title: string; docs: DocEntry[] }[] {\n const groups: { section: string; title: string; docs: DocEntry[] }[] = []\n for (const doc of entries) {\n const last = groups[groups.length - 1]\n if (last && last.section === doc.section) last.docs.push(doc)\n else groups.push({ section: doc.section, title: doc.sectionTitle, docs: [doc] })\n }\n return groups\n}\n"]}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { extractPageMeta } from './chunk-VXAV2435.js';
|
|
2
|
+
import { API_METHODS } from './chunk-C4MQRWXS.js';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
|
|
5
|
+
// @squadbase/vantage — generated build. Do not edit.
|
|
6
|
+
|
|
7
|
+
// src/core/source.ts
|
|
8
|
+
function stripComments(src) {
|
|
9
|
+
return src.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:"'`\\])\/\/[^\n]*/g, "$1");
|
|
10
|
+
}
|
|
11
|
+
var OPENERS = { "(": ")", "[": "]", "{": "}" };
|
|
12
|
+
function readBracketBody(src, openIndex) {
|
|
13
|
+
const open = src[openIndex];
|
|
14
|
+
if (!open || !OPENERS[open]) return null;
|
|
15
|
+
let depth = 0;
|
|
16
|
+
let quote = null;
|
|
17
|
+
for (let i = openIndex; i < src.length; i++) {
|
|
18
|
+
const c = src[i];
|
|
19
|
+
if (quote) {
|
|
20
|
+
if (c === "\\") i++;
|
|
21
|
+
else if (c === quote) quote = null;
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
25
|
+
quote = c;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (OPENERS[c]) depth++;
|
|
29
|
+
else if (c === ")" || c === "]" || c === "}") {
|
|
30
|
+
if (--depth === 0) return src.slice(openIndex + 1, i);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function splitTopLevel(body) {
|
|
36
|
+
const parts = [];
|
|
37
|
+
let depth = 0;
|
|
38
|
+
let quote = null;
|
|
39
|
+
let start = 0;
|
|
40
|
+
for (let i = 0; i < body.length; i++) {
|
|
41
|
+
const c = body[i];
|
|
42
|
+
if (quote) {
|
|
43
|
+
if (c === "\\") i++;
|
|
44
|
+
else if (c === quote) quote = null;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
48
|
+
quote = c;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (OPENERS[c]) depth++;
|
|
52
|
+
else if (c === ")" || c === "]" || c === "}") depth--;
|
|
53
|
+
else if (c === "," && depth === 0) {
|
|
54
|
+
parts.push(body.slice(start, i));
|
|
55
|
+
start = i + 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
parts.push(body.slice(start));
|
|
59
|
+
return parts.map((p) => p.trim()).filter(Boolean);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// src/core/route-spec.ts
|
|
63
|
+
function detectApiMethods(src) {
|
|
64
|
+
return API_METHODS.filter(
|
|
65
|
+
(m) => new RegExp(`export\\s+(async\\s+)?(function|const|let|var)\\s+${m}\\b`).test(src) || new RegExp(`export\\s*\\{[^}]*\\b${m}\\b[^}]*\\}`).test(src)
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
function methodRegions(src) {
|
|
69
|
+
const re = new RegExp(
|
|
70
|
+
`export\\s+(?:async\\s+)?(?:function|const|let|var)\\s+(${API_METHODS.join("|")})\\b`,
|
|
71
|
+
"g"
|
|
72
|
+
);
|
|
73
|
+
const decls = [];
|
|
74
|
+
let m;
|
|
75
|
+
while (m = re.exec(src)) decls.push({ method: m[1], index: m.index });
|
|
76
|
+
const regions = /* @__PURE__ */ new Map();
|
|
77
|
+
decls.forEach((d, i) => {
|
|
78
|
+
regions.set(d.method, src.slice(d.index, decls[i + 1]?.index ?? src.length));
|
|
79
|
+
});
|
|
80
|
+
for (const method of detectApiMethods(src)) {
|
|
81
|
+
if (!regions.has(method)) regions.set(method, src);
|
|
82
|
+
}
|
|
83
|
+
return regions;
|
|
84
|
+
}
|
|
85
|
+
function objectKeys(expr) {
|
|
86
|
+
const trimmed = expr.trim();
|
|
87
|
+
if (!trimmed.startsWith("{")) return void 0;
|
|
88
|
+
const body = readBracketBody(trimmed, 0);
|
|
89
|
+
if (body == null) return void 0;
|
|
90
|
+
const keys = [];
|
|
91
|
+
for (const part of splitTopLevel(body)) {
|
|
92
|
+
if (part.startsWith("...")) {
|
|
93
|
+
keys.push("\u2026");
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const name = part.match(/^["'`]?([A-Za-z0-9_$]+)/);
|
|
97
|
+
if (name) keys.push(name[1]);
|
|
98
|
+
}
|
|
99
|
+
return keys.length ? keys : void 0;
|
|
100
|
+
}
|
|
101
|
+
function initStatus(init) {
|
|
102
|
+
const m = init?.match(/\bstatus\s*:\s*(\d{3})\b/);
|
|
103
|
+
return m ? Number(m[1]) : void 0;
|
|
104
|
+
}
|
|
105
|
+
function initContentType(init) {
|
|
106
|
+
const m = init?.match(/["']?content-type["']?\s*:\s*["']([^"';]+)/i);
|
|
107
|
+
return m ? m[1].trim() : void 0;
|
|
108
|
+
}
|
|
109
|
+
function extractResponses(region) {
|
|
110
|
+
const re = /\bnew\s+Response\s*\(|\bResponse\s*\.\s*json\s*\(|(?<![.\w$])json\s*\(/g;
|
|
111
|
+
const out = [];
|
|
112
|
+
const seen = /* @__PURE__ */ new Set();
|
|
113
|
+
let m;
|
|
114
|
+
while (m = re.exec(region)) {
|
|
115
|
+
const isJson = !m[0].startsWith("new");
|
|
116
|
+
const args = readBracketBody(region, m.index + m[0].length - 1);
|
|
117
|
+
if (args == null) continue;
|
|
118
|
+
const [payload, init] = splitTopLevel(args);
|
|
119
|
+
const contentType = isJson ? "application/json" : initContentType(init) ?? (payload?.startsWith("JSON.stringify") ? "application/json" : void 0);
|
|
120
|
+
const keys = isJson && payload ? objectKeys(payload) : void 0;
|
|
121
|
+
const spec = {
|
|
122
|
+
status: initStatus(init) ?? 200,
|
|
123
|
+
...contentType ? { contentType } : {},
|
|
124
|
+
...keys ? { keys } : {}
|
|
125
|
+
};
|
|
126
|
+
const key = JSON.stringify(spec);
|
|
127
|
+
if (seen.has(key)) continue;
|
|
128
|
+
seen.add(key);
|
|
129
|
+
out.push(spec);
|
|
130
|
+
}
|
|
131
|
+
return out;
|
|
132
|
+
}
|
|
133
|
+
function extractErrors(region) {
|
|
134
|
+
const re = /\bHttpError\s*\(\s*(\d{3})\s*(?:,\s*(?:(["'`])((?:\\.|(?!\2)[\s\S])*)\2))?/g;
|
|
135
|
+
const out = [];
|
|
136
|
+
const seen = /* @__PURE__ */ new Set();
|
|
137
|
+
let m;
|
|
138
|
+
while (m = re.exec(region)) {
|
|
139
|
+
const message = m[3]?.replace(/\\(.)/g, "$1");
|
|
140
|
+
const spec = { status: Number(m[1]), ...message ? { message } : {} };
|
|
141
|
+
const key = JSON.stringify(spec);
|
|
142
|
+
if (seen.has(key)) continue;
|
|
143
|
+
seen.add(key);
|
|
144
|
+
out.push(spec);
|
|
145
|
+
}
|
|
146
|
+
return out;
|
|
147
|
+
}
|
|
148
|
+
function extractQuery(region) {
|
|
149
|
+
const re = /searchParams\s*\.\s*(?:get|getAll|has)\s*\(\s*["'`]([^"'`]+)["'`]/g;
|
|
150
|
+
const out = /* @__PURE__ */ new Set();
|
|
151
|
+
let m;
|
|
152
|
+
while (m = re.exec(region)) out.add(m[1]);
|
|
153
|
+
return [...out];
|
|
154
|
+
}
|
|
155
|
+
function extractBody(region) {
|
|
156
|
+
const read = region.match(/\b(?:request|req)\s*\.\s*(json|formData|text|arrayBuffer|blob)\s*\(/);
|
|
157
|
+
if (!read) return void 0;
|
|
158
|
+
const method = read[1];
|
|
159
|
+
const format = method === "json" || method === "formData" || method === "text" ? method : "binary";
|
|
160
|
+
const destructured = region.match(
|
|
161
|
+
/(?:const|let|var)\s*(\{[\s\S]*?\})\s*=\s*(?:await\s+)?[\w.]*\.json\s*\(/
|
|
162
|
+
);
|
|
163
|
+
const keys = format === "json" && destructured ? objectKeys(destructured[1]) : void 0;
|
|
164
|
+
return { format, ...keys ? { keys } : {} };
|
|
165
|
+
}
|
|
166
|
+
function toParams(segments) {
|
|
167
|
+
const out = [];
|
|
168
|
+
for (const s of segments) {
|
|
169
|
+
if (s.kind === "static") continue;
|
|
170
|
+
out.push({ name: s.name, kind: s.kind });
|
|
171
|
+
}
|
|
172
|
+
return out;
|
|
173
|
+
}
|
|
174
|
+
function extractPageSpec(page) {
|
|
175
|
+
return { params: toParams(page.segments), ...extractPageMeta(page.absFile) };
|
|
176
|
+
}
|
|
177
|
+
function extractApiSpec(api) {
|
|
178
|
+
const params = toParams(api.segments);
|
|
179
|
+
let src;
|
|
180
|
+
try {
|
|
181
|
+
src = stripComments(fs.readFileSync(api.absFile, "utf8"));
|
|
182
|
+
} catch {
|
|
183
|
+
return { params, methods: [] };
|
|
184
|
+
}
|
|
185
|
+
const regions = methodRegions(src);
|
|
186
|
+
const methods = API_METHODS.filter((m) => regions.has(m)).map((method) => {
|
|
187
|
+
const region = regions.get(method);
|
|
188
|
+
const body = extractBody(region);
|
|
189
|
+
return {
|
|
190
|
+
method,
|
|
191
|
+
query: extractQuery(region),
|
|
192
|
+
...body ? { body } : {},
|
|
193
|
+
responses: extractResponses(region),
|
|
194
|
+
errors: extractErrors(region)
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
return { params, methods };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export { detectApiMethods, extractApiSpec, extractPageSpec, stripComments };
|
|
201
|
+
//# sourceMappingURL=chunk-BAM33YZ6.js.map
|
|
202
|
+
//# sourceMappingURL=chunk-BAM33YZ6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/source.ts","../src/core/route-spec.ts"],"names":[],"mappings":"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","file":"chunk-BAM33YZ6.js","sourcesContent":["/**\n * Low-level source scanning helpers shared by the static analyzers\n * (`diagnostics.ts`, `route-spec.ts`). Everything here is text-only — user code\n * is never imported or executed.\n */\n\n/**\n * Strip block and line comments so commented-out code doesn't produce false\n * positives (or hide real issues). Naive but adequate for presence checks:\n * URLs (`http://`) are preserved via the `[^:]` guard before `//`.\n */\nexport function stripComments(src: string): string {\n return src.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\").replace(/(^|[^:\"'`\\\\])\\/\\/[^\\n]*/g, \"$1\")\n}\n\nconst OPENERS: Record<string, string> = { \"(\": \")\", \"[\": \"]\", \"{\": \"}\" }\n\n/**\n * Read a balanced bracketed region starting at `openIndex` (which must hold\n * `(`, `[` or `{`), returning the raw text *between* the brackets. Quote- and\n * nesting-aware so brackets inside string literals don't unbalance the scan.\n * Returns null when the region is never closed.\n */\nexport function readBracketBody(src: string, openIndex: number): string | null {\n const open = src[openIndex]\n if (!open || !OPENERS[open]) return null\n let depth = 0\n let quote: string | null = null\n for (let i = openIndex; i < src.length; i++) {\n const c = src[i]!\n if (quote) {\n if (c === \"\\\\\") i++\n else if (c === quote) quote = null\n continue\n }\n if (c === '\"' || c === \"'\" || c === \"`\") {\n quote = c\n continue\n }\n if (OPENERS[c]) depth++\n else if (c === \")\" || c === \"]\" || c === \"}\") {\n if (--depth === 0) return src.slice(openIndex + 1, i)\n }\n }\n return null\n}\n\n/**\n * Split an argument list or object body on top-level commas, ignoring commas\n * nested inside brackets or string literals. Empty parts are dropped.\n */\nexport function splitTopLevel(body: string): string[] {\n const parts: string[] = []\n let depth = 0\n let quote: string | null = null\n let start = 0\n for (let i = 0; i < body.length; i++) {\n const c = body[i]!\n if (quote) {\n if (c === \"\\\\\") i++\n else if (c === quote) quote = null\n continue\n }\n if (c === '\"' || c === \"'\" || c === \"`\") {\n quote = c\n continue\n }\n if (OPENERS[c]) depth++\n else if (c === \")\" || c === \"]\" || c === \"}\") depth--\n else if (c === \",\" && depth === 0) {\n parts.push(body.slice(start, i))\n start = i + 1\n }\n }\n parts.push(body.slice(start))\n return parts.map((p) => p.trim()).filter(Boolean)\n}\n","import fs from \"node:fs\"\nimport { API_METHODS, type ApiMethod } from \"./constants\"\nimport { extractPageMeta } from \"./route-tree\"\nimport { readBracketBody, splitTopLevel, stripComments } from \"./source\"\nimport type { ApiRoute, PageRoute, Segment } from \"./types\"\n\n/**\n * Best-effort *static* specs for the routes `vantage routes --detail` prints:\n * what a page takes in its path, and what an API route accepts and answers\n * with. Like `diagnostics.ts` this only reads text — user modules are never\n * imported or executed — so every field is a hint derived from the source, not\n * a guarantee. Callers pass sources through {@link stripComments} first.\n */\n\n/** A dynamic segment of a route path. */\nexport interface RouteParam {\n name: string\n kind: \"param\" | \"catchall\"\n}\n\n/** Static spec of a page route. */\nexport interface PageSpec {\n params: RouteParam[]\n title?: string\n description?: string\n navLabel?: string\n}\n\n/** The request body an API handler reads, when detectable. */\nexport interface ApiBodySpec {\n format: \"json\" | \"formData\" | \"text\" | \"binary\"\n /** Top-level keys, when the handler destructures them. */\n keys?: string[]\n}\n\n/** A response an API handler returns. */\nexport interface ApiResponseSpec {\n status: number\n /** Response content type, omitted when it can't be derived. */\n contentType?: string\n /** Top-level keys, when the payload is an object literal. */\n keys?: string[]\n}\n\n/** An `HttpError` an API handler throws. */\nexport interface ApiErrorSpec {\n status: number\n message?: string\n}\n\n/** Static spec of one HTTP method handler. */\nexport interface ApiMethodSpec {\n method: ApiMethod\n /** Query string keys read via `searchParams`. */\n query: string[]\n body?: ApiBodySpec\n responses: ApiResponseSpec[]\n errors: ApiErrorSpec[]\n}\n\n/** Static spec of an API route module. */\nexport interface ApiSpec {\n params: RouteParam[]\n methods: ApiMethodSpec[]\n}\n\n/**\n * HTTP method handlers a module exports (direct declaration or export list).\n * `src` must be comment-stripped. Shared with the `INVALID_API_EXPORT`\n * diagnostic so both agree on what counts as a handler.\n */\nexport function detectApiMethods(src: string): ApiMethod[] {\n return API_METHODS.filter(\n (m) =>\n new RegExp(`export\\\\s+(async\\\\s+)?(function|const|let|var)\\\\s+${m}\\\\b`).test(src) ||\n new RegExp(`export\\\\s*\\\\{[^}]*\\\\b${m}\\\\b[^}]*\\\\}`).test(src),\n )\n}\n\n/**\n * Slice the module into one source region per handler: from a handler's export\n * declaration to the next one (or EOF). Coarse on purpose — matching a function\n * body would have to cope with arrow bodies, overloads and trailing helpers —\n * and good enough because handlers are written one after another. A method\n * exported only through an export list gets the whole module as its region.\n */\nfunction methodRegions(src: string): Map<ApiMethod, string> {\n const re = new RegExp(\n `export\\\\s+(?:async\\\\s+)?(?:function|const|let|var)\\\\s+(${API_METHODS.join(\"|\")})\\\\b`,\n \"g\",\n )\n const decls: { method: ApiMethod; index: number }[] = []\n let m: RegExpExecArray | null\n while ((m = re.exec(src))) decls.push({ method: m[1] as ApiMethod, index: m.index })\n\n const regions = new Map<ApiMethod, string>()\n decls.forEach((d, i) => {\n regions.set(d.method, src.slice(d.index, decls[i + 1]?.index ?? src.length))\n })\n for (const method of detectApiMethods(src)) {\n if (!regions.has(method)) regions.set(method, src)\n }\n return regions\n}\n\n/** Top-level keys of an object literal expression, `…` standing in for spreads. */\nfunction objectKeys(expr: string): string[] | undefined {\n const trimmed = expr.trim()\n if (!trimmed.startsWith(\"{\")) return undefined\n const body = readBracketBody(trimmed, 0)\n if (body == null) return undefined\n const keys: string[] = []\n for (const part of splitTopLevel(body)) {\n if (part.startsWith(\"...\")) {\n keys.push(\"…\")\n continue\n }\n const name = part.match(/^[\"'`]?([A-Za-z0-9_$]+)/)\n if (name) keys.push(name[1]!)\n }\n return keys.length ? keys : undefined\n}\n\n/** Read `status: 201` out of a `ResponseInit` literal. */\nfunction initStatus(init: string | undefined): number | undefined {\n const m = init?.match(/\\bstatus\\s*:\\s*(\\d{3})\\b/)\n return m ? Number(m[1]) : undefined\n}\n\n/** Read a content-type header out of a `ResponseInit` literal. */\nfunction initContentType(init: string | undefined): string | undefined {\n const m = init?.match(/[\"']?content-type[\"']?\\s*:\\s*[\"']([^\"';]+)/i)\n return m ? m[1]!.trim() : undefined\n}\n\n/** Every `Response.json(…)` / `json(…)` / `new Response(…)` in a handler region. */\nfunction extractResponses(region: string): ApiResponseSpec[] {\n const re = /\\bnew\\s+Response\\s*\\(|\\bResponse\\s*\\.\\s*json\\s*\\(|(?<![.\\w$])json\\s*\\(/g\n const out: ApiResponseSpec[] = []\n const seen = new Set<string>()\n let m: RegExpExecArray | null\n while ((m = re.exec(region))) {\n const isJson = !m[0].startsWith(\"new\")\n const args = readBracketBody(region, m.index + m[0].length - 1)\n if (args == null) continue\n const [payload, init] = splitTopLevel(args)\n const contentType = isJson\n ? \"application/json\"\n : (initContentType(init) ??\n (payload?.startsWith(\"JSON.stringify\") ? \"application/json\" : undefined))\n const keys = isJson && payload ? objectKeys(payload) : undefined\n const spec: ApiResponseSpec = {\n status: initStatus(init) ?? 200,\n ...(contentType ? { contentType } : {}),\n ...(keys ? { keys } : {}),\n }\n const key = JSON.stringify(spec)\n if (seen.has(key)) continue\n seen.add(key)\n out.push(spec)\n }\n return out\n}\n\n/** Every `new HttpError(status, \"message\")` in a handler region. */\nfunction extractErrors(region: string): ApiErrorSpec[] {\n const re = /\\bHttpError\\s*\\(\\s*(\\d{3})\\s*(?:,\\s*(?:([\"'`])((?:\\\\.|(?!\\2)[\\s\\S])*)\\2))?/g\n const out: ApiErrorSpec[] = []\n const seen = new Set<string>()\n let m: RegExpExecArray | null\n while ((m = re.exec(region))) {\n const message = m[3]?.replace(/\\\\(.)/g, \"$1\")\n const spec: ApiErrorSpec = { status: Number(m[1]), ...(message ? { message } : {}) }\n const key = JSON.stringify(spec)\n if (seen.has(key)) continue\n seen.add(key)\n out.push(spec)\n }\n return out\n}\n\n/** Query keys read through `searchParams.get/getAll/has(\"x\")`. */\nfunction extractQuery(region: string): string[] {\n const re = /searchParams\\s*\\.\\s*(?:get|getAll|has)\\s*\\(\\s*[\"'`]([^\"'`]+)[\"'`]/g\n const out = new Set<string>()\n let m: RegExpExecArray | null\n while ((m = re.exec(region))) out.add(m[1]!)\n return [...out]\n}\n\n/** The request body a handler reads, plus destructured keys when present. */\nfunction extractBody(region: string): ApiBodySpec | undefined {\n const read = region.match(/\\b(?:request|req)\\s*\\.\\s*(json|formData|text|arrayBuffer|blob)\\s*\\(/)\n if (!read) return undefined\n const method = read[1]!\n const format: ApiBodySpec[\"format\"] =\n method === \"json\" || method === \"formData\" || method === \"text\" ? method : \"binary\"\n\n const destructured = region.match(\n /(?:const|let|var)\\s*(\\{[\\s\\S]*?\\})\\s*=\\s*(?:await\\s+)?[\\w.]*\\.json\\s*\\(/,\n )\n const keys = format === \"json\" && destructured ? objectKeys(destructured[1]!) : undefined\n return { format, ...(keys ? { keys } : {}) }\n}\n\nfunction toParams(segments: Segment[]): RouteParam[] {\n const out: RouteParam[] = []\n for (const s of segments) {\n if (s.kind === \"static\") continue\n out.push({ name: s.name, kind: s.kind })\n }\n return out\n}\n\n/** Static spec of a page: its path params and its `definePage` metadata. */\nexport function extractPageSpec(page: PageRoute): PageSpec {\n return { params: toParams(page.segments), ...extractPageMeta(page.absFile) }\n}\n\n/** Static spec of an API route: path params and a per-method request/response sketch. */\nexport function extractApiSpec(api: ApiRoute): ApiSpec {\n const params = toParams(api.segments)\n let src: string\n try {\n src = stripComments(fs.readFileSync(api.absFile, \"utf8\"))\n } catch {\n return { params, methods: [] }\n }\n const regions = methodRegions(src)\n const methods = API_METHODS.filter((m) => regions.has(m)).map((method) => {\n const region = regions.get(method)!\n const body = extractBody(region)\n return {\n method,\n query: extractQuery(region),\n ...(body ? { body } : {}),\n responses: extractResponses(region),\n errors: extractErrors(region),\n }\n })\n return { params, methods }\n}\n"]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// @squadbase/vantage — generated build. Do not edit.
|
|
2
|
+
|
|
3
|
+
// src/core/constants.ts
|
|
4
|
+
var VANTAGE_DIR = ".vantage";
|
|
5
|
+
var SRC_DIR = "src";
|
|
6
|
+
var NON_ROUTE_DIRS = /* @__PURE__ */ new Set([
|
|
7
|
+
"components",
|
|
8
|
+
"hooks",
|
|
9
|
+
"lib",
|
|
10
|
+
"server",
|
|
11
|
+
"public",
|
|
12
|
+
"node_modules",
|
|
13
|
+
VANTAGE_DIR,
|
|
14
|
+
"dist"
|
|
15
|
+
]);
|
|
16
|
+
var SUSPICIOUS_ROUTE_DIRS = /* @__PURE__ */ new Set([
|
|
17
|
+
SRC_DIR,
|
|
18
|
+
"app",
|
|
19
|
+
"pages",
|
|
20
|
+
"routes",
|
|
21
|
+
"views",
|
|
22
|
+
"screens",
|
|
23
|
+
"features",
|
|
24
|
+
"containers",
|
|
25
|
+
"modules",
|
|
26
|
+
"layouts",
|
|
27
|
+
"utils",
|
|
28
|
+
"types",
|
|
29
|
+
"styles",
|
|
30
|
+
"assets",
|
|
31
|
+
"store",
|
|
32
|
+
"stores",
|
|
33
|
+
"context",
|
|
34
|
+
"contexts",
|
|
35
|
+
"providers",
|
|
36
|
+
"api",
|
|
37
|
+
"test",
|
|
38
|
+
"tests",
|
|
39
|
+
"__tests__"
|
|
40
|
+
]);
|
|
41
|
+
var PAGE_EXTENSIONS = [".tsx", ".jsx"];
|
|
42
|
+
var API_EXTENSIONS = [".ts", ".tsx", ".js"];
|
|
43
|
+
var RESERVED_PAGE_NAMES = {
|
|
44
|
+
layout: "_layout",
|
|
45
|
+
notFound: "_404",
|
|
46
|
+
error: "_error"
|
|
47
|
+
};
|
|
48
|
+
var API_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"];
|
|
49
|
+
var FORBIDDEN_FILES = [
|
|
50
|
+
{
|
|
51
|
+
pattern: /^vite\.config\.(ts|js|mjs|cjs|mts|cts)$/,
|
|
52
|
+
label: "Vite config",
|
|
53
|
+
remedy: "Vantage owns the Vite configuration. Remove this file."
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
pattern: /^tailwind\.config\.(ts|js|mjs|cjs)$/,
|
|
57
|
+
label: "Tailwind config",
|
|
58
|
+
remedy: "Customize theme tokens in styles.css instead."
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
pattern: /^postcss\.config\.(ts|js|mjs|cjs)$/,
|
|
62
|
+
label: "PostCSS config",
|
|
63
|
+
remedy: "Vantage manages PostCSS/Tailwind. Remove this file."
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
pattern: /^components\.json$/,
|
|
67
|
+
label: "shadcn components.json",
|
|
68
|
+
remedy: "Use `vantage add ui <name>` to copy UI source instead."
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
pattern: /^vantage\.config\.(ts|js|mjs|cjs)$/,
|
|
72
|
+
label: "Vantage config",
|
|
73
|
+
remedy: "v1 has no vantage.config. Configuration lives in file conventions."
|
|
74
|
+
}
|
|
75
|
+
];
|
|
76
|
+
var PUBLIC_ENV_PREFIX = "PUBLIC_";
|
|
77
|
+
var MANIFEST_SCHEMA_VERSION = 1;
|
|
78
|
+
|
|
79
|
+
export { API_EXTENSIONS, API_METHODS, FORBIDDEN_FILES, MANIFEST_SCHEMA_VERSION, NON_ROUTE_DIRS, PAGE_EXTENSIONS, PUBLIC_ENV_PREFIX, RESERVED_PAGE_NAMES, SRC_DIR, SUSPICIOUS_ROUTE_DIRS, VANTAGE_DIR };
|
|
80
|
+
//# sourceMappingURL=chunk-C4MQRWXS.js.map
|
|
81
|
+
//# sourceMappingURL=chunk-C4MQRWXS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/constants.ts"],"names":[],"mappings":";;;AAMO,IAAM,WAAA,GAAc;AASpB,IAAM,OAAA,GAAU;AAGhB,IAAM,cAAA,uBAAqB,GAAA,CAAI;AAAA,EACpC,YAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,cAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAC;AASM,IAAM,qBAAA,uBAA4B,GAAA,CAAI;AAAA,EAC3C,OAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAC;AAGM,IAAM,eAAA,GAAkB,CAAC,MAAA,EAAQ,MAAM;AAGvC,IAAM,cAAA,GAAiB,CAAC,KAAA,EAAO,MAAA,EAAQ,KAAK;AAG5C,IAAM,mBAAA,GAAsB;AAAA,EACjC,MAAA,EAAQ,SAAA;AAAA,EACR,QAAA,EAAU,MAAA;AAAA,EACV,KAAA,EAAO;AACT;AAGO,IAAM,cAAc,CAAC,KAAA,EAAO,QAAQ,KAAA,EAAO,OAAA,EAAS,UAAU,SAAS;AAOvE,IAAM,eAAA,GAAwE;AAAA,EACnF;AAAA,IACE,OAAA,EAAS,yCAAA;AAAA,IACT,KAAA,EAAO,aAAA;AAAA,IACP,MAAA,EAAQ;AAAA,GACV;AAAA,EACA;AAAA,IACE,OAAA,EAAS,qCAAA;AAAA,IACT,KAAA,EAAO,iBAAA;AAAA,IACP,MAAA,EAAQ;AAAA,GACV;AAAA,EACA;AAAA,IACE,OAAA,EAAS,oCAAA;AAAA,IACT,KAAA,EAAO,gBAAA;AAAA,IACP,MAAA,EAAQ;AAAA,GACV;AAAA,EACA;AAAA,IACE,OAAA,EAAS,oBAAA;AAAA,IACT,KAAA,EAAO,wBAAA;AAAA,IACP,MAAA,EAAQ;AAAA,GACV;AAAA,EACA;AAAA,IACE,OAAA,EAAS,oCAAA;AAAA,IACT,KAAA,EAAO,gBAAA;AAAA,IACP,MAAA,EAAQ;AAAA;AAEZ;AAGO,IAAM,iBAAA,GAAoB;AAG1B,IAAM,uBAAA,GAA0B","file":"chunk-C4MQRWXS.js","sourcesContent":["/**\n * Framework-wide constants: naming conventions and reserved paths.\n * These encode the \"convention over configuration\" contract from the design.\n */\n\n/** Directory that holds all generated, hidden artifacts. */\nexport const VANTAGE_DIR = \".vantage\"\n\n/**\n * Optional directory holding the app's client source. When it exists, it is the\n * one and only page-scan root; when it does not, pages live at the project root.\n * Both layouts are supported so a single-file app stays a single file, while an\n * app (or a coding agent) that reaches for the near-universal `src/` convention\n * gets routes that make sense instead of a `/src/...` prefix on every page.\n */\nexport const SRC_DIR = \"src\"\n\n/** Directories that are never scanned for pages. */\nexport const NON_ROUTE_DIRS = new Set([\n \"components\",\n \"hooks\",\n \"lib\",\n \"server\",\n \"public\",\n \"node_modules\",\n VANTAGE_DIR,\n \"dist\",\n])\n\n/**\n * Directory names that almost always mean \"framework scaffolding\", not \"a URL\n * segment\". Page scanning is a denylist (`NON_ROUTE_DIRS`), so any directory\n * not on it becomes part of the route path — `pages/sales.tsx` silently serves\n * `/pages/sales`. These names are still scanned (they may be deliberate), but\n * routes coming out of them raise `SUSPICIOUS_ROUTE_DIR`.\n */\nexport const SUSPICIOUS_ROUTE_DIRS = new Set([\n SRC_DIR,\n \"app\",\n \"pages\",\n \"routes\",\n \"views\",\n \"screens\",\n \"features\",\n \"containers\",\n \"modules\",\n \"layouts\",\n \"utils\",\n \"types\",\n \"styles\",\n \"assets\",\n \"store\",\n \"stores\",\n \"context\",\n \"contexts\",\n \"providers\",\n \"api\",\n \"test\",\n \"tests\",\n \"__tests__\",\n])\n\n/** File extensions treated as page modules. */\nexport const PAGE_EXTENSIONS = [\".tsx\", \".jsx\"]\n\n/** File extensions treated as server API modules. */\nexport const API_EXTENSIONS = [\".ts\", \".tsx\", \".js\"]\n\n/** Reserved page filenames (without extension). */\nexport const RESERVED_PAGE_NAMES = {\n layout: \"_layout\",\n notFound: \"_404\",\n error: \"_error\",\n} as const\n\n/** HTTP methods that an API module may export. */\nexport const API_METHODS = [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"] as const\nexport type ApiMethod = (typeof API_METHODS)[number]\n\n/**\n * Files that must not exist in a Vantage project. Their presence means the\n * user is trying to escape the managed stack, which v1 forbids.\n */\nexport const FORBIDDEN_FILES: { pattern: RegExp; label: string; remedy: string }[] = [\n {\n pattern: /^vite\\.config\\.(ts|js|mjs|cjs|mts|cts)$/,\n label: \"Vite config\",\n remedy: \"Vantage owns the Vite configuration. Remove this file.\",\n },\n {\n pattern: /^tailwind\\.config\\.(ts|js|mjs|cjs)$/,\n label: \"Tailwind config\",\n remedy: \"Customize theme tokens in styles.css instead.\",\n },\n {\n pattern: /^postcss\\.config\\.(ts|js|mjs|cjs)$/,\n label: \"PostCSS config\",\n remedy: \"Vantage manages PostCSS/Tailwind. Remove this file.\",\n },\n {\n pattern: /^components\\.json$/,\n label: \"shadcn components.json\",\n remedy: \"Use `vantage add ui <name>` to copy UI source instead.\",\n },\n {\n pattern: /^vantage\\.config\\.(ts|js|mjs|cjs)$/,\n label: \"Vantage config\",\n remedy: \"v1 has no vantage.config. Configuration lives in file conventions.\",\n },\n]\n\n/** Public env var prefix exposed to the client bundle. */\nexport const PUBLIC_ENV_PREFIX = \"PUBLIC_\"\n\n/** Manifest schema version emitted into build output. */\nexport const MANIFEST_SCHEMA_VERSION = 1\n"]}
|