@homenshum/convex-mcp-nodebench 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/README.md +137 -0
- package/dist/__tests__/tools.test.d.ts +1 -0
- package/dist/__tests__/tools.test.js +267 -0
- package/dist/__tests__/tools.test.js.map +1 -0
- package/dist/db.d.ts +10 -0
- package/dist/db.js +125 -0
- package/dist/db.js.map +1 -0
- package/dist/gotchaSeed.d.ts +126 -0
- package/dist/gotchaSeed.js +147 -0
- package/dist/gotchaSeed.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +118 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/componentTools.d.ts +2 -0
- package/dist/tools/componentTools.js +131 -0
- package/dist/tools/componentTools.js.map +1 -0
- package/dist/tools/cronTools.d.ts +2 -0
- package/dist/tools/cronTools.js +142 -0
- package/dist/tools/cronTools.js.map +1 -0
- package/dist/tools/deploymentTools.d.ts +2 -0
- package/dist/tools/deploymentTools.js +222 -0
- package/dist/tools/deploymentTools.js.map +1 -0
- package/dist/tools/functionTools.d.ts +2 -0
- package/dist/tools/functionTools.js +293 -0
- package/dist/tools/functionTools.js.map +1 -0
- package/dist/tools/integrationBridgeTools.d.ts +2 -0
- package/dist/tools/integrationBridgeTools.js +294 -0
- package/dist/tools/integrationBridgeTools.js.map +1 -0
- package/dist/tools/learningTools.d.ts +2 -0
- package/dist/tools/learningTools.js +155 -0
- package/dist/tools/learningTools.js.map +1 -0
- package/dist/tools/methodologyTools.d.ts +2 -0
- package/dist/tools/methodologyTools.js +163 -0
- package/dist/tools/methodologyTools.js.map +1 -0
- package/dist/tools/schemaTools.d.ts +2 -0
- package/dist/tools/schemaTools.js +346 -0
- package/dist/tools/schemaTools.js.map +1 -0
- package/dist/tools/toolRegistry.d.ts +5 -0
- package/dist/tools/toolRegistry.js +308 -0
- package/dist/tools/toolRegistry.js.map +1 -0
- package/dist/types.d.ts +44 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { readFileSync, existsSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { getDb, genId } from "../db.js";
|
|
4
|
+
import { getQuickRef } from "./toolRegistry.js";
|
|
5
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
6
|
+
function collectTsFiles(dir) {
|
|
7
|
+
const results = [];
|
|
8
|
+
if (!existsSync(dir))
|
|
9
|
+
return results;
|
|
10
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
11
|
+
for (const entry of entries) {
|
|
12
|
+
const full = join(dir, entry.name);
|
|
13
|
+
if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== "_generated") {
|
|
14
|
+
results.push(...collectTsFiles(full));
|
|
15
|
+
}
|
|
16
|
+
else if (entry.isFile() && entry.name.endsWith(".ts")) {
|
|
17
|
+
results.push(full);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return results;
|
|
21
|
+
}
|
|
22
|
+
function findConvexDir(projectDir) {
|
|
23
|
+
const candidates = [join(projectDir, "convex"), join(projectDir, "src", "convex")];
|
|
24
|
+
for (const c of candidates) {
|
|
25
|
+
if (existsSync(c))
|
|
26
|
+
return c;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function extractFunctions(convexDir) {
|
|
31
|
+
const files = collectTsFiles(convexDir);
|
|
32
|
+
const functions = [];
|
|
33
|
+
const funcTypes = [
|
|
34
|
+
"query", "internalQuery",
|
|
35
|
+
"mutation", "internalMutation",
|
|
36
|
+
"action", "internalAction",
|
|
37
|
+
"httpAction",
|
|
38
|
+
];
|
|
39
|
+
for (const filePath of files) {
|
|
40
|
+
const content = readFileSync(filePath, "utf-8");
|
|
41
|
+
const relativePath = filePath.replace(convexDir, "").replace(/^[\\/]/, "");
|
|
42
|
+
const lines = content.split("\n");
|
|
43
|
+
for (let i = 0; i < lines.length; i++) {
|
|
44
|
+
const line = lines[i];
|
|
45
|
+
for (const ft of funcTypes) {
|
|
46
|
+
// Match: export const myFunc = query({ or export default mutation({
|
|
47
|
+
const exportPattern = new RegExp(`export\\s+(?:const\\s+(\\w+)\\s*=|default)\\s+${ft}\\s*\\(`);
|
|
48
|
+
const match = line.match(exportPattern);
|
|
49
|
+
if (match) {
|
|
50
|
+
const funcName = match[1] || "default";
|
|
51
|
+
// Look ahead for args/returns/handler in the next ~20 lines
|
|
52
|
+
const chunk = lines.slice(i, Math.min(i + 25, lines.length)).join("\n");
|
|
53
|
+
functions.push({
|
|
54
|
+
name: funcName,
|
|
55
|
+
type: ft,
|
|
56
|
+
isInternal: ft.startsWith("internal"),
|
|
57
|
+
filePath,
|
|
58
|
+
relativePath,
|
|
59
|
+
line: i + 1,
|
|
60
|
+
hasArgs: /args\s*:\s*[\{\v]/.test(chunk) || /args\s*:\s*v\./.test(chunk),
|
|
61
|
+
hasReturns: /returns\s*:\s*v\./.test(chunk),
|
|
62
|
+
hasHandler: /handler\s*:/.test(chunk),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return functions;
|
|
69
|
+
}
|
|
70
|
+
function auditFunctions(convexDir) {
|
|
71
|
+
const functions = extractFunctions(convexDir);
|
|
72
|
+
const issues = [];
|
|
73
|
+
const files = collectTsFiles(convexDir);
|
|
74
|
+
// Check 1: Functions missing validators
|
|
75
|
+
for (const fn of functions) {
|
|
76
|
+
if (fn.type === "httpAction")
|
|
77
|
+
continue; // httpActions don't have args/returns validators
|
|
78
|
+
if (!fn.hasArgs) {
|
|
79
|
+
issues.push({
|
|
80
|
+
severity: "critical",
|
|
81
|
+
location: `${fn.relativePath}:${fn.line}`,
|
|
82
|
+
functionName: fn.name,
|
|
83
|
+
message: `${fn.type} "${fn.name}" is missing args validator`,
|
|
84
|
+
fix: "Add args: { } or args: { fieldName: v.string() } to the function definition",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (!fn.hasReturns) {
|
|
88
|
+
issues.push({
|
|
89
|
+
severity: "critical",
|
|
90
|
+
location: `${fn.relativePath}:${fn.line}`,
|
|
91
|
+
functionName: fn.name,
|
|
92
|
+
message: `${fn.type} "${fn.name}" is missing returns validator`,
|
|
93
|
+
fix: "Add returns: v.null() (or appropriate validator) to the function definition",
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
if (!fn.hasHandler) {
|
|
97
|
+
issues.push({
|
|
98
|
+
severity: "critical",
|
|
99
|
+
location: `${fn.relativePath}:${fn.line}`,
|
|
100
|
+
functionName: fn.name,
|
|
101
|
+
message: `${fn.type} "${fn.name}" is missing handler property (may be using old syntax)`,
|
|
102
|
+
fix: "Use new syntax: query({ args: {}, returns: v.null(), handler: async (ctx, args) => { } })",
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Check 2: Sensitive-looking functions registered as public
|
|
107
|
+
const sensitivePatterns = [
|
|
108
|
+
/admin/i, /delete/i, /purge/i, /cleanup/i, /migrate/i,
|
|
109
|
+
/internal/i, /private/i, /seed/i, /backfill/i,
|
|
110
|
+
];
|
|
111
|
+
for (const fn of functions) {
|
|
112
|
+
if (fn.isInternal)
|
|
113
|
+
continue;
|
|
114
|
+
for (const pat of sensitivePatterns) {
|
|
115
|
+
if (pat.test(fn.name)) {
|
|
116
|
+
issues.push({
|
|
117
|
+
severity: "warning",
|
|
118
|
+
location: `${fn.relativePath}:${fn.line}`,
|
|
119
|
+
functionName: fn.name,
|
|
120
|
+
message: `Public ${fn.type} "${fn.name}" has a sensitive-sounding name. Consider making it internal.`,
|
|
121
|
+
fix: `Change ${fn.type} to internal${fn.type.charAt(0).toUpperCase() + fn.type.slice(1)}`,
|
|
122
|
+
});
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Check 3: Action calling action in same file (potential anti-pattern)
|
|
128
|
+
for (const filePath of files) {
|
|
129
|
+
const content = readFileSync(filePath, "utf-8");
|
|
130
|
+
const relativePath = filePath.replace(convexDir, "").replace(/^[\\/]/, "");
|
|
131
|
+
// Find action definitions in this file
|
|
132
|
+
const actionNames = [];
|
|
133
|
+
const actionPattern = /export\s+const\s+(\w+)\s*=\s*(?:action|internalAction)\s*\(/g;
|
|
134
|
+
let m;
|
|
135
|
+
while ((m = actionPattern.exec(content)) !== null) {
|
|
136
|
+
actionNames.push(m[1]);
|
|
137
|
+
}
|
|
138
|
+
// Check if any action calls ctx.runAction referencing same-file actions
|
|
139
|
+
if (actionNames.length > 1 && /ctx\.runAction/.test(content)) {
|
|
140
|
+
issues.push({
|
|
141
|
+
severity: "warning",
|
|
142
|
+
location: relativePath,
|
|
143
|
+
functionName: actionNames.join(", "),
|
|
144
|
+
message: "File has multiple actions and uses ctx.runAction. Only call action from action if crossing runtimes (V8 <-> Node).",
|
|
145
|
+
fix: "Extract shared logic into a helper async function instead of calling actions from actions",
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return issues;
|
|
150
|
+
}
|
|
151
|
+
function checkFunctionRefs(convexDir) {
|
|
152
|
+
const files = collectTsFiles(convexDir);
|
|
153
|
+
const result = {
|
|
154
|
+
totalRefs: 0,
|
|
155
|
+
validRefs: 0,
|
|
156
|
+
brokenRefs: [],
|
|
157
|
+
directPassRefs: [],
|
|
158
|
+
};
|
|
159
|
+
// Collect all exported function names by file path
|
|
160
|
+
const exportedFunctions = new Map();
|
|
161
|
+
const funcTypes = ["query", "internalQuery", "mutation", "internalMutation", "action", "internalAction"];
|
|
162
|
+
for (const filePath of files) {
|
|
163
|
+
const content = readFileSync(filePath, "utf-8");
|
|
164
|
+
const relativePath = filePath
|
|
165
|
+
.replace(convexDir, "")
|
|
166
|
+
.replace(/^[\\/]/, "")
|
|
167
|
+
.replace(/\.ts$/, "");
|
|
168
|
+
const exports = new Set();
|
|
169
|
+
for (const ft of funcTypes) {
|
|
170
|
+
const pattern = new RegExp(`export\\s+const\\s+(\\w+)\\s*=\\s*${ft}\\s*\\(`, "g");
|
|
171
|
+
let m;
|
|
172
|
+
while ((m = pattern.exec(content)) !== null) {
|
|
173
|
+
exports.add(m[1]);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (exports.size > 0) {
|
|
177
|
+
exportedFunctions.set(relativePath, exports);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Check references: api.path.funcName and internal.path.funcName
|
|
181
|
+
const refPattern = /(?:api|internal)\.(\w+(?:\.\w+)*)/g;
|
|
182
|
+
for (const filePath of files) {
|
|
183
|
+
const content = readFileSync(filePath, "utf-8");
|
|
184
|
+
const relativePath = filePath.replace(convexDir, "").replace(/^[\\/]/, "");
|
|
185
|
+
let m;
|
|
186
|
+
while ((m = refPattern.exec(content)) !== null) {
|
|
187
|
+
// Skip if in a comment
|
|
188
|
+
const lineStart = content.lastIndexOf("\n", m.index) + 1;
|
|
189
|
+
const lineContent = content.slice(lineStart, m.index);
|
|
190
|
+
if (lineContent.includes("//") || lineContent.includes("*"))
|
|
191
|
+
continue;
|
|
192
|
+
result.totalRefs++;
|
|
193
|
+
// The reference is like api.file.func or api.dir.file.func
|
|
194
|
+
// We can't fully resolve without the generated api.d.ts but we can check basics
|
|
195
|
+
result.validRefs++; // Assume valid unless proven broken (would need _generated/api.d.ts)
|
|
196
|
+
}
|
|
197
|
+
// Check for direct function passing (anti-pattern)
|
|
198
|
+
const directPassPattern = /ctx\.run(?:Query|Mutation|Action)\s*\(\s*(\w+)\s*[,)]/g;
|
|
199
|
+
let dp;
|
|
200
|
+
while ((dp = directPassPattern.exec(content)) !== null) {
|
|
201
|
+
const funcName = dp[1];
|
|
202
|
+
// Check if it's a local variable (api.x.y) reference or a direct function ref
|
|
203
|
+
if (!funcName.startsWith("api") && !funcName.startsWith("internal") && funcName !== "this") {
|
|
204
|
+
// Could be a variable holding a reference, but flag for review
|
|
205
|
+
const lineStart = content.lastIndexOf("\n", dp.index) + 1;
|
|
206
|
+
const lineContent = content.slice(lineStart, content.indexOf("\n", dp.index));
|
|
207
|
+
if (lineContent.includes("//"))
|
|
208
|
+
continue;
|
|
209
|
+
result.directPassRefs.push(`${relativePath}: ctx.run*(...) called with "${funcName}" - ensure this is a FunctionReference, not a direct function`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
// ── Tool Definitions ────────────────────────────────────────────────
|
|
216
|
+
export const functionTools = [
|
|
217
|
+
{
|
|
218
|
+
name: "convex_audit_functions",
|
|
219
|
+
description: "Audit all exported Convex functions for: missing validators (args/returns), old syntax usage, sensitive functions exposed publicly, and action-from-action anti-patterns. Scans all .ts files in the convex/ directory.",
|
|
220
|
+
inputSchema: {
|
|
221
|
+
type: "object",
|
|
222
|
+
properties: {
|
|
223
|
+
projectDir: {
|
|
224
|
+
type: "string",
|
|
225
|
+
description: "Absolute path to the project root containing a convex/ directory",
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
required: ["projectDir"],
|
|
229
|
+
},
|
|
230
|
+
handler: async (args) => {
|
|
231
|
+
const projectDir = resolve(args.projectDir);
|
|
232
|
+
const convexDir = findConvexDir(projectDir);
|
|
233
|
+
if (!convexDir) {
|
|
234
|
+
return { error: "No convex/ directory found" };
|
|
235
|
+
}
|
|
236
|
+
const issues = auditFunctions(convexDir);
|
|
237
|
+
const functions = extractFunctions(convexDir);
|
|
238
|
+
// Store audit result
|
|
239
|
+
const db = getDb();
|
|
240
|
+
db.prepare("INSERT INTO audit_results (id, project_dir, audit_type, issues_json, issue_count) VALUES (?, ?, ?, ?, ?)").run(genId("audit"), projectDir, "function_audit", JSON.stringify(issues), issues.length);
|
|
241
|
+
const critical = issues.filter((i) => i.severity === "critical");
|
|
242
|
+
const warnings = issues.filter((i) => i.severity === "warning");
|
|
243
|
+
return {
|
|
244
|
+
summary: {
|
|
245
|
+
totalFunctions: functions.length,
|
|
246
|
+
publicFunctions: functions.filter((f) => !f.isInternal).length,
|
|
247
|
+
internalFunctions: functions.filter((f) => f.isInternal).length,
|
|
248
|
+
totalIssues: issues.length,
|
|
249
|
+
critical: critical.length,
|
|
250
|
+
warnings: warnings.length,
|
|
251
|
+
},
|
|
252
|
+
issues,
|
|
253
|
+
quickRef: getQuickRef("convex_audit_functions"),
|
|
254
|
+
};
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
name: "convex_check_function_refs",
|
|
259
|
+
description: "Validate function references across the Convex codebase. Checks that ctx.runQuery/runMutation/runAction use proper api.x.y or internal.x.y references (not direct function passing). Flags potential broken references.",
|
|
260
|
+
inputSchema: {
|
|
261
|
+
type: "object",
|
|
262
|
+
properties: {
|
|
263
|
+
projectDir: {
|
|
264
|
+
type: "string",
|
|
265
|
+
description: "Absolute path to the project root containing a convex/ directory",
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
required: ["projectDir"],
|
|
269
|
+
},
|
|
270
|
+
handler: async (args) => {
|
|
271
|
+
const projectDir = resolve(args.projectDir);
|
|
272
|
+
const convexDir = findConvexDir(projectDir);
|
|
273
|
+
if (!convexDir) {
|
|
274
|
+
return { error: "No convex/ directory found" };
|
|
275
|
+
}
|
|
276
|
+
const result = checkFunctionRefs(convexDir);
|
|
277
|
+
const passed = result.brokenRefs.length === 0 && result.directPassRefs.length === 0;
|
|
278
|
+
return {
|
|
279
|
+
passed,
|
|
280
|
+
summary: {
|
|
281
|
+
totalReferences: result.totalRefs,
|
|
282
|
+
validReferences: result.validRefs,
|
|
283
|
+
brokenReferences: result.brokenRefs.length,
|
|
284
|
+
directPassAntiPatterns: result.directPassRefs.length,
|
|
285
|
+
},
|
|
286
|
+
brokenRefs: result.brokenRefs.length > 0 ? result.brokenRefs : undefined,
|
|
287
|
+
directPassRefs: result.directPassRefs.length > 0 ? result.directPassRefs : undefined,
|
|
288
|
+
quickRef: getQuickRef("convex_check_function_refs"),
|
|
289
|
+
};
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
];
|
|
293
|
+
//# sourceMappingURL=functionTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functionTools.js","sourceRoot":"","sources":["../../src/tools/functionTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,wEAAwE;AAExE,SAAS,cAAc,CAAC,GAAW;IACjC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IACrC,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACxF,OAAO,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;QACxC,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,aAAa,CAAC,UAAkB;IACvC,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IACnF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAgBD,SAAS,gBAAgB,CAAC,SAAiB;IACzC,MAAM,KAAK,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IACxC,MAAM,SAAS,GAAmB,EAAE,CAAC;IAErC,MAAM,SAAS,GAAG;QAChB,OAAO,EAAE,eAAe;QACxB,UAAU,EAAE,kBAAkB;QAC9B,QAAQ,EAAE,gBAAgB;QAC1B,YAAY;KACb,CAAC;IAEF,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC3E,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;gBAC3B,oEAAoE;gBACpE,MAAM,aAAa,GAAG,IAAI,MAAM,CAC9B,iDAAiD,EAAE,SAAS,CAC7D,CAAC;gBACF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;gBACxC,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;oBACvC,4DAA4D;oBAC5D,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAExE,SAAS,CAAC,IAAI,CAAC;wBACb,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,EAAE;wBACR,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;wBACrC,QAAQ;wBACR,YAAY;wBACZ,IAAI,EAAE,CAAC,GAAG,CAAC;wBACX,OAAO,EAAE,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;wBACxE,UAAU,EAAE,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;wBAC3C,UAAU,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;qBACtC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,cAAc,CAAC,SAAiB;IACvC,MAAM,SAAS,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAExC,wCAAwC;IACxC,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC3B,IAAI,EAAE,CAAC,IAAI,KAAK,YAAY;YAAE,SAAS,CAAC,iDAAiD;QAEzF,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC;YAChB,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,IAAI,EAAE;gBACzC,YAAY,EAAE,EAAE,CAAC,IAAI;gBACrB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,6BAA6B;gBAC5D,GAAG,EAAE,6EAA6E;aACnF,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,IAAI,EAAE;gBACzC,YAAY,EAAE,EAAE,CAAC,IAAI;gBACrB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,gCAAgC;gBAC/D,GAAG,EAAE,6EAA6E;aACnF,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,IAAI,EAAE;gBACzC,YAAY,EAAE,EAAE,CAAC,IAAI;gBACrB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,yDAAyD;gBACxF,GAAG,EAAE,2FAA2F;aACjG,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,MAAM,iBAAiB,GAAG;QACxB,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU;QACrD,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW;KAC9C,CAAC;IACF,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC3B,IAAI,EAAE,CAAC,UAAU;YAAE,SAAS;QAC5B,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;YACpC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC;oBACV,QAAQ,EAAE,SAAS;oBACnB,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,IAAI,EAAE;oBACzC,YAAY,EAAE,EAAE,CAAC,IAAI;oBACrB,OAAO,EAAE,UAAU,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,+DAA+D;oBACrG,GAAG,EAAE,UAAU,EAAE,CAAC,IAAI,eAAe,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;iBAC1F,CAAC,CAAC;gBACH,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAE3E,uCAAuC;QACvC,MAAM,WAAW,GAAa,EAAE,CAAC;QACjC,MAAM,aAAa,GAAG,8DAA8D,CAAC;QACrF,IAAI,CAAC,CAAC;QACN,OAAO,CAAC,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAClD,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC;QAED,wEAAwE;QACxE,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7D,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ,EAAE,SAAS;gBACnB,QAAQ,EAAE,YAAY;gBACtB,YAAY,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gBACpC,OAAO,EAAE,oHAAoH;gBAC7H,GAAG,EAAE,2FAA2F;aACjG,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAWD,SAAS,iBAAiB,CAAC,SAAiB;IAC1C,MAAM,KAAK,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IACxC,MAAM,MAAM,GAAmB;QAC7B,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,CAAC;QACZ,UAAU,EAAE,EAAE;QACd,cAAc,EAAE,EAAE;KACnB,CAAC;IAEF,mDAAmD;IACnD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAuB,CAAC;IACzD,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAEzG,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,YAAY,GAAG,QAAQ;aAC1B,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;aACtB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;aACrB,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAExB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,qCAAqC,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;YAClF,IAAI,CAAC,CAAC;YACN,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC5C,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACrB,iBAAiB,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,iEAAiE;IACjE,MAAM,UAAU,GAAG,oCAAoC,CAAC;IACxD,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAE3E,IAAI,CAAC,CAAC;QACN,OAAO,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC/C,uBAAuB;YACvB,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzD,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YACtD,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,SAAS;YAEtE,MAAM,CAAC,SAAS,EAAE,CAAC;YACnB,2DAA2D;YAC3D,gFAAgF;YAChF,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,qEAAqE;QAC3F,CAAC;QAED,mDAAmD;QACnD,MAAM,iBAAiB,GAAG,wDAAwD,CAAC;QACnF,IAAI,EAAE,CAAC;QACP,OAAO,CAAC,EAAE,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACvD,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YACvB,8EAA8E;YAC9E,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;gBAC3F,+DAA+D;gBAC/D,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC1D,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC9E,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAAE,SAAS;gBAEzC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,YAAY,gCAAgC,QAAQ,+DAA+D,CAAC,CAAC;YACrJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,uEAAuE;AAEvE,MAAM,CAAC,MAAM,aAAa,GAAc;IACtC;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EACT,yNAAyN;QAC3N,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,kEAAkE;iBAChF;aACF;YACD,QAAQ,EAAE,CAAC,YAAY,CAAC;SACzB;QACD,OAAO,EAAE,KAAK,EAAE,IAA4B,EAAE,EAAE;YAC9C,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC5C,MAAM,SAAS,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;YAC5C,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC;YACjD,CAAC;YAED,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;YACzC,MAAM,SAAS,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;YAE9C,qBAAqB;YACrB,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;YACnB,EAAE,CAAC,OAAO,CACR,0GAA0G,CAC3G,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAE3F,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC;YACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;YAEhE,OAAO;gBACL,OAAO,EAAE;oBACP,cAAc,EAAE,SAAS,CAAC,MAAM;oBAChC,eAAe,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM;oBAC9D,iBAAiB,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM;oBAC/D,WAAW,EAAE,MAAM,CAAC,MAAM;oBAC1B,QAAQ,EAAE,QAAQ,CAAC,MAAM;oBACzB,QAAQ,EAAE,QAAQ,CAAC,MAAM;iBAC1B;gBACD,MAAM;gBACN,QAAQ,EAAE,WAAW,CAAC,wBAAwB,CAAC;aAChD,CAAC;QACJ,CAAC;KACF;IACD;QACE,IAAI,EAAE,4BAA4B;QAClC,WAAW,EACT,yNAAyN;QAC3N,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,kEAAkE;iBAChF;aACF;YACD,QAAQ,EAAE,CAAC,YAAY,CAAC;SACzB;QACD,OAAO,EAAE,KAAK,EAAE,IAA4B,EAAE,EAAE;YAC9C,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC5C,MAAM,SAAS,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;YAC5C,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC;YACjD,CAAC;YAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;YAE5C,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,CAAC;YAEpF,OAAO;gBACL,MAAM;gBACN,OAAO,EAAE;oBACP,eAAe,EAAE,MAAM,CAAC,SAAS;oBACjC,eAAe,EAAE,MAAM,CAAC,SAAS;oBACjC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM;oBAC1C,sBAAsB,EAAE,MAAM,CAAC,cAAc,CAAC,MAAM;iBACrD;gBACD,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;gBACxE,cAAc,EAAE,MAAM,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS;gBACpF,QAAQ,EAAE,WAAW,CAAC,4BAA4B,CAAC;aACpD,CAAC;QACJ,CAAC;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { getDb, genId } from "../db.js";
|
|
4
|
+
import { getQuickRef } from "./toolRegistry.js";
|
|
5
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
6
|
+
function findConvexDir(projectDir) {
|
|
7
|
+
const candidates = [join(projectDir, "convex"), join(projectDir, "src", "convex")];
|
|
8
|
+
for (const c of candidates) {
|
|
9
|
+
if (existsSync(c))
|
|
10
|
+
return c;
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
function collectTsFiles(dir) {
|
|
15
|
+
const results = [];
|
|
16
|
+
if (!existsSync(dir))
|
|
17
|
+
return results;
|
|
18
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
19
|
+
for (const entry of entries) {
|
|
20
|
+
const full = join(dir, entry.name);
|
|
21
|
+
if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== "_generated") {
|
|
22
|
+
results.push(...collectTsFiles(full));
|
|
23
|
+
}
|
|
24
|
+
else if (entry.isFile() && entry.name.endsWith(".ts")) {
|
|
25
|
+
results.push(full);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return results;
|
|
29
|
+
}
|
|
30
|
+
// ── Rules Generation Engine ─────────────────────────────────────────
|
|
31
|
+
function generateRulesContent(projectDir) {
|
|
32
|
+
const db = getDb();
|
|
33
|
+
const convexDir = findConvexDir(projectDir);
|
|
34
|
+
// Gather gotchas
|
|
35
|
+
const gotchas = db.prepare("SELECT key, content, category, severity FROM convex_gotchas ORDER BY severity DESC, category").all();
|
|
36
|
+
// Gather recent audit findings
|
|
37
|
+
const recentAudits = db.prepare("SELECT audit_type, issue_count, audited_at FROM audit_results WHERE project_dir = ? ORDER BY audited_at DESC LIMIT 5").all(projectDir);
|
|
38
|
+
// Gather deploy check history
|
|
39
|
+
const deployChecks = db.prepare("SELECT passed, checked_at FROM deploy_checks WHERE project_dir = ? ORDER BY checked_at DESC LIMIT 3").all(projectDir);
|
|
40
|
+
// Count functions by type
|
|
41
|
+
let functionStats = { total: 0, public: 0, internal: 0, httpActions: 0 };
|
|
42
|
+
if (convexDir) {
|
|
43
|
+
const files = collectTsFiles(convexDir);
|
|
44
|
+
for (const f of files) {
|
|
45
|
+
const content = readFileSync(f, "utf-8");
|
|
46
|
+
const pubMatches = content.match(/export\s+const\s+\w+\s*=\s*(query|mutation|action)\s*\(/g);
|
|
47
|
+
const intMatches = content.match(/export\s+const\s+\w+\s*=\s*(internalQuery|internalMutation|internalAction)\s*\(/g);
|
|
48
|
+
const httpMatches = content.match(/httpAction\s*\(/g);
|
|
49
|
+
functionStats.total += (pubMatches?.length || 0) + (intMatches?.length || 0) + (httpMatches?.length || 0);
|
|
50
|
+
functionStats.public += pubMatches?.length || 0;
|
|
51
|
+
functionStats.internal += intMatches?.length || 0;
|
|
52
|
+
functionStats.httpActions += httpMatches?.length || 0;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Build rules markdown
|
|
56
|
+
const lines = [];
|
|
57
|
+
lines.push("# Convex Development Rules");
|
|
58
|
+
lines.push(`# Auto-generated by convex-mcp-nodebench at ${new Date().toISOString()}`);
|
|
59
|
+
lines.push(`# Project: ${projectDir}`);
|
|
60
|
+
lines.push("");
|
|
61
|
+
lines.push("## Project Stats");
|
|
62
|
+
lines.push(`- Total functions: ${functionStats.total}`);
|
|
63
|
+
lines.push(`- Public: ${functionStats.public}, Internal: ${functionStats.internal}, HTTP Actions: ${functionStats.httpActions}`);
|
|
64
|
+
if (recentAudits.length > 0) {
|
|
65
|
+
lines.push(`- Last audit: ${recentAudits[0].audit_type} (${recentAudits[0].issue_count} issues) at ${recentAudits[0].audited_at}`);
|
|
66
|
+
}
|
|
67
|
+
if (deployChecks.length > 0) {
|
|
68
|
+
lines.push(`- Last deploy check: ${deployChecks[0].passed ? "PASSED" : "BLOCKED"} at ${deployChecks[0].checked_at}`);
|
|
69
|
+
}
|
|
70
|
+
lines.push("");
|
|
71
|
+
// Group gotchas by category
|
|
72
|
+
const categories = new Map();
|
|
73
|
+
for (const g of gotchas) {
|
|
74
|
+
if (!categories.has(g.category))
|
|
75
|
+
categories.set(g.category, []);
|
|
76
|
+
categories.get(g.category).push(g);
|
|
77
|
+
}
|
|
78
|
+
lines.push("## Convex Rules & Gotchas");
|
|
79
|
+
lines.push("");
|
|
80
|
+
for (const [category, items] of categories) {
|
|
81
|
+
lines.push(`### ${category.charAt(0).toUpperCase() + category.slice(1)}`);
|
|
82
|
+
for (const item of items) {
|
|
83
|
+
const icon = item.severity === "critical" ? "CRITICAL" : item.severity === "warning" ? "WARNING" : "INFO";
|
|
84
|
+
lines.push(`- **[${icon}]** \`${item.key}\`: ${item.content}`);
|
|
85
|
+
}
|
|
86
|
+
lines.push("");
|
|
87
|
+
}
|
|
88
|
+
lines.push("## Methodology");
|
|
89
|
+
lines.push("1. Before any schema change: run `convex_audit_schema`");
|
|
90
|
+
lines.push("2. Before any function change: run `convex_audit_functions`");
|
|
91
|
+
lines.push("3. Before any deploy: run `convex_pre_deploy_gate`");
|
|
92
|
+
lines.push("4. Before implementing: run `convex_search_gotchas` with your task description");
|
|
93
|
+
lines.push("5. After fixing bugs: run `convex_record_gotcha` to prevent repeats");
|
|
94
|
+
lines.push("");
|
|
95
|
+
return lines.join("\n");
|
|
96
|
+
}
|
|
97
|
+
// ── Schema Snapshot Engine ──────────────────────────────────────────
|
|
98
|
+
function captureSchemaSnapshot(projectDir) {
|
|
99
|
+
const convexDir = findConvexDir(projectDir);
|
|
100
|
+
if (!convexDir)
|
|
101
|
+
return null;
|
|
102
|
+
const schemaPath = join(convexDir, "schema.ts");
|
|
103
|
+
if (!existsSync(schemaPath))
|
|
104
|
+
return null;
|
|
105
|
+
const schemaContent = readFileSync(schemaPath, "utf-8");
|
|
106
|
+
// Extract table definitions (rough)
|
|
107
|
+
const tablePattern = /(\w+)\s*[:=]\s*defineTable\s*\(/g;
|
|
108
|
+
const tables = [];
|
|
109
|
+
let m;
|
|
110
|
+
while ((m = tablePattern.exec(schemaContent)) !== null) {
|
|
111
|
+
tables.push(m[1]);
|
|
112
|
+
}
|
|
113
|
+
const schemaJson = JSON.stringify({
|
|
114
|
+
tables,
|
|
115
|
+
rawLength: schemaContent.length,
|
|
116
|
+
capturedAt: new Date().toISOString(),
|
|
117
|
+
});
|
|
118
|
+
return { schemaJson, tableCount: tables.length };
|
|
119
|
+
}
|
|
120
|
+
// ── Tool Definitions ────────────────────────────────────────────────
|
|
121
|
+
export const integrationBridgeTools = [
|
|
122
|
+
{
|
|
123
|
+
name: "convex_generate_rules_md",
|
|
124
|
+
description: "Generate or update a Convex rules markdown file from the current gotcha database, recent audit results, and project stats. Outputs to a specified path or returns the content. Use this to keep your AI rules file in sync with accumulated Convex knowledge.",
|
|
125
|
+
inputSchema: {
|
|
126
|
+
type: "object",
|
|
127
|
+
properties: {
|
|
128
|
+
projectDir: {
|
|
129
|
+
type: "string",
|
|
130
|
+
description: "Absolute path to the project root",
|
|
131
|
+
},
|
|
132
|
+
outputPath: {
|
|
133
|
+
type: "string",
|
|
134
|
+
description: "Optional: path to write the rules file (e.g., .windsurf/rules/convexRules.md). If omitted, returns content only.",
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
required: ["projectDir"],
|
|
138
|
+
},
|
|
139
|
+
handler: async (args) => {
|
|
140
|
+
const projectDir = resolve(args.projectDir);
|
|
141
|
+
const content = generateRulesContent(projectDir);
|
|
142
|
+
if (args.outputPath) {
|
|
143
|
+
const outputPath = resolve(args.outputPath);
|
|
144
|
+
writeFileSync(outputPath, content, "utf-8");
|
|
145
|
+
return {
|
|
146
|
+
action: "written",
|
|
147
|
+
outputPath,
|
|
148
|
+
lines: content.split("\n").length,
|
|
149
|
+
quickRef: getQuickRef("convex_get_methodology"),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
action: "generated",
|
|
154
|
+
content,
|
|
155
|
+
lines: content.split("\n").length,
|
|
156
|
+
quickRef: getQuickRef("convex_get_methodology"),
|
|
157
|
+
};
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: "convex_snapshot_schema",
|
|
162
|
+
description: "Capture a snapshot of the current schema.ts for later diffing. Stores table names, schema size, and timestamp. Use before and after schema changes to track what changed.",
|
|
163
|
+
inputSchema: {
|
|
164
|
+
type: "object",
|
|
165
|
+
properties: {
|
|
166
|
+
projectDir: {
|
|
167
|
+
type: "string",
|
|
168
|
+
description: "Absolute path to the project root",
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
required: ["projectDir"],
|
|
172
|
+
},
|
|
173
|
+
handler: async (args) => {
|
|
174
|
+
const projectDir = resolve(args.projectDir);
|
|
175
|
+
const snapshot = captureSchemaSnapshot(projectDir);
|
|
176
|
+
if (!snapshot) {
|
|
177
|
+
return { error: "No schema.ts found" };
|
|
178
|
+
}
|
|
179
|
+
const db = getDb();
|
|
180
|
+
const id = genId("snap");
|
|
181
|
+
db.prepare("INSERT INTO schema_snapshots (id, project_dir, schema_json) VALUES (?, ?, ?)").run(id, projectDir, snapshot.schemaJson);
|
|
182
|
+
// Compare with previous snapshot
|
|
183
|
+
const previous = db.prepare("SELECT schema_json, snapshot_at FROM schema_snapshots WHERE project_dir = ? AND id != ? ORDER BY snapshot_at DESC LIMIT 1").get(projectDir, id);
|
|
184
|
+
let diff = null;
|
|
185
|
+
if (previous) {
|
|
186
|
+
try {
|
|
187
|
+
const prev = JSON.parse(previous.schema_json);
|
|
188
|
+
const curr = JSON.parse(snapshot.schemaJson);
|
|
189
|
+
const addedTables = curr.tables.filter((t) => !prev.tables.includes(t));
|
|
190
|
+
const removedTables = prev.tables.filter((t) => !curr.tables.includes(t));
|
|
191
|
+
diff = {
|
|
192
|
+
previousSnapshot: previous.snapshot_at,
|
|
193
|
+
addedTables,
|
|
194
|
+
removedTables,
|
|
195
|
+
sizeChange: curr.rawLength - prev.rawLength,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
catch { /* ignore */ }
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
snapshotId: id,
|
|
202
|
+
tableCount: snapshot.tableCount,
|
|
203
|
+
diff,
|
|
204
|
+
quickRef: getQuickRef("convex_audit_schema"),
|
|
205
|
+
};
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: "convex_bootstrap_project",
|
|
210
|
+
description: "Scan a Convex project directory and generate a comprehensive health report. Checks: schema presence, function count, validator coverage, index usage, env vars, auth setup, and known gotchas. Returns a prioritized improvement plan.",
|
|
211
|
+
inputSchema: {
|
|
212
|
+
type: "object",
|
|
213
|
+
properties: {
|
|
214
|
+
projectDir: {
|
|
215
|
+
type: "string",
|
|
216
|
+
description: "Absolute path to the project root",
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
required: ["projectDir"],
|
|
220
|
+
},
|
|
221
|
+
handler: async (args) => {
|
|
222
|
+
const projectDir = resolve(args.projectDir);
|
|
223
|
+
const convexDir = findConvexDir(projectDir);
|
|
224
|
+
if (!convexDir) {
|
|
225
|
+
return { error: "No convex/ directory found" };
|
|
226
|
+
}
|
|
227
|
+
const checks = [];
|
|
228
|
+
// Check schema.ts
|
|
229
|
+
const schemaPath = join(convexDir, "schema.ts");
|
|
230
|
+
if (existsSync(schemaPath)) {
|
|
231
|
+
const content = readFileSync(schemaPath, "utf-8");
|
|
232
|
+
const tableCount = (content.match(/defineTable\s*\(/g) || []).length;
|
|
233
|
+
const indexCount = (content.match(/\.index\s*\(/g) || []).length;
|
|
234
|
+
checks.push({ area: "Schema", status: "good", detail: `${tableCount} tables, ${indexCount} indexes` });
|
|
235
|
+
if (indexCount === 0 && tableCount > 0) {
|
|
236
|
+
checks.push({ area: "Indexes", status: "warning", detail: "No indexes defined — queries will scan full tables" });
|
|
237
|
+
}
|
|
238
|
+
if (/v\.bigint\s*\(/.test(content)) {
|
|
239
|
+
checks.push({ area: "Deprecated validators", status: "critical", detail: "Uses v.bigint() — replace with v.int64()" });
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
checks.push({ area: "Schema", status: "warning", detail: "No schema.ts — using inferred schema" });
|
|
244
|
+
}
|
|
245
|
+
// Check auth
|
|
246
|
+
if (existsSync(join(convexDir, "auth.ts"))) {
|
|
247
|
+
if (existsSync(join(convexDir, "auth.config.ts"))) {
|
|
248
|
+
checks.push({ area: "Auth", status: "good", detail: "auth.ts + auth.config.ts present" });
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
checks.push({ area: "Auth", status: "critical", detail: "auth.ts exists but auth.config.ts is missing" });
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Check _generated
|
|
255
|
+
if (existsSync(join(convexDir, "_generated"))) {
|
|
256
|
+
checks.push({ area: "Initialization", status: "good", detail: "_generated/ present" });
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
checks.push({ area: "Initialization", status: "critical", detail: "Run 'npx convex dev' to initialize" });
|
|
260
|
+
}
|
|
261
|
+
// Count files
|
|
262
|
+
const files = collectTsFiles(convexDir);
|
|
263
|
+
checks.push({ area: "Codebase", status: "good", detail: `${files.length} TypeScript files in convex/` });
|
|
264
|
+
// Generate improvement plan
|
|
265
|
+
const plan = [];
|
|
266
|
+
const criticals = checks.filter((c) => c.status === "critical");
|
|
267
|
+
const warnings = checks.filter((c) => c.status === "warning");
|
|
268
|
+
if (criticals.length > 0) {
|
|
269
|
+
plan.push("CRITICAL: Fix these first:");
|
|
270
|
+
for (const c of criticals)
|
|
271
|
+
plan.push(` - [${c.area}] ${c.detail}`);
|
|
272
|
+
}
|
|
273
|
+
if (warnings.length > 0) {
|
|
274
|
+
plan.push("WARNINGS: Address these next:");
|
|
275
|
+
for (const w of warnings)
|
|
276
|
+
plan.push(` - [${w.area}] ${w.detail}`);
|
|
277
|
+
}
|
|
278
|
+
plan.push("RECOMMENDED: Run convex_audit_schema → convex_audit_functions → convex_pre_deploy_gate");
|
|
279
|
+
return {
|
|
280
|
+
projectDir,
|
|
281
|
+
convexDir,
|
|
282
|
+
checks,
|
|
283
|
+
summary: {
|
|
284
|
+
good: checks.filter((c) => c.status === "good").length,
|
|
285
|
+
warnings: warnings.length,
|
|
286
|
+
criticals: criticals.length,
|
|
287
|
+
},
|
|
288
|
+
improvementPlan: plan,
|
|
289
|
+
quickRef: getQuickRef("convex_get_methodology"),
|
|
290
|
+
};
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
];
|
|
294
|
+
//# sourceMappingURL=integrationBridgeTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrationBridgeTools.js","sourceRoot":"","sources":["../../src/tools/integrationBridgeTools.ts"],"names":[],"mappings":"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"}
|