structx 1.0.0 → 2.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 +72 -0
- package/dist/cli.js +260 -211
- package/dist/cli.js.map +1 -1
- package/dist/db/connection.js +28 -1
- package/dist/db/connection.js.map +1 -1
- package/dist/db/queries.d.ts +144 -0
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +282 -6
- package/dist/db/queries.js.map +1 -1
- package/dist/db/schema.sql +59 -0
- package/dist/ingest/constant-extractor.d.ts +11 -0
- package/dist/ingest/constant-extractor.d.ts.map +1 -0
- package/dist/ingest/constant-extractor.js +38 -0
- package/dist/ingest/constant-extractor.js.map +1 -0
- package/dist/ingest/file-metadata.d.ts +13 -0
- package/dist/ingest/file-metadata.d.ts.map +1 -0
- package/dist/ingest/file-metadata.js +55 -0
- package/dist/ingest/file-metadata.js.map +1 -0
- package/dist/ingest/ingester.d.ts +15 -0
- package/dist/ingest/ingester.d.ts.map +1 -0
- package/dist/ingest/ingester.js +217 -0
- package/dist/ingest/ingester.js.map +1 -0
- package/dist/ingest/parser.d.ts +12 -0
- package/dist/ingest/parser.d.ts.map +1 -1
- package/dist/ingest/parser.js +48 -0
- package/dist/ingest/parser.js.map +1 -1
- package/dist/ingest/route-extractor.d.ts +12 -0
- package/dist/ingest/route-extractor.d.ts.map +1 -0
- package/dist/ingest/route-extractor.js +64 -0
- package/dist/ingest/route-extractor.js.map +1 -0
- package/dist/ingest/type-extractor.d.ts +11 -0
- package/dist/ingest/type-extractor.d.ts.map +1 -0
- package/dist/ingest/type-extractor.js +47 -0
- package/dist/ingest/type-extractor.js.map +1 -0
- package/dist/instructions/claude.md +54 -25
- package/dist/instructions/codex.md +70 -0
- package/dist/instructions/copilot.md +57 -26
- package/dist/instructions/cursor.md +54 -25
- package/dist/instructions/generic.md +54 -25
- package/dist/query/answerer.d.ts.map +1 -1
- package/dist/query/answerer.js +6 -2
- package/dist/query/answerer.js.map +1 -1
- package/dist/query/classifier.d.ts +6 -1
- package/dist/query/classifier.d.ts.map +1 -1
- package/dist/query/classifier.js +22 -2
- package/dist/query/classifier.js.map +1 -1
- package/dist/query/context-builder.d.ts.map +1 -1
- package/dist/query/context-builder.js +152 -6
- package/dist/query/context-builder.js.map +1 -1
- package/dist/query/retriever.d.ts +44 -0
- package/dist/query/retriever.d.ts.map +1 -1
- package/dist/query/retriever.js +211 -14
- package/dist/query/retriever.js.map +1 -1
- package/dist/semantic/analyzer.d.ts +10 -0
- package/dist/semantic/analyzer.d.ts.map +1 -1
- package/dist/semantic/analyzer.js +147 -1
- package/dist/semantic/analyzer.js.map +1 -1
- package/dist/semantic/prompt.d.ts +21 -0
- package/dist/semantic/prompt.d.ts.map +1 -1
- package/dist/semantic/prompt.js +63 -0
- package/dist/semantic/prompt.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ingestDirectory = ingestDirectory;
|
|
37
|
+
exports.printIngestResult = printIngestResult;
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const queries_1 = require("../db/queries");
|
|
41
|
+
const parser_1 = require("./parser");
|
|
42
|
+
const relationships_1 = require("./relationships");
|
|
43
|
+
const differ_1 = require("./differ");
|
|
44
|
+
const scanner_1 = require("./scanner");
|
|
45
|
+
const logger_1 = require("../utils/logger");
|
|
46
|
+
function ingestDirectory(db, repoPath, diffThreshold) {
|
|
47
|
+
const project = (0, parser_1.createProject)(repoPath);
|
|
48
|
+
const files = (0, scanner_1.scanDirectory)(repoPath);
|
|
49
|
+
console.log(`Found ${files.length} TypeScript files.`);
|
|
50
|
+
const result = {
|
|
51
|
+
newFiles: 0,
|
|
52
|
+
changedFiles: 0,
|
|
53
|
+
unchangedFiles: 0,
|
|
54
|
+
totalFunctions: 0,
|
|
55
|
+
totalRelationships: 0,
|
|
56
|
+
totalTypes: 0,
|
|
57
|
+
totalRoutes: 0,
|
|
58
|
+
totalConstants: 0,
|
|
59
|
+
queued: 0,
|
|
60
|
+
};
|
|
61
|
+
for (const filePath of files) {
|
|
62
|
+
const relativePath = path.relative(repoPath, filePath);
|
|
63
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
64
|
+
const contentHash = (0, parser_1.hashFileContent)(content);
|
|
65
|
+
const existingFile = (0, queries_1.getFileByPath)(db, relativePath);
|
|
66
|
+
if (existingFile && existingFile.content_hash === contentHash) {
|
|
67
|
+
result.unchangedFiles++;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const isNew = !existingFile;
|
|
71
|
+
if (isNew)
|
|
72
|
+
result.newFiles++;
|
|
73
|
+
else
|
|
74
|
+
result.changedFiles++;
|
|
75
|
+
// Wrap each file's ingest in a transaction for atomicity
|
|
76
|
+
db.transaction(() => {
|
|
77
|
+
const fileId = (0, queries_1.upsertFile)(db, relativePath, contentHash);
|
|
78
|
+
const oldFunctions = isNew ? [] : (0, queries_1.getFunctionsByFileId)(db, fileId);
|
|
79
|
+
const oldFunctionMap = new Map(oldFunctions.map(f => [f.name, f]));
|
|
80
|
+
if (!isNew) {
|
|
81
|
+
for (const oldFn of oldFunctions) {
|
|
82
|
+
(0, queries_1.deleteRelationshipsByCallerFunctionId)(db, oldFn.id);
|
|
83
|
+
}
|
|
84
|
+
(0, queries_1.deleteFunctionsByFileId)(db, fileId);
|
|
85
|
+
(0, queries_1.deleteTypesByFileId)(db, fileId);
|
|
86
|
+
(0, queries_1.deleteRoutesByFileId)(db, fileId);
|
|
87
|
+
(0, queries_1.deleteConstantsByFileId)(db, fileId);
|
|
88
|
+
}
|
|
89
|
+
let parsed;
|
|
90
|
+
try {
|
|
91
|
+
parsed = (0, parser_1.parseFileComplete)(project, filePath);
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
logger_1.logger.warn(`Failed to parse ${relativePath}: ${err.message}`);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// Insert functions
|
|
98
|
+
const functionIdMap = new Map();
|
|
99
|
+
for (const fn of parsed.functions) {
|
|
100
|
+
const fnId = (0, queries_1.insertFunction)(db, {
|
|
101
|
+
file_id: fileId,
|
|
102
|
+
name: fn.name,
|
|
103
|
+
signature: fn.signature,
|
|
104
|
+
body: fn.body,
|
|
105
|
+
code_hash: fn.codeHash,
|
|
106
|
+
start_line: fn.startLine,
|
|
107
|
+
end_line: fn.endLine,
|
|
108
|
+
is_exported: fn.isExported,
|
|
109
|
+
is_async: fn.isAsync,
|
|
110
|
+
});
|
|
111
|
+
functionIdMap.set(fn.name, fnId);
|
|
112
|
+
result.totalFunctions++;
|
|
113
|
+
const oldFn = oldFunctionMap.get(fn.name);
|
|
114
|
+
if (!oldFn) {
|
|
115
|
+
(0, queries_1.enqueueForAnalysis)(db, fnId, 'new', (0, differ_1.getPriority)('new', fn.isExported));
|
|
116
|
+
result.queued++;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
const { reanalyze, reason } = (0, differ_1.shouldReanalyze)(oldFn, fn.signature, fn.codeHash, fn.body, diffThreshold);
|
|
120
|
+
if (reanalyze) {
|
|
121
|
+
(0, queries_1.enqueueForAnalysis)(db, fnId, reason, (0, differ_1.getPriority)(reason, fn.isExported));
|
|
122
|
+
result.queued++;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Insert types
|
|
127
|
+
for (const t of parsed.types) {
|
|
128
|
+
(0, queries_1.insertType)(db, {
|
|
129
|
+
file_id: fileId,
|
|
130
|
+
name: t.name,
|
|
131
|
+
kind: t.kind,
|
|
132
|
+
full_text: t.fullText,
|
|
133
|
+
is_exported: t.isExported,
|
|
134
|
+
start_line: t.startLine,
|
|
135
|
+
end_line: t.endLine,
|
|
136
|
+
});
|
|
137
|
+
result.totalTypes++;
|
|
138
|
+
}
|
|
139
|
+
// Insert routes
|
|
140
|
+
for (const r of parsed.routes) {
|
|
141
|
+
(0, queries_1.insertRoute)(db, {
|
|
142
|
+
file_id: fileId,
|
|
143
|
+
method: r.method,
|
|
144
|
+
path: r.path,
|
|
145
|
+
handler_name: r.handlerName,
|
|
146
|
+
handler_body: r.handlerBody,
|
|
147
|
+
middleware: r.middleware,
|
|
148
|
+
start_line: r.startLine,
|
|
149
|
+
end_line: r.endLine,
|
|
150
|
+
});
|
|
151
|
+
result.totalRoutes++;
|
|
152
|
+
}
|
|
153
|
+
// Insert constants
|
|
154
|
+
for (const c of parsed.constants) {
|
|
155
|
+
(0, queries_1.insertConstant)(db, {
|
|
156
|
+
file_id: fileId,
|
|
157
|
+
name: c.name,
|
|
158
|
+
value_text: c.valueText,
|
|
159
|
+
type_annotation: c.typeAnnotation,
|
|
160
|
+
is_exported: c.isExported,
|
|
161
|
+
start_line: c.startLine,
|
|
162
|
+
end_line: c.endLine,
|
|
163
|
+
});
|
|
164
|
+
result.totalConstants++;
|
|
165
|
+
}
|
|
166
|
+
// Insert file summary
|
|
167
|
+
(0, queries_1.upsertFileSummary)(db, {
|
|
168
|
+
file_id: fileId,
|
|
169
|
+
import_count: parsed.fileMetadata.importCount,
|
|
170
|
+
export_count: parsed.fileMetadata.exportCount,
|
|
171
|
+
function_count: parsed.fileMetadata.functionCount,
|
|
172
|
+
type_count: parsed.fileMetadata.typeCount,
|
|
173
|
+
route_count: parsed.fileMetadata.routeCount,
|
|
174
|
+
loc: parsed.fileMetadata.loc,
|
|
175
|
+
imports_json: JSON.stringify(parsed.fileMetadata.imports),
|
|
176
|
+
exports_json: JSON.stringify(parsed.fileMetadata.exports),
|
|
177
|
+
});
|
|
178
|
+
// Extract and insert relationships
|
|
179
|
+
try {
|
|
180
|
+
const calls = (0, relationships_1.extractCallsFromFile)(project, filePath);
|
|
181
|
+
for (const call of calls) {
|
|
182
|
+
if (call.callerName === '__file__')
|
|
183
|
+
continue;
|
|
184
|
+
const callerId = functionIdMap.get(call.callerName);
|
|
185
|
+
if (!callerId)
|
|
186
|
+
continue;
|
|
187
|
+
const callee = (0, queries_1.getFunctionByName)(db, call.calleeName);
|
|
188
|
+
(0, queries_1.insertRelationship)(db, callerId, call.calleeName, call.relationType, callee?.id);
|
|
189
|
+
result.totalRelationships++;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
logger_1.logger.warn(`Failed to extract calls from ${relativePath}: ${err.message}`);
|
|
194
|
+
}
|
|
195
|
+
})();
|
|
196
|
+
}
|
|
197
|
+
// Second-pass: resolve NULL callee_function_ids and rebuild all FTS indexes
|
|
198
|
+
const resolvedCount = (0, queries_1.resolveNullCallees)(db);
|
|
199
|
+
if (resolvedCount > 0) {
|
|
200
|
+
logger_1.logger.info(`Resolved ${resolvedCount} NULL callee_function_id(s)`);
|
|
201
|
+
}
|
|
202
|
+
(0, queries_1.rebuildAllFtsIndexes)(db);
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
function printIngestResult(result) {
|
|
206
|
+
console.log(`\nIngestion complete:`);
|
|
207
|
+
console.log(` New files: ${result.newFiles}`);
|
|
208
|
+
console.log(` Changed files: ${result.changedFiles}`);
|
|
209
|
+
console.log(` Unchanged: ${result.unchangedFiles}`);
|
|
210
|
+
console.log(` Functions: ${result.totalFunctions}`);
|
|
211
|
+
console.log(` Types: ${result.totalTypes}`);
|
|
212
|
+
console.log(` Routes: ${result.totalRoutes}`);
|
|
213
|
+
console.log(` Constants: ${result.totalConstants}`);
|
|
214
|
+
console.log(` Relationships: ${result.totalRelationships}`);
|
|
215
|
+
console.log(` Queued: ${result.queued} functions for semantic analysis`);
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=ingester.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingester.js","sourceRoot":"","sources":["../../src/ingest/ingester.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,0CA+KC;AAED,8CAWC;AA3ND,2CAA6B;AAC7B,uCAAyB;AAEzB,2CASuB;AACvB,qCAA6E;AAC7E,mDAAuD;AACvD,qCAAwD;AACxD,uCAA0C;AAC1C,4CAAyC;AAczC,SAAgB,eAAe,CAC7B,EAAqB,EACrB,QAAgB,EAChB,aAAqB;IAErB,MAAM,OAAO,GAAG,IAAA,sBAAa,EAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,IAAA,uBAAa,EAAC,QAAQ,CAAC,CAAC;IAEtC,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,CAAC,MAAM,oBAAoB,CAAC,CAAC;IAEvD,MAAM,MAAM,GAAiB;QAC3B,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,CAAC;QACf,cAAc,EAAE,CAAC;QACjB,cAAc,EAAE,CAAC;QACjB,kBAAkB,EAAE,CAAC;QACrB,UAAU,EAAE,CAAC;QACb,WAAW,EAAE,CAAC;QACd,cAAc,EAAE,CAAC;QACjB,MAAM,EAAE,CAAC;KACV,CAAC;IAEF,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,WAAW,GAAG,IAAA,wBAAe,EAAC,OAAO,CAAC,CAAC;QAE7C,MAAM,YAAY,GAAG,IAAA,uBAAa,EAAC,EAAE,EAAE,YAAY,CAAC,CAAC;QACrD,IAAI,YAAY,IAAI,YAAY,CAAC,YAAY,KAAK,WAAW,EAAE,CAAC;YAC9D,MAAM,CAAC,cAAc,EAAE,CAAC;YACxB,SAAS;QACX,CAAC;QAED,MAAM,KAAK,GAAG,CAAC,YAAY,CAAC;QAC5B,IAAI,KAAK;YAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;;YACxB,MAAM,CAAC,YAAY,EAAE,CAAC;QAE3B,yDAAyD;QACzD,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YAClB,MAAM,MAAM,GAAG,IAAA,oBAAU,EAAC,EAAE,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;YAEzD,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAA,8BAAoB,EAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YACnE,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAEnE,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;oBACjC,IAAA,+CAAqC,EAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;gBACtD,CAAC;gBACD,IAAA,iCAAuB,EAAC,EAAE,EAAE,MAAM,CAAC,CAAC;gBACpC,IAAA,6BAAmB,EAAC,EAAE,EAAE,MAAM,CAAC,CAAC;gBAChC,IAAA,8BAAoB,EAAC,EAAE,EAAE,MAAM,CAAC,CAAC;gBACjC,IAAA,iCAAuB,EAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YACtC,CAAC;YAED,IAAI,MAAM,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,GAAG,IAAA,0BAAiB,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAChD,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,eAAM,CAAC,IAAI,CAAC,mBAAmB,YAAY,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC/D,OAAO;YACT,CAAC;YAED,mBAAmB;YACnB,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;YAChD,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBAClC,MAAM,IAAI,GAAG,IAAA,wBAAc,EAAC,EAAE,EAAE;oBAC9B,OAAO,EAAE,MAAM;oBACf,IAAI,EAAE,EAAE,CAAC,IAAI;oBACb,SAAS,EAAE,EAAE,CAAC,SAAS;oBACvB,IAAI,EAAE,EAAE,CAAC,IAAI;oBACb,SAAS,EAAE,EAAE,CAAC,QAAQ;oBACtB,UAAU,EAAE,EAAE,CAAC,SAAS;oBACxB,QAAQ,EAAE,EAAE,CAAC,OAAO;oBACpB,WAAW,EAAE,EAAE,CAAC,UAAU;oBAC1B,QAAQ,EAAE,EAAE,CAAC,OAAO;iBACrB,CAAC,CAAC;gBACH,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACjC,MAAM,CAAC,cAAc,EAAE,CAAC;gBAExB,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;gBAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,IAAA,4BAAkB,EAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAA,oBAAW,EAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;oBACvE,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,CAAC;qBAAM,CAAC;oBACN,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAA,wBAAe,EAC3C,KAAK,EAAE,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,EAAE,aAAa,CACzD,CAAC;oBACF,IAAI,SAAS,EAAE,CAAC;wBACd,IAAA,4BAAkB,EAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAA,oBAAW,EAAC,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;wBACzE,MAAM,CAAC,MAAM,EAAE,CAAC;oBAClB,CAAC;gBACH,CAAC;YACH,CAAC;YAED,eAAe;YACf,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBAC7B,IAAA,oBAAU,EAAC,EAAE,EAAE;oBACb,OAAO,EAAE,MAAM;oBACf,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,SAAS,EAAE,CAAC,CAAC,QAAQ;oBACrB,WAAW,EAAE,CAAC,CAAC,UAAU;oBACzB,UAAU,EAAE,CAAC,CAAC,SAAS;oBACvB,QAAQ,EAAE,CAAC,CAAC,OAAO;iBACpB,CAAC,CAAC;gBACH,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,CAAC;YAED,gBAAgB;YAChB,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC9B,IAAA,qBAAW,EAAC,EAAE,EAAE;oBACd,OAAO,EAAE,MAAM;oBACf,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,YAAY,EAAE,CAAC,CAAC,WAAW;oBAC3B,YAAY,EAAE,CAAC,CAAC,WAAW;oBAC3B,UAAU,EAAE,CAAC,CAAC,UAAU;oBACxB,UAAU,EAAE,CAAC,CAAC,SAAS;oBACvB,QAAQ,EAAE,CAAC,CAAC,OAAO;iBACpB,CAAC,CAAC;gBACH,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,CAAC;YAED,mBAAmB;YACnB,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBACjC,IAAA,wBAAc,EAAC,EAAE,EAAE;oBACjB,OAAO,EAAE,MAAM;oBACf,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,UAAU,EAAE,CAAC,CAAC,SAAS;oBACvB,eAAe,EAAE,CAAC,CAAC,cAAc;oBACjC,WAAW,EAAE,CAAC,CAAC,UAAU;oBACzB,UAAU,EAAE,CAAC,CAAC,SAAS;oBACvB,QAAQ,EAAE,CAAC,CAAC,OAAO;iBACpB,CAAC,CAAC;gBACH,MAAM,CAAC,cAAc,EAAE,CAAC;YAC1B,CAAC;YAED,sBAAsB;YACtB,IAAA,2BAAiB,EAAC,EAAE,EAAE;gBACpB,OAAO,EAAE,MAAM;gBACf,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,WAAW;gBAC7C,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,WAAW;gBAC7C,cAAc,EAAE,MAAM,CAAC,YAAY,CAAC,aAAa;gBACjD,UAAU,EAAE,MAAM,CAAC,YAAY,CAAC,SAAS;gBACzC,WAAW,EAAE,MAAM,CAAC,YAAY,CAAC,UAAU;gBAC3C,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,GAAG;gBAC5B,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC;gBACzD,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC;aAC1D,CAAC,CAAC;YAEH,mCAAmC;YACnC,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,IAAA,oCAAoB,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;gBACtD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,IAAI,IAAI,CAAC,UAAU,KAAK,UAAU;wBAAE,SAAS;oBAC7C,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;oBACpD,IAAI,CAAC,QAAQ;wBAAE,SAAS;oBACxB,MAAM,MAAM,GAAG,IAAA,2BAAiB,EAAC,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;oBACtD,IAAA,4BAAkB,EAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;oBACjF,MAAM,CAAC,kBAAkB,EAAE,CAAC;gBAC9B,CAAC;YACH,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,eAAM,CAAC,IAAI,CAAC,gCAAgC,YAAY,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9E,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;IACP,CAAC;IAED,4EAA4E;IAC5E,MAAM,aAAa,GAAG,IAAA,4BAAkB,EAAC,EAAE,CAAC,CAAC;IAC7C,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;QACtB,eAAM,CAAC,IAAI,CAAC,YAAY,aAAa,6BAA6B,CAAC,CAAC;IACtE,CAAC;IACD,IAAA,8BAAoB,EAAC,EAAE,CAAC,CAAC;IAEzB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,iBAAiB,CAAC,MAAoB;IACpD,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,MAAM,kCAAkC,CAAC,CAAC;AACrF,CAAC"}
|
package/dist/ingest/parser.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { Project } from 'ts-morph';
|
|
2
|
+
import { type ExtractedType } from './type-extractor';
|
|
3
|
+
import { type ExtractedRoute } from './route-extractor';
|
|
4
|
+
import { type ExtractedConstant } from './constant-extractor';
|
|
5
|
+
import { type ExtractedFileMetadata } from './file-metadata';
|
|
2
6
|
export interface ExtractedFunction {
|
|
3
7
|
name: string;
|
|
4
8
|
signature: string;
|
|
@@ -11,5 +15,13 @@ export interface ExtractedFunction {
|
|
|
11
15
|
}
|
|
12
16
|
export declare function createProject(repoPath: string): Project;
|
|
13
17
|
export declare function parseFile(project: Project, filePath: string): ExtractedFunction[];
|
|
18
|
+
export interface ParseFileCompleteResult {
|
|
19
|
+
functions: ExtractedFunction[];
|
|
20
|
+
types: ExtractedType[];
|
|
21
|
+
routes: ExtractedRoute[];
|
|
22
|
+
constants: ExtractedConstant[];
|
|
23
|
+
fileMetadata: ExtractedFileMetadata;
|
|
24
|
+
}
|
|
25
|
+
export declare function parseFileComplete(project: Project, filePath: string): ParseFileCompleteResult;
|
|
14
26
|
export declare function hashFileContent(content: string): string;
|
|
15
27
|
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/ingest/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAA4G,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/ingest/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAA4G,MAAM,UAAU,CAAC;AAE7I,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAuB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAElF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CASvD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAuCjF;AA2ED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,YAAY,EAAE,qBAAqB,CAAC;CACrC;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,uBAAuB,CA4C7F;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD"}
|
package/dist/ingest/parser.js
CHANGED
|
@@ -35,9 +35,14 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.createProject = createProject;
|
|
37
37
|
exports.parseFile = parseFile;
|
|
38
|
+
exports.parseFileComplete = parseFileComplete;
|
|
38
39
|
exports.hashFileContent = hashFileContent;
|
|
39
40
|
const ts_morph_1 = require("ts-morph");
|
|
40
41
|
const crypto = __importStar(require("crypto"));
|
|
42
|
+
const type_extractor_1 = require("./type-extractor");
|
|
43
|
+
const route_extractor_1 = require("./route-extractor");
|
|
44
|
+
const constant_extractor_1 = require("./constant-extractor");
|
|
45
|
+
const file_metadata_1 = require("./file-metadata");
|
|
41
46
|
function createProject(repoPath) {
|
|
42
47
|
return new ts_morph_1.Project({
|
|
43
48
|
tsConfigFilePath: undefined,
|
|
@@ -148,6 +153,49 @@ function buildSignature(fn) {
|
|
|
148
153
|
function hashCode(code) {
|
|
149
154
|
return crypto.createHash('sha256').update(code).digest('hex');
|
|
150
155
|
}
|
|
156
|
+
function parseFileComplete(project, filePath) {
|
|
157
|
+
const sourceFile = project.addSourceFileAtPath(filePath);
|
|
158
|
+
const functions = [];
|
|
159
|
+
// Extract top-level function declarations
|
|
160
|
+
for (const fn of sourceFile.getFunctions()) {
|
|
161
|
+
const extracted = extractFunctionDeclaration(fn);
|
|
162
|
+
if (extracted)
|
|
163
|
+
functions.push(extracted);
|
|
164
|
+
}
|
|
165
|
+
// Extract arrow functions assigned to variables
|
|
166
|
+
for (const varStmt of sourceFile.getVariableStatements()) {
|
|
167
|
+
for (const decl of varStmt.getDeclarations()) {
|
|
168
|
+
const initializer = decl.getInitializer();
|
|
169
|
+
if (initializer && ts_morph_1.Node.isArrowFunction(initializer)) {
|
|
170
|
+
const extracted = extractArrowFunction(decl, initializer, varStmt.isExported());
|
|
171
|
+
if (extracted)
|
|
172
|
+
functions.push(extracted);
|
|
173
|
+
}
|
|
174
|
+
if (initializer && ts_morph_1.Node.isFunctionExpression(initializer)) {
|
|
175
|
+
const extracted = extractArrowFunction(decl, initializer, varStmt.isExported());
|
|
176
|
+
if (extracted)
|
|
177
|
+
functions.push(extracted);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Extract class methods
|
|
182
|
+
for (const cls of sourceFile.getClasses()) {
|
|
183
|
+
const className = cls.getName() || 'AnonymousClass';
|
|
184
|
+
for (const method of cls.getMethods()) {
|
|
185
|
+
const extracted = extractMethodDeclaration(method, className);
|
|
186
|
+
if (extracted)
|
|
187
|
+
functions.push(extracted);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Extract new entity types
|
|
191
|
+
const types = (0, type_extractor_1.extractTypes)(sourceFile);
|
|
192
|
+
const routes = (0, route_extractor_1.extractRoutes)(sourceFile);
|
|
193
|
+
const constants = (0, constant_extractor_1.extractConstants)(sourceFile);
|
|
194
|
+
const fileMetadata = (0, file_metadata_1.extractFileMetadata)(sourceFile, functions.length, types.length, routes.length);
|
|
195
|
+
// Remove the source file from project to prevent memory bloat
|
|
196
|
+
project.removeSourceFile(sourceFile);
|
|
197
|
+
return { functions, types, routes, constants, fileMetadata };
|
|
198
|
+
}
|
|
151
199
|
function hashFileContent(content) {
|
|
152
200
|
return crypto.createHash('sha256').update(content).digest('hex');
|
|
153
201
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/ingest/parser.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/ingest/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SourceFile } from 'ts-morph';
|
|
2
|
+
export interface ExtractedRoute {
|
|
3
|
+
method: string;
|
|
4
|
+
path: string;
|
|
5
|
+
handlerName: string | null;
|
|
6
|
+
handlerBody: string;
|
|
7
|
+
middleware: string | null;
|
|
8
|
+
startLine: number;
|
|
9
|
+
endLine: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function extractRoutes(sourceFile: SourceFile): ExtractedRoute[];
|
|
12
|
+
//# sourceMappingURL=route-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-extractor.d.ts","sourceRoot":"","sources":["../../src/ingest/route-extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAoB,MAAM,UAAU,CAAC;AAExD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,wBAAgB,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,cAAc,EAAE,CA+DtE"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractRoutes = extractRoutes;
|
|
4
|
+
const ts_morph_1 = require("ts-morph");
|
|
5
|
+
const HTTP_METHODS = new Set(['get', 'post', 'put', 'delete', 'patch', 'all', 'use']);
|
|
6
|
+
function extractRoutes(sourceFile) {
|
|
7
|
+
const routes = [];
|
|
8
|
+
const callExpressions = sourceFile.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression);
|
|
9
|
+
for (const callExpr of callExpressions) {
|
|
10
|
+
const expression = callExpr.getExpression();
|
|
11
|
+
// Match patterns like router.get(...), app.post(...), *.method('/path', ...)
|
|
12
|
+
if (!ts_morph_1.Node.isPropertyAccessExpression(expression))
|
|
13
|
+
continue;
|
|
14
|
+
const methodName = expression.getName().toLowerCase();
|
|
15
|
+
if (!HTTP_METHODS.has(methodName))
|
|
16
|
+
continue;
|
|
17
|
+
const args = callExpr.getArguments();
|
|
18
|
+
if (args.length < 1)
|
|
19
|
+
continue;
|
|
20
|
+
// First argument should be a string literal path starting with '/'
|
|
21
|
+
const firstArg = args[0];
|
|
22
|
+
let routePath = null;
|
|
23
|
+
if (ts_morph_1.Node.isStringLiteral(firstArg)) {
|
|
24
|
+
routePath = firstArg.getLiteralValue();
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
// Could be a template literal or variable — skip non-literal paths
|
|
28
|
+
const text = firstArg.getText();
|
|
29
|
+
if (text.startsWith("'") || text.startsWith('"') || text.startsWith('`')) {
|
|
30
|
+
routePath = text.replace(/^['"`]|['"`]$/g, '');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (!routePath || (!routePath.startsWith('/') && methodName !== 'use'))
|
|
34
|
+
continue;
|
|
35
|
+
// Last argument is the handler
|
|
36
|
+
const lastArg = args[args.length - 1];
|
|
37
|
+
const handlerBody = lastArg.getText().substring(0, 2000); // Truncate very large handlers
|
|
38
|
+
// Try to extract handler name
|
|
39
|
+
let handlerName = null;
|
|
40
|
+
if (ts_morph_1.Node.isIdentifier(lastArg)) {
|
|
41
|
+
handlerName = lastArg.getText();
|
|
42
|
+
}
|
|
43
|
+
else if (ts_morph_1.Node.isArrowFunction(lastArg) || ts_morph_1.Node.isFunctionExpression(lastArg)) {
|
|
44
|
+
handlerName = null; // Inline handler
|
|
45
|
+
}
|
|
46
|
+
// Middleware: arguments between path and handler
|
|
47
|
+
let middleware = null;
|
|
48
|
+
if (args.length > 2) {
|
|
49
|
+
const middlewareArgs = args.slice(1, -1).map(a => a.getText());
|
|
50
|
+
middleware = JSON.stringify(middlewareArgs);
|
|
51
|
+
}
|
|
52
|
+
routes.push({
|
|
53
|
+
method: methodName.toUpperCase(),
|
|
54
|
+
path: routePath,
|
|
55
|
+
handlerName,
|
|
56
|
+
handlerBody,
|
|
57
|
+
middleware,
|
|
58
|
+
startLine: callExpr.getStartLineNumber(),
|
|
59
|
+
endLine: callExpr.getEndLineNumber(),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return routes;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=route-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-extractor.js","sourceRoot":"","sources":["../../src/ingest/route-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SourceFile } from 'ts-morph';
|
|
2
|
+
export interface ExtractedType {
|
|
3
|
+
name: string;
|
|
4
|
+
kind: 'interface' | 'type_alias' | 'enum';
|
|
5
|
+
fullText: string;
|
|
6
|
+
isExported: boolean;
|
|
7
|
+
startLine: number;
|
|
8
|
+
endLine: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function extractTypes(sourceFile: SourceFile): ExtractedType[];
|
|
11
|
+
//# sourceMappingURL=type-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-extractor.d.ts","sourceRoot":"","sources":["../../src/ingest/type-extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,GAAG,YAAY,GAAG,MAAM,CAAC;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,UAAU,GAAG,aAAa,EAAE,CA2CpE"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractTypes = extractTypes;
|
|
4
|
+
function extractTypes(sourceFile) {
|
|
5
|
+
const types = [];
|
|
6
|
+
for (const iface of sourceFile.getInterfaces()) {
|
|
7
|
+
const name = iface.getName();
|
|
8
|
+
if (!name)
|
|
9
|
+
continue;
|
|
10
|
+
types.push({
|
|
11
|
+
name,
|
|
12
|
+
kind: 'interface',
|
|
13
|
+
fullText: iface.getFullText().trim(),
|
|
14
|
+
isExported: iface.isExported(),
|
|
15
|
+
startLine: iface.getStartLineNumber(),
|
|
16
|
+
endLine: iface.getEndLineNumber(),
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
for (const alias of sourceFile.getTypeAliases()) {
|
|
20
|
+
const name = alias.getName();
|
|
21
|
+
if (!name)
|
|
22
|
+
continue;
|
|
23
|
+
types.push({
|
|
24
|
+
name,
|
|
25
|
+
kind: 'type_alias',
|
|
26
|
+
fullText: alias.getFullText().trim(),
|
|
27
|
+
isExported: alias.isExported(),
|
|
28
|
+
startLine: alias.getStartLineNumber(),
|
|
29
|
+
endLine: alias.getEndLineNumber(),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
for (const enumDecl of sourceFile.getEnums()) {
|
|
33
|
+
const name = enumDecl.getName();
|
|
34
|
+
if (!name)
|
|
35
|
+
continue;
|
|
36
|
+
types.push({
|
|
37
|
+
name,
|
|
38
|
+
kind: 'enum',
|
|
39
|
+
fullText: enumDecl.getFullText().trim(),
|
|
40
|
+
isExported: enumDecl.isExported(),
|
|
41
|
+
startLine: enumDecl.getStartLineNumber(),
|
|
42
|
+
endLine: enumDecl.getEndLineNumber(),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return types;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=type-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-extractor.js","sourceRoot":"","sources":["../../src/ingest/type-extractor.ts"],"names":[],"mappings":";;AAWA,oCA2CC;AA3CD,SAAgB,YAAY,CAAC,UAAsB;IACjD,MAAM,KAAK,GAAoB,EAAE,CAAC;IAElC,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,aAAa,EAAE,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,KAAK,CAAC,IAAI,CAAC;YACT,IAAI;YACJ,IAAI,EAAE,WAAW;YACjB,QAAQ,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE;YACpC,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE;YAC9B,SAAS,EAAE,KAAK,CAAC,kBAAkB,EAAE;YACrC,OAAO,EAAE,KAAK,CAAC,gBAAgB,EAAE;SAClC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,KAAK,CAAC,IAAI,CAAC;YACT,IAAI;YACJ,IAAI,EAAE,YAAY;YAClB,QAAQ,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE;YACpC,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE;YAC9B,SAAS,EAAE,KAAK,CAAC,kBAAkB,EAAE;YACrC,OAAO,EAAE,KAAK,CAAC,gBAAgB,EAAE;SAClC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,MAAM,QAAQ,IAAI,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,KAAK,CAAC,IAAI,CAAC;YACT,IAAI;YACJ,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE;YACvC,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE;YACjC,SAAS,EAAE,QAAQ,CAAC,kBAAkB,EAAE;YACxC,OAAO,EAAE,QAAQ,CAAC,gBAAgB,EAAE;SACrC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -1,41 +1,70 @@
|
|
|
1
|
-
# StructX — Code Intelligence Graph
|
|
1
|
+
# StructX — Code Intelligence Graph (MANDATORY)
|
|
2
2
|
|
|
3
3
|
This project uses **StructX**, a graph-powered code intelligence tool for TypeScript.
|
|
4
|
-
StructX maintains a
|
|
5
|
-
|
|
4
|
+
StructX maintains a knowledge graph of the codebase including functions, types, routes,
|
|
5
|
+
constants, and file summaries. **You MUST use StructX as your primary source of codebase
|
|
6
|
+
understanding. Do NOT read raw source files to learn about the codebase.**
|
|
6
7
|
|
|
7
|
-
##
|
|
8
|
+
## Mandatory Workflow
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
### Step 1: Initialize (ALWAYS do this first)
|
|
11
|
+
Run `npx structx status` to check the graph state.
|
|
12
|
+
- If it says "not initialized", run `npx structx setup .`
|
|
13
|
+
- If Functions/Types/Routes counts are 0, run `npx structx setup .`
|
|
14
|
+
- **Do NOT proceed to any code task until StructX is initialized and populated.**
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
### Step 2: Understand the codebase via StructX (NEVER skip this)
|
|
17
|
+
Before writing ANY code, you MUST query StructX to understand the codebase:
|
|
18
|
+
```
|
|
19
|
+
npx structx overview --repo .
|
|
20
|
+
npx structx ask "what types and interfaces exist?" --repo .
|
|
21
|
+
npx structx ask "what routes/endpoints exist?" --repo .
|
|
22
|
+
npx structx ask "how does <relevant feature> work?" --repo .
|
|
23
|
+
```
|
|
24
|
+
**You are FORBIDDEN from reading .ts source files to understand the codebase architecture,
|
|
25
|
+
discover what functions exist, learn about types, or understand how features work.
|
|
26
|
+
StructX provides all of this. Use it.**
|
|
15
27
|
|
|
16
|
-
|
|
17
|
-
|
|
28
|
+
### Step 3: Read source files ONLY for editing
|
|
29
|
+
You may ONLY use raw file reads (Read/cat) when you have ALREADY queried StructX and
|
|
30
|
+
now need to see the exact code at a specific location to make an edit. The workflow is:
|
|
31
|
+
1. Ask StructX what exists and where it is
|
|
32
|
+
2. StructX tells you the file path and line numbers
|
|
33
|
+
3. THEN read that specific file to make your edit
|
|
18
34
|
|
|
19
|
-
|
|
20
|
-
|
|
35
|
+
**Reading source files to "explore" or "understand" the codebase is PROHIBITED.
|
|
36
|
+
That is what StructX is for.**
|
|
21
37
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
38
|
+
### Step 4: After making changes
|
|
39
|
+
After editing any TypeScript files:
|
|
40
|
+
```
|
|
41
|
+
npx structx ingest .
|
|
42
|
+
npx structx analyze . --yes
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Step 5: Impact analysis before modifying existing code
|
|
46
|
+
Before changing any existing function, type, or route:
|
|
47
|
+
```
|
|
48
|
+
npx structx ask "what breaks if I change <name>?" --repo .
|
|
49
|
+
```
|
|
25
50
|
|
|
26
51
|
## Available Commands
|
|
27
52
|
|
|
28
53
|
| Command | Description |
|
|
29
54
|
|---------|-------------|
|
|
30
|
-
| `npx structx status` | Check
|
|
31
|
-
| `npx structx setup .` |
|
|
55
|
+
| `npx structx status` | Check graph state — ALWAYS run first |
|
|
56
|
+
| `npx structx setup .` | Full bootstrap (init + ingest + analyze) |
|
|
57
|
+
| `npx structx overview --repo .` | Full codebase summary in one shot |
|
|
58
|
+
| `npx structx ask "<question>" --repo .` | Query the knowledge graph |
|
|
32
59
|
| `npx structx ingest .` | Re-parse codebase after changes |
|
|
33
|
-
| `npx structx analyze . --yes` | Run semantic analysis on new/changed
|
|
34
|
-
| `npx structx ask "question" --repo .` | Query the function graph |
|
|
60
|
+
| `npx structx analyze . --yes` | Run semantic analysis on new/changed entities |
|
|
35
61
|
|
|
36
|
-
##
|
|
62
|
+
## Rules Summary
|
|
37
63
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
64
|
+
1. **ALWAYS** run `structx status` at session start
|
|
65
|
+
2. **ALWAYS** run `structx setup .` if not initialized
|
|
66
|
+
3. **ALWAYS** use `structx ask` or `structx overview` to understand the codebase
|
|
67
|
+
4. **NEVER** read .ts files to explore/understand architecture — use StructX
|
|
68
|
+
5. **ONLY** read .ts files when you know exactly what file+line to edit (from StructX output)
|
|
69
|
+
6. **ALWAYS** run `structx ingest .` after making code changes
|
|
70
|
+
7. **ALWAYS** run impact analysis before modifying existing functions
|