forge-cc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.forge.json +5 -0
- package/AGENTS.md +42 -0
- package/README.md +283 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +148 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/loader.d.ts +2 -0
- package/dist/config/loader.js +44 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +57 -0
- package/dist/config/schema.js +15 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/gates/index.d.ts +11 -0
- package/dist/gates/index.js +106 -0
- package/dist/gates/index.js.map +1 -0
- package/dist/gates/lint-gate.d.ts +2 -0
- package/dist/gates/lint-gate.js +66 -0
- package/dist/gates/lint-gate.js.map +1 -0
- package/dist/gates/prd-gate.d.ts +7 -0
- package/dist/gates/prd-gate.js +193 -0
- package/dist/gates/prd-gate.js.map +1 -0
- package/dist/gates/runtime-gate.d.ts +5 -0
- package/dist/gates/runtime-gate.js +99 -0
- package/dist/gates/runtime-gate.js.map +1 -0
- package/dist/gates/tests-gate.d.ts +2 -0
- package/dist/gates/tests-gate.js +116 -0
- package/dist/gates/tests-gate.js.map +1 -0
- package/dist/gates/types-gate.d.ts +2 -0
- package/dist/gates/types-gate.js +59 -0
- package/dist/gates/types-gate.js.map +1 -0
- package/dist/gates/visual-gate.d.ts +6 -0
- package/dist/gates/visual-gate.js +118 -0
- package/dist/gates/visual-gate.js.map +1 -0
- package/dist/go/auto-chain.d.ts +107 -0
- package/dist/go/auto-chain.js +303 -0
- package/dist/go/auto-chain.js.map +1 -0
- package/dist/go/executor.d.ts +130 -0
- package/dist/go/executor.js +409 -0
- package/dist/go/executor.js.map +1 -0
- package/dist/go/finalize.d.ts +58 -0
- package/dist/go/finalize.js +200 -0
- package/dist/go/finalize.js.map +1 -0
- package/dist/go/linear-sync.d.ts +75 -0
- package/dist/go/linear-sync.js +239 -0
- package/dist/go/linear-sync.js.map +1 -0
- package/dist/go/verify-loop.d.ts +47 -0
- package/dist/go/verify-loop.js +172 -0
- package/dist/go/verify-loop.js.map +1 -0
- package/dist/hooks/pre-commit.d.ts +5 -0
- package/dist/hooks/pre-commit.js +69 -0
- package/dist/hooks/pre-commit.js.map +1 -0
- package/dist/linear/client.d.ts +108 -0
- package/dist/linear/client.js +388 -0
- package/dist/linear/client.js.map +1 -0
- package/dist/linear/issues.d.ts +20 -0
- package/dist/linear/issues.js +39 -0
- package/dist/linear/issues.js.map +1 -0
- package/dist/linear/milestones.d.ts +11 -0
- package/dist/linear/milestones.js +32 -0
- package/dist/linear/milestones.js.map +1 -0
- package/dist/linear/projects.d.ts +16 -0
- package/dist/linear/projects.js +50 -0
- package/dist/linear/projects.js.map +1 -0
- package/dist/reporter/human.d.ts +2 -0
- package/dist/reporter/human.js +63 -0
- package/dist/reporter/human.js.map +1 -0
- package/dist/reporter/json.d.ts +2 -0
- package/dist/reporter/json.js +4 -0
- package/dist/reporter/json.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +109 -0
- package/dist/server.js.map +1 -0
- package/dist/spec/generator.d.ts +14 -0
- package/dist/spec/generator.js +206 -0
- package/dist/spec/generator.js.map +1 -0
- package/dist/spec/interview.d.ts +104 -0
- package/dist/spec/interview.js +342 -0
- package/dist/spec/interview.js.map +1 -0
- package/dist/spec/linear-sync.d.ts +48 -0
- package/dist/spec/linear-sync.js +125 -0
- package/dist/spec/linear-sync.js.map +1 -0
- package/dist/spec/scanner.d.ts +45 -0
- package/dist/spec/scanner.js +473 -0
- package/dist/spec/scanner.js.map +1 -0
- package/dist/spec/templates.d.ts +345 -0
- package/dist/spec/templates.js +86 -0
- package/dist/spec/templates.js.map +1 -0
- package/dist/state/reader.d.ts +29 -0
- package/dist/state/reader.js +116 -0
- package/dist/state/reader.js.map +1 -0
- package/dist/state/writer.d.ts +60 -0
- package/dist/state/writer.js +222 -0
- package/dist/state/writer.js.map +1 -0
- package/dist/types.d.ts +64 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/browser.d.ts +10 -0
- package/dist/utils/browser.js +89 -0
- package/dist/utils/browser.js.map +1 -0
- package/hooks/pre-commit-verify.js +103 -0
- package/package.json +68 -0
- package/skills/README.md +33 -0
- package/skills/forge-go.md +332 -0
- package/skills/forge-spec.md +251 -0
- package/skills/forge-triage.md +133 -0
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
import { readdir, readFile, stat } from "node:fs/promises";
|
|
2
|
+
import { join, relative, extname, basename } from "node:path";
|
|
3
|
+
// ── Helpers ────────────────────────────────────────────────────────────────
|
|
4
|
+
const IGNORE_DIRS = new Set([
|
|
5
|
+
"node_modules", ".git", "dist", "build", ".next", ".nuxt",
|
|
6
|
+
".svelte-kit", ".output", "coverage", ".turbo", ".cache",
|
|
7
|
+
]);
|
|
8
|
+
async function exists(p) {
|
|
9
|
+
try {
|
|
10
|
+
await stat(p);
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function readJson(p) {
|
|
18
|
+
try {
|
|
19
|
+
const raw = await readFile(p, "utf-8");
|
|
20
|
+
return JSON.parse(raw);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function walkDir(dir, base, maxDepth, depth = 0) {
|
|
27
|
+
if (depth > maxDepth)
|
|
28
|
+
return [];
|
|
29
|
+
let entries;
|
|
30
|
+
try {
|
|
31
|
+
const items = await readdir(dir, { withFileTypes: true });
|
|
32
|
+
entries = [];
|
|
33
|
+
for (const item of items) {
|
|
34
|
+
const full = join(dir, item.name);
|
|
35
|
+
const rel = relative(base, full);
|
|
36
|
+
if (item.isDirectory()) {
|
|
37
|
+
if (!IGNORE_DIRS.has(item.name)) {
|
|
38
|
+
entries.push(rel + "/");
|
|
39
|
+
const sub = await walkDir(full, base, maxDepth, depth + 1);
|
|
40
|
+
entries.push(...sub);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
entries.push(rel);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
entries = [];
|
|
50
|
+
}
|
|
51
|
+
return entries;
|
|
52
|
+
}
|
|
53
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".vue", ".svelte"]);
|
|
54
|
+
function isCodeFile(file) {
|
|
55
|
+
return CODE_EXTS.has(extname(file));
|
|
56
|
+
}
|
|
57
|
+
// ── Structure Scan ─────────────────────────────────────────────────────────
|
|
58
|
+
const FRAMEWORK_MARKERS = {
|
|
59
|
+
next: "Next.js",
|
|
60
|
+
nuxt: "Nuxt",
|
|
61
|
+
"react-dom": "React",
|
|
62
|
+
vue: "Vue",
|
|
63
|
+
svelte: "Svelte",
|
|
64
|
+
"@sveltejs/kit": "SvelteKit",
|
|
65
|
+
angular: "Angular",
|
|
66
|
+
"@angular/core": "Angular",
|
|
67
|
+
express: "Express",
|
|
68
|
+
fastify: "Fastify",
|
|
69
|
+
hono: "Hono",
|
|
70
|
+
koa: "Koa",
|
|
71
|
+
"react-native": "React Native",
|
|
72
|
+
expo: "Expo",
|
|
73
|
+
electron: "Electron",
|
|
74
|
+
astro: "Astro",
|
|
75
|
+
remix: "Remix",
|
|
76
|
+
gatsby: "Gatsby",
|
|
77
|
+
"@nestjs/core": "NestJS",
|
|
78
|
+
};
|
|
79
|
+
const CONFIG_FILES = [
|
|
80
|
+
"tsconfig.json", "jsconfig.json",
|
|
81
|
+
"tailwind.config.ts", "tailwind.config.js", "tailwind.config.mjs",
|
|
82
|
+
"postcss.config.js", "postcss.config.mjs",
|
|
83
|
+
"vite.config.ts", "vite.config.js",
|
|
84
|
+
"next.config.ts", "next.config.js", "next.config.mjs",
|
|
85
|
+
"nuxt.config.ts",
|
|
86
|
+
"svelte.config.js",
|
|
87
|
+
"astro.config.mjs",
|
|
88
|
+
".env", ".env.local", ".env.example",
|
|
89
|
+
"docker-compose.yml", "Dockerfile",
|
|
90
|
+
".eslintrc.json", ".eslintrc.js", "eslint.config.js", "eslint.config.mjs",
|
|
91
|
+
"biome.json", "biome.jsonc",
|
|
92
|
+
"vitest.config.ts", "jest.config.ts", "jest.config.js",
|
|
93
|
+
"playwright.config.ts",
|
|
94
|
+
".prettierrc", ".prettierrc.json",
|
|
95
|
+
"drizzle.config.ts", "prisma/schema.prisma",
|
|
96
|
+
];
|
|
97
|
+
const ENTRY_CANDIDATES = [
|
|
98
|
+
"src/index.ts", "src/index.tsx", "src/main.ts", "src/main.tsx",
|
|
99
|
+
"src/app.ts", "src/app.tsx", "src/server.ts",
|
|
100
|
+
"index.ts", "index.js", "app.ts", "server.ts",
|
|
101
|
+
"src/index.js", "src/main.js", "src/app.js",
|
|
102
|
+
];
|
|
103
|
+
export async function scanStructure(projectDir) {
|
|
104
|
+
const pkg = await readJson(join(projectDir, "package.json"));
|
|
105
|
+
// Project name
|
|
106
|
+
const projectName = pkg?.name || basename(projectDir);
|
|
107
|
+
// Detect frameworks from dependencies
|
|
108
|
+
const allDeps = {
|
|
109
|
+
...(typeof pkg?.dependencies === "object" ? pkg.dependencies : {}),
|
|
110
|
+
...(typeof pkg?.devDependencies === "object" ? pkg.devDependencies : {}),
|
|
111
|
+
};
|
|
112
|
+
const frameworks = [];
|
|
113
|
+
for (const [dep, label] of Object.entries(FRAMEWORK_MARKERS)) {
|
|
114
|
+
if (dep in allDeps) {
|
|
115
|
+
frameworks.push(label);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Deduplicate (e.g. React appears via react-dom and next)
|
|
119
|
+
const uniqueFrameworks = [...new Set(frameworks)];
|
|
120
|
+
// Language
|
|
121
|
+
const hasTs = await exists(join(projectDir, "tsconfig.json"));
|
|
122
|
+
const language = hasTs
|
|
123
|
+
? "typescript"
|
|
124
|
+
: pkg ? "javascript" : "unknown";
|
|
125
|
+
// Package manager
|
|
126
|
+
let packageManager = "unknown";
|
|
127
|
+
if (await exists(join(projectDir, "bun.lockb")) || await exists(join(projectDir, "bun.lock"))) {
|
|
128
|
+
packageManager = "bun";
|
|
129
|
+
}
|
|
130
|
+
else if (await exists(join(projectDir, "pnpm-lock.yaml"))) {
|
|
131
|
+
packageManager = "pnpm";
|
|
132
|
+
}
|
|
133
|
+
else if (await exists(join(projectDir, "yarn.lock"))) {
|
|
134
|
+
packageManager = "yarn";
|
|
135
|
+
}
|
|
136
|
+
else if (await exists(join(projectDir, "package-lock.json"))) {
|
|
137
|
+
packageManager = "npm";
|
|
138
|
+
}
|
|
139
|
+
// Config files present
|
|
140
|
+
const configFiles = [];
|
|
141
|
+
for (const cf of CONFIG_FILES) {
|
|
142
|
+
if (await exists(join(projectDir, cf))) {
|
|
143
|
+
configFiles.push(cf);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Top-level directories
|
|
147
|
+
const topLevelDirs = [];
|
|
148
|
+
try {
|
|
149
|
+
const items = await readdir(projectDir, { withFileTypes: true });
|
|
150
|
+
for (const item of items) {
|
|
151
|
+
if (item.isDirectory() && !IGNORE_DIRS.has(item.name) && !item.name.startsWith(".")) {
|
|
152
|
+
topLevelDirs.push(item.name);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch { /* empty */ }
|
|
157
|
+
// Entry points
|
|
158
|
+
const entryPoints = [];
|
|
159
|
+
for (const ep of ENTRY_CANDIDATES) {
|
|
160
|
+
if (await exists(join(projectDir, ep))) {
|
|
161
|
+
entryPoints.push(ep);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
projectName,
|
|
166
|
+
frameworks: uniqueFrameworks,
|
|
167
|
+
language,
|
|
168
|
+
packageManager,
|
|
169
|
+
configFiles,
|
|
170
|
+
topLevelDirs,
|
|
171
|
+
entryPoints,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
// ── Routes / UI Scan ───────────────────────────────────────────────────────
|
|
175
|
+
const ROUTE_DIRS = [
|
|
176
|
+
{ dir: "app", framework: "Next.js (App Router)" },
|
|
177
|
+
{ dir: "pages", framework: "Next.js (Pages Router)" },
|
|
178
|
+
{ dir: "src/app", framework: "Next.js (App Router)" },
|
|
179
|
+
{ dir: "src/pages", framework: "Next.js (Pages Router)" },
|
|
180
|
+
{ dir: "src/routes", framework: "SvelteKit/Remix" },
|
|
181
|
+
{ dir: "routes", framework: "Remix" },
|
|
182
|
+
{ dir: "src/views", framework: "Vue" },
|
|
183
|
+
{ dir: "src/screens", framework: "React Native" },
|
|
184
|
+
];
|
|
185
|
+
const COMPONENT_DIRS = [
|
|
186
|
+
"src/components", "components", "src/ui", "ui",
|
|
187
|
+
"src/features", "src/modules",
|
|
188
|
+
];
|
|
189
|
+
function classifyRouteFile(filePath) {
|
|
190
|
+
const name = basename(filePath).toLowerCase();
|
|
191
|
+
if (name.startsWith("layout"))
|
|
192
|
+
return "layout";
|
|
193
|
+
if (name.startsWith("middleware") || name === "_middleware.ts" || name === "_middleware.js")
|
|
194
|
+
return "middleware";
|
|
195
|
+
if (filePath.includes("/api/") || filePath.includes("\\api\\"))
|
|
196
|
+
return "api";
|
|
197
|
+
return "page";
|
|
198
|
+
}
|
|
199
|
+
function fileToRoutePath(file, routeDir) {
|
|
200
|
+
let route = file
|
|
201
|
+
.replace(routeDir, "")
|
|
202
|
+
.replace(/\\/g, "/");
|
|
203
|
+
// Strip file extension
|
|
204
|
+
route = route.replace(/\.(ts|tsx|js|jsx|vue|svelte)$/, "");
|
|
205
|
+
// Strip index suffix
|
|
206
|
+
route = route.replace(/\/index$/, "") || "/";
|
|
207
|
+
// Strip Next.js page.tsx pattern
|
|
208
|
+
route = route.replace(/\/page$/, "") || "/";
|
|
209
|
+
return route;
|
|
210
|
+
}
|
|
211
|
+
export async function scanRoutes(projectDir) {
|
|
212
|
+
let framework = null;
|
|
213
|
+
let routeDir = null;
|
|
214
|
+
const routes = [];
|
|
215
|
+
// Find the route directory
|
|
216
|
+
for (const candidate of ROUTE_DIRS) {
|
|
217
|
+
const fullPath = join(projectDir, candidate.dir);
|
|
218
|
+
if (await exists(fullPath)) {
|
|
219
|
+
framework = candidate.framework;
|
|
220
|
+
routeDir = candidate.dir;
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Scan routes if found
|
|
225
|
+
if (routeDir) {
|
|
226
|
+
const fullRouteDir = join(projectDir, routeDir);
|
|
227
|
+
const files = await walkDir(fullRouteDir, fullRouteDir, 5);
|
|
228
|
+
for (const file of files) {
|
|
229
|
+
if (file.endsWith("/"))
|
|
230
|
+
continue; // skip directories
|
|
231
|
+
if (!isCodeFile(file))
|
|
232
|
+
continue;
|
|
233
|
+
const name = basename(file).toLowerCase();
|
|
234
|
+
// Skip test files and non-route utilities
|
|
235
|
+
if (name.includes(".test.") || name.includes(".spec.") || name.startsWith("_"))
|
|
236
|
+
continue;
|
|
237
|
+
const type = classifyRouteFile(file);
|
|
238
|
+
routes.push({
|
|
239
|
+
path: fileToRoutePath(file, ""),
|
|
240
|
+
file: join(routeDir, file),
|
|
241
|
+
type,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// Scan component directories
|
|
246
|
+
const components = [];
|
|
247
|
+
for (const compDir of COMPONENT_DIRS) {
|
|
248
|
+
const fullPath = join(projectDir, compDir);
|
|
249
|
+
if (!(await exists(fullPath)))
|
|
250
|
+
continue;
|
|
251
|
+
const files = await walkDir(fullPath, fullPath, 3);
|
|
252
|
+
for (const file of files) {
|
|
253
|
+
if (file.endsWith("/"))
|
|
254
|
+
continue;
|
|
255
|
+
if (!isCodeFile(file))
|
|
256
|
+
continue;
|
|
257
|
+
const name = basename(file).toLowerCase();
|
|
258
|
+
if (name.includes(".test.") || name.includes(".spec."))
|
|
259
|
+
continue;
|
|
260
|
+
components.push(join(compDir, file));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return { framework, routeDir, routes, components };
|
|
264
|
+
}
|
|
265
|
+
// ── Data / APIs Scan ───────────────────────────────────────────────────────
|
|
266
|
+
const API_DIRS = [
|
|
267
|
+
"src/api", "api", "src/server", "server",
|
|
268
|
+
"src/controllers", "controllers",
|
|
269
|
+
"src/handlers", "handlers",
|
|
270
|
+
"app/api", "pages/api", "src/app/api", "src/pages/api",
|
|
271
|
+
];
|
|
272
|
+
const HTTP_METHOD_RE = /\.(get|post|put|patch|delete|all)\s*\(/gi;
|
|
273
|
+
const ROUTE_STRING_RE = /['"`](\/[a-zA-Z0-9/:_\-.*[\]{}]*?)['"`]/g;
|
|
274
|
+
async function extractAPIEndpoints(projectDir, filePath) {
|
|
275
|
+
const endpoints = [];
|
|
276
|
+
try {
|
|
277
|
+
const content = await readFile(join(projectDir, filePath), "utf-8");
|
|
278
|
+
// Check for HTTP method patterns (Express/Hono/Fastify style)
|
|
279
|
+
let match;
|
|
280
|
+
const methodRe = new RegExp(HTTP_METHOD_RE.source, "gi");
|
|
281
|
+
while ((match = methodRe.exec(content)) !== null) {
|
|
282
|
+
const method = match[1].toUpperCase();
|
|
283
|
+
// Try to find route string near this match
|
|
284
|
+
const nearby = content.slice(Math.max(0, match.index - 100), match.index + 200);
|
|
285
|
+
const routeMatch = ROUTE_STRING_RE.exec(nearby);
|
|
286
|
+
ROUTE_STRING_RE.lastIndex = 0;
|
|
287
|
+
endpoints.push({
|
|
288
|
+
method,
|
|
289
|
+
path: routeMatch ? routeMatch[1] : "(dynamic)",
|
|
290
|
+
file: filePath,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
// Next.js API route convention: file path IS the route
|
|
294
|
+
if (filePath.includes("/api/")) {
|
|
295
|
+
const routePath = "/" + filePath
|
|
296
|
+
.replace(/.*\/api\//, "api/")
|
|
297
|
+
.replace(/\.(ts|tsx|js|jsx)$/, "")
|
|
298
|
+
.replace(/\/route$/, "")
|
|
299
|
+
.replace(/\/index$/, "");
|
|
300
|
+
// Check for exported HTTP methods (Next.js App Router)
|
|
301
|
+
const exportedMethods = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
302
|
+
for (const m of exportedMethods) {
|
|
303
|
+
if (content.includes(`export function ${m}`) || content.includes(`export async function ${m}`)) {
|
|
304
|
+
endpoints.push({ method: m, path: routePath, file: filePath });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// If no explicit methods found, add a generic entry
|
|
308
|
+
if (endpoints.filter(e => e.file === filePath).length === 0) {
|
|
309
|
+
endpoints.push({ method: "ANY", path: routePath, file: filePath });
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch { /* unreadable file */ }
|
|
314
|
+
return endpoints;
|
|
315
|
+
}
|
|
316
|
+
const PRISMA_MODEL_RE = /^model\s+(\w+)/gm;
|
|
317
|
+
const DRIZZLE_TABLE_RE = /export\s+const\s+(\w+)\s*=\s*(?:pgTable|mysqlTable|sqliteTable)\(/g;
|
|
318
|
+
const MONGOOSE_MODEL_RE = /mongoose\.model\s*[<(]\s*['"`]?(\w+)/g;
|
|
319
|
+
async function extractDataModels(projectDir) {
|
|
320
|
+
const models = [];
|
|
321
|
+
// Prisma
|
|
322
|
+
const prismaPath = join(projectDir, "prisma/schema.prisma");
|
|
323
|
+
try {
|
|
324
|
+
const content = await readFile(prismaPath, "utf-8");
|
|
325
|
+
let match;
|
|
326
|
+
const re = new RegExp(PRISMA_MODEL_RE.source, "gm");
|
|
327
|
+
while ((match = re.exec(content)) !== null) {
|
|
328
|
+
models.push({ name: match[1], file: "prisma/schema.prisma", source: "prisma" });
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
catch { /* no prisma */ }
|
|
332
|
+
// Drizzle — look for schema files
|
|
333
|
+
const drizzleCandidates = [
|
|
334
|
+
"src/db/schema.ts", "src/schema.ts", "drizzle/schema.ts",
|
|
335
|
+
"src/db/schema/index.ts", "src/lib/db/schema.ts",
|
|
336
|
+
];
|
|
337
|
+
for (const candidate of drizzleCandidates) {
|
|
338
|
+
try {
|
|
339
|
+
const content = await readFile(join(projectDir, candidate), "utf-8");
|
|
340
|
+
let match;
|
|
341
|
+
const re = new RegExp(DRIZZLE_TABLE_RE.source, "g");
|
|
342
|
+
while ((match = re.exec(content)) !== null) {
|
|
343
|
+
models.push({ name: match[1], file: candidate, source: "drizzle" });
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
catch { /* not found */ }
|
|
347
|
+
}
|
|
348
|
+
// Mongoose — look for model files
|
|
349
|
+
const mongooseDirs = ["src/models", "models", "src/db/models"];
|
|
350
|
+
for (const dir of mongooseDirs) {
|
|
351
|
+
try {
|
|
352
|
+
const files = await readdir(join(projectDir, dir));
|
|
353
|
+
for (const file of files) {
|
|
354
|
+
if (!isCodeFile(file))
|
|
355
|
+
continue;
|
|
356
|
+
const content = await readFile(join(projectDir, dir, file), "utf-8");
|
|
357
|
+
let match;
|
|
358
|
+
const re = new RegExp(MONGOOSE_MODEL_RE.source, "g");
|
|
359
|
+
while ((match = re.exec(content)) !== null) {
|
|
360
|
+
models.push({ name: match[1], file: join(dir, file), source: "mongoose" });
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
catch { /* not found */ }
|
|
365
|
+
}
|
|
366
|
+
return models;
|
|
367
|
+
}
|
|
368
|
+
const EXTERNAL_SERVICE_MARKERS = {
|
|
369
|
+
stripe: "Stripe",
|
|
370
|
+
"@stripe/stripe-js": "Stripe",
|
|
371
|
+
"@supabase/supabase-js": "Supabase",
|
|
372
|
+
firebase: "Firebase",
|
|
373
|
+
"firebase-admin": "Firebase Admin",
|
|
374
|
+
"@aws-sdk": "AWS",
|
|
375
|
+
"@azure": "Azure",
|
|
376
|
+
"@google-cloud": "Google Cloud",
|
|
377
|
+
"@sendgrid/mail": "SendGrid",
|
|
378
|
+
resend: "Resend",
|
|
379
|
+
"@clerk/nextjs": "Clerk Auth",
|
|
380
|
+
"@auth/core": "Auth.js",
|
|
381
|
+
"next-auth": "NextAuth",
|
|
382
|
+
"@lucia-auth/core": "Lucia Auth",
|
|
383
|
+
"@upstash/redis": "Upstash Redis",
|
|
384
|
+
ioredis: "Redis",
|
|
385
|
+
"@sentry/node": "Sentry",
|
|
386
|
+
posthog: "PostHog",
|
|
387
|
+
"@vercel/analytics": "Vercel Analytics",
|
|
388
|
+
openai: "OpenAI",
|
|
389
|
+
"@anthropic-ai/sdk": "Anthropic",
|
|
390
|
+
"@pinecone-database/pinecone": "Pinecone",
|
|
391
|
+
"@linear/sdk": "Linear",
|
|
392
|
+
};
|
|
393
|
+
const DB_TYPE_MARKERS = {
|
|
394
|
+
"@prisma/client": "PostgreSQL (Prisma)",
|
|
395
|
+
pg: "PostgreSQL",
|
|
396
|
+
mysql2: "MySQL",
|
|
397
|
+
"better-sqlite3": "SQLite",
|
|
398
|
+
"@libsql/client": "SQLite (Turso)",
|
|
399
|
+
mongoose: "MongoDB",
|
|
400
|
+
mongodb: "MongoDB",
|
|
401
|
+
"@neondatabase/serverless": "PostgreSQL (Neon)",
|
|
402
|
+
"@planetscale/database": "MySQL (PlanetScale)",
|
|
403
|
+
};
|
|
404
|
+
export async function scanDataAPIs(projectDir) {
|
|
405
|
+
const pkg = await readJson(join(projectDir, "package.json"));
|
|
406
|
+
const allDeps = {
|
|
407
|
+
...(typeof pkg?.dependencies === "object" ? pkg.dependencies : {}),
|
|
408
|
+
...(typeof pkg?.devDependencies === "object" ? pkg.devDependencies : {}),
|
|
409
|
+
};
|
|
410
|
+
// External services
|
|
411
|
+
const externalServices = [];
|
|
412
|
+
for (const [dep, label] of Object.entries(EXTERNAL_SERVICE_MARKERS)) {
|
|
413
|
+
const found = dep.startsWith("@")
|
|
414
|
+
? Object.keys(allDeps).some(d => d.startsWith(dep))
|
|
415
|
+
: dep in allDeps;
|
|
416
|
+
if (found) {
|
|
417
|
+
externalServices.push(label);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
// Database type
|
|
421
|
+
let databaseType = null;
|
|
422
|
+
for (const [dep, label] of Object.entries(DB_TYPE_MARKERS)) {
|
|
423
|
+
if (dep in allDeps) {
|
|
424
|
+
databaseType = label;
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
// API endpoints
|
|
429
|
+
const apiEndpoints = [];
|
|
430
|
+
for (const apiDir of API_DIRS) {
|
|
431
|
+
const fullPath = join(projectDir, apiDir);
|
|
432
|
+
if (!(await exists(fullPath)))
|
|
433
|
+
continue;
|
|
434
|
+
const files = await walkDir(fullPath, fullPath, 4);
|
|
435
|
+
for (const file of files) {
|
|
436
|
+
if (file.endsWith("/"))
|
|
437
|
+
continue;
|
|
438
|
+
if (!isCodeFile(file))
|
|
439
|
+
continue;
|
|
440
|
+
const name = basename(file).toLowerCase();
|
|
441
|
+
if (name.includes(".test.") || name.includes(".spec."))
|
|
442
|
+
continue;
|
|
443
|
+
const eps = await extractAPIEndpoints(projectDir, join(apiDir, file));
|
|
444
|
+
apiEndpoints.push(...eps);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
// Also check for standalone server files
|
|
448
|
+
const serverFiles = ["src/server.ts", "server.ts", "src/app.ts", "app.ts", "src/index.ts"];
|
|
449
|
+
for (const sf of serverFiles) {
|
|
450
|
+
if (await exists(join(projectDir, sf))) {
|
|
451
|
+
const eps = await extractAPIEndpoints(projectDir, sf);
|
|
452
|
+
apiEndpoints.push(...eps);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
// Data models
|
|
456
|
+
const dataModels = await extractDataModels(projectDir);
|
|
457
|
+
return {
|
|
458
|
+
apiEndpoints,
|
|
459
|
+
dataModels,
|
|
460
|
+
externalServices: [...new Set(externalServices)],
|
|
461
|
+
databaseType,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
// ── Combined Scan ──────────────────────────────────────────────────────────
|
|
465
|
+
export async function scanAll(projectDir) {
|
|
466
|
+
const [structure, routes, dataAPIs] = await Promise.all([
|
|
467
|
+
scanStructure(projectDir),
|
|
468
|
+
scanRoutes(projectDir),
|
|
469
|
+
scanDataAPIs(projectDir),
|
|
470
|
+
]);
|
|
471
|
+
return { structure, routes, dataAPIs };
|
|
472
|
+
}
|
|
473
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/spec/scanner.ts"],"names":[],"mappings":"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"}
|