project-librarian 0.5.4 → 0.5.6

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.
Files changed (46) hide show
  1. package/CONTRIBUTING.md +36 -0
  2. package/README.ko.md +57 -360
  3. package/README.md +56 -359
  4. package/dist/args.js +6 -1
  5. package/dist/code-index/extractors/light-languages.js +285 -0
  6. package/dist/code-index/extractors/registry.js +12 -0
  7. package/dist/code-index/extractors/shared.js +18 -1
  8. package/dist/code-index/extractors/typescript.js +30 -16
  9. package/dist/code-index/modes.js +136 -32
  10. package/dist/code-index/native-helper-matrix.js +99 -0
  11. package/dist/code-index/native-helper.js +292 -0
  12. package/dist/code-index/ownership.js +8 -6
  13. package/dist/code-index/schema.js +72 -13
  14. package/dist/code-index/search.js +1 -1
  15. package/dist/code-index-db.js +20 -12
  16. package/dist/code-index-file-policy.js +17 -11
  17. package/dist/code-index.js +365 -13
  18. package/dist/hooks.js +5 -5
  19. package/dist/init-project-wiki.js +7 -1
  20. package/dist/install-skill.js +99 -6
  21. package/dist/mcp-server.js +4 -4
  22. package/dist/migration.js +27 -2
  23. package/dist/native/darwin-arm64/project-librarian-indexer +0 -0
  24. package/dist/native/darwin-x64/project-librarian-indexer +0 -0
  25. package/dist/native/linux-arm64/project-librarian-indexer +0 -0
  26. package/dist/native/linux-arm64-musl/project-librarian-indexer +0 -0
  27. package/dist/native/linux-x64/project-librarian-indexer +0 -0
  28. package/dist/native/linux-x64-musl/project-librarian-indexer +0 -0
  29. package/dist/native/project-librarian-indexer-manifest.json +70 -0
  30. package/dist/native/win32-arm64/project-librarian-indexer.exe +0 -0
  31. package/dist/native/win32-x64/project-librarian-indexer.exe +0 -0
  32. package/dist/templates.js +4 -3
  33. package/dist/workspace.js +137 -10
  34. package/docs/README.md +11 -0
  35. package/docs/benchmarks.md +64 -0
  36. package/docs/cli-reference.md +60 -0
  37. package/docs/code-evidence.md +87 -0
  38. package/docs/ko/README.md +13 -0
  39. package/docs/ko/benchmarks.md +64 -0
  40. package/docs/ko/cli-reference.md +60 -0
  41. package/docs/ko/code-evidence.md +87 -0
  42. package/docs/ko/maintainer.md +76 -0
  43. package/docs/ko/usage.md +167 -0
  44. package/docs/maintainer.md +76 -0
  45. package/docs/usage.md +175 -0
  46. package/package.json +13 -2
@@ -1,8 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.genericLightProfileByLanguage = void 0;
3
4
  exports.indexPythonLight = indexPythonLight;
4
5
  exports.indexGoLight = indexGoLight;
6
+ exports.indexGenericLight = indexGenericLight;
5
7
  const shared_1 = require("./shared");
8
+ exports.genericLightProfileByLanguage = {
9
+ c: "c-light",
10
+ cpp: "cpp-light",
11
+ csharp: "csharp-light",
12
+ java: "java-light",
13
+ kotlin: "kotlin-light",
14
+ php: "php-light",
15
+ rust: "rust-light",
16
+ swift: "swift-light",
17
+ };
6
18
  function indexPythonLight(file, statements) {
7
19
  const symbolPatterns = [
8
20
  [/^\s*def\s+([A-Za-z_]\w*)\s*\(([^)]*)\)/gm, "function", (match) => `def ${match[1] ?? ""}(${match[2] ?? ""})`],
@@ -50,3 +62,276 @@ function indexGoLight(file, statements) {
50
62
  }
51
63
  });
52
64
  }
65
+ function indexGenericLight(file, statements, language) {
66
+ let phpTypeDepth = 0;
67
+ for (const [index, rawLine] of file.text.split("\n").entries()) {
68
+ const line = rawLine.replace(/\r$/, "");
69
+ const lineNumberOneBased = index + 1;
70
+ const trimmed = normalizeGenericLightLine(line, language);
71
+ if (!trimmed || genericLineIsComment(trimmed, language)) {
72
+ phpTypeDepth += braceDelta(trimmed);
73
+ continue;
74
+ }
75
+ const imported = genericLightImport(trimmed, language);
76
+ if (imported) {
77
+ statements.insertImport.run(file.path, imported.toRef, imported.imported, lineNumberOneBased, imported.raw);
78
+ (0, shared_1.insertEdge)(statements, imported.edgeKind, "file", file.path, "module", imported.toRef, file, lineNumberOneBased, imported.raw);
79
+ }
80
+ const symbol = genericLightSymbol(trimmed, language, phpTypeDepth > 0);
81
+ if (symbol)
82
+ (0, shared_1.insertSymbol)(statements, symbol.name, symbol.kind, file, lineNumberOneBased, symbol.signature);
83
+ phpTypeDepth += braceDelta(trimmed);
84
+ }
85
+ }
86
+ function normalizeGenericLightLine(line, language) {
87
+ const trimmed = line.trim();
88
+ if (language === "php")
89
+ return trimmed.replace(/^<\?php\s*/, "");
90
+ if (language === "java" || language === "kotlin" || language === "swift")
91
+ return stripLeadingAtAnnotations(trimmed);
92
+ return trimmed;
93
+ }
94
+ function stripLeadingAtAnnotations(line) {
95
+ let rest = line;
96
+ while (true) {
97
+ const match = rest.match(/^@[A-Za-z_][\w.]*(:[A-Za-z_]\w*)?(?:\([^)]*\))?\s*/);
98
+ if (!match)
99
+ return rest;
100
+ rest = rest.slice(match[0].length).trimStart();
101
+ }
102
+ }
103
+ function genericLineIsComment(line, language) {
104
+ if (line.startsWith("//") || line.startsWith("/*") || line.startsWith("*"))
105
+ return true;
106
+ if (language === "php" && line.startsWith("#"))
107
+ return true;
108
+ return false;
109
+ }
110
+ function braceDelta(line) {
111
+ let delta = 0;
112
+ let quote = "";
113
+ let escaped = false;
114
+ for (const ch of line) {
115
+ if (quote) {
116
+ if (escaped)
117
+ escaped = false;
118
+ else if (ch === "\\")
119
+ escaped = true;
120
+ else if (ch === quote)
121
+ quote = "";
122
+ continue;
123
+ }
124
+ if (ch === "\"" || ch === "'" || ch === "`") {
125
+ quote = ch;
126
+ continue;
127
+ }
128
+ if (ch === "{")
129
+ delta += 1;
130
+ else if (ch === "}")
131
+ delta -= 1;
132
+ }
133
+ return delta;
134
+ }
135
+ function genericLightImport(line, language) {
136
+ if (language === "c" || language === "cpp") {
137
+ const include = line.match(/^#\s*include\s*[<"]([^>"]+)[>"]/);
138
+ if (include?.[1])
139
+ return { edgeKind: "import", imported: "", raw: include[0], toRef: include[1] };
140
+ if (language === "cpp") {
141
+ const using = line.match(/^using\s+(?:namespace\s+)?([A-Za-z_]\w*(?:::[A-Za-z_]\w*)*)\s*;?/);
142
+ if (using?.[1])
143
+ return { edgeKind: "import", imported: "", raw: line.replace(/;$/, ""), toRef: using[1] };
144
+ }
145
+ return null;
146
+ }
147
+ if (language === "rust") {
148
+ const rustUse = line.match(/^use\s+(.+?)\s*;?$/);
149
+ if (rustUse?.[1])
150
+ return { edgeKind: "use", imported: "", raw: line.replace(/;$/, ""), toRef: rustUse[1].replace(/\s+/g, " ").trim() };
151
+ return null;
152
+ }
153
+ if (language === "php") {
154
+ const phpUse = line.match(/^use\s+([^;]+)\s*;?/);
155
+ if (phpUse?.[1])
156
+ return { edgeKind: "import", imported: "", raw: line.replace(/;$/, ""), toRef: phpUse[1].replace(/\s+/g, " ").trim() };
157
+ return null;
158
+ }
159
+ if (language === "csharp") {
160
+ const using = line.match(/^using\s+([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\s*;?/);
161
+ if (using?.[1])
162
+ return { edgeKind: "import", imported: "", raw: line.replace(/;$/, ""), toRef: using[1] };
163
+ return null;
164
+ }
165
+ if (language === "swift") {
166
+ const imported = line.match(/^import\s+([A-Za-z_]\w*)/);
167
+ if (imported?.[1])
168
+ return { edgeKind: "import", imported: "", raw: imported[0], toRef: imported[1] };
169
+ return null;
170
+ }
171
+ const imported = line.match(/^import\s+([A-Za-z_]\w*(?:[.*$][A-Za-z_]\w*)*(?:\.\*)?)\s*;?/);
172
+ if (imported?.[1])
173
+ return { edgeKind: "import", imported: "", raw: line.replace(/;$/, ""), toRef: imported[1] };
174
+ return null;
175
+ }
176
+ function genericLightSymbol(line, language, phpInsideType) {
177
+ if (language === "rust")
178
+ return rustLightSymbol(line);
179
+ if (language === "kotlin")
180
+ return kotlinLightSymbol(line);
181
+ if (language === "swift")
182
+ return swiftLightSymbol(line);
183
+ if (language === "php")
184
+ return phpLightSymbol(line, phpInsideType);
185
+ if (language === "c" || language === "cpp")
186
+ return cFamilyLightSymbol(line, language);
187
+ if (language === "java" || language === "csharp")
188
+ return jvmOrCsharpLightSymbol(line, language);
189
+ return null;
190
+ }
191
+ function rustLightSymbol(line) {
192
+ const fn = line.match(/^(?:pub(?:\([^)]*\))?\s+)?(?:async\s+)?fn\s+([A-Za-z_]\w*)/);
193
+ if (fn?.[1])
194
+ return symbol("function", fn[1], line);
195
+ for (const [keyword, kind] of [["struct", "struct"], ["enum", "enum"], ["trait", "trait"]]) {
196
+ const found = line.match(new RegExp(`^(?:pub(?:\\([^)]*\\))?\\s+)?${keyword}\\s+([A-Za-z_]\\w*)`));
197
+ if (found?.[1])
198
+ return symbol(kind, found[1], line);
199
+ }
200
+ const implName = rustImplName(line);
201
+ if (implName)
202
+ return symbol("impl", implName, line);
203
+ return null;
204
+ }
205
+ function rustImplName(line) {
206
+ let rest = line.replace(/^unsafe\s+/, "");
207
+ if (!rest.startsWith("impl"))
208
+ return "";
209
+ rest = rest.slice("impl".length);
210
+ if (rest.startsWith("<")) {
211
+ const genericEnd = matchingAngleEnd(rest);
212
+ if (genericEnd <= 1)
213
+ return "";
214
+ const afterGeneric = rest.slice(genericEnd + 1);
215
+ if (!/^\s+/.test(afterGeneric))
216
+ return "";
217
+ rest = afterGeneric.trimStart();
218
+ }
219
+ else if (/^\s+/.test(rest)) {
220
+ rest = rest.trimStart();
221
+ }
222
+ else {
223
+ return "";
224
+ }
225
+ const forIndex = rest.lastIndexOf(" for ");
226
+ if (forIndex !== -1) {
227
+ const afterForName = rest.slice(forIndex + " for ".length).trimStart().match(/^([A-Za-z_]\w*)/);
228
+ if (afterForName?.[1])
229
+ return afterForName[1];
230
+ rest = rest.slice(0, forIndex).trimEnd();
231
+ }
232
+ return rest.match(/^([A-Za-z_]\w*)/)?.[1] ?? "";
233
+ }
234
+ function matchingAngleEnd(text) {
235
+ let depth = 0;
236
+ for (let index = 0; index < text.length; index += 1) {
237
+ const ch = text[index];
238
+ if (ch === "<")
239
+ depth += 1;
240
+ else if (ch === ">") {
241
+ depth -= 1;
242
+ if (depth === 0)
243
+ return index;
244
+ }
245
+ }
246
+ return -1;
247
+ }
248
+ function kotlinLightSymbol(line) {
249
+ const fn = line.match(/^(?:[\w\s]+\s+)?fun\s+(?:[A-Za-z_]\w*\.)?([A-Za-z_]\w*)/);
250
+ if (fn?.[1])
251
+ return symbol("function", fn[1], line);
252
+ const klass = line.match(/^(?:[\w\s]+\s+)?(?:data\s+|sealed\s+|open\s+)?(class|interface)\s+([A-Za-z_]\w*)/);
253
+ if (klass?.[2])
254
+ return symbol(klass[1] === "interface" ? "interface" : "class", klass[2], line);
255
+ const object = line.match(/^(?:[\w\s]+\s+)?object\s+([A-Za-z_]\w*)/);
256
+ if (object?.[1])
257
+ return symbol("object", object[1], line);
258
+ return null;
259
+ }
260
+ function swiftLightSymbol(line) {
261
+ const fn = line.match(/^(?:[\w\s]+\s+)?func\s+([A-Za-z_]\w*)/);
262
+ if (fn?.[1])
263
+ return symbol("function", fn[1], line);
264
+ for (const [keyword, kind] of [["class", "class"], ["struct", "struct"], ["protocol", "protocol"], ["enum", "enum"]]) {
265
+ const found = line.match(new RegExp(`^(?:[\\w\\s]+\\s+)?${keyword}\\s+([A-Za-z_]\\w*)`));
266
+ if (found?.[1])
267
+ return symbol(kind, found[1], line);
268
+ }
269
+ return null;
270
+ }
271
+ function phpLightSymbol(line, insideType) {
272
+ for (const [keyword, kind] of [["class", "class"], ["interface", "interface"], ["trait", "trait"]]) {
273
+ const found = line.match(new RegExp(`^(?:abstract\\s+|final\\s+)?${keyword}\\s+([A-Za-z_]\\w*)`));
274
+ if (found?.[1])
275
+ return symbol(kind, found[1], line);
276
+ }
277
+ const fn = line.match(/^(?:public\s+|private\s+|protected\s+|static\s+|final\s+|abstract\s+)*function\s+&?\s*([A-Za-z_]\w*)/);
278
+ if (fn?.[1])
279
+ return symbol(insideType ? "method" : "function", fn[1], line);
280
+ return null;
281
+ }
282
+ function cFamilyLightSymbol(line, language) {
283
+ if (language === "cpp") {
284
+ const namespace = line.match(/^namespace\s+([A-Za-z_]\w*)/);
285
+ if (namespace?.[1])
286
+ return symbol("namespace", namespace[1], line);
287
+ const klass = line.match(/^(?:template\s*<[^>]+>\s*)?(class|struct)\s+([A-Za-z_]\w*)/);
288
+ if (klass?.[2])
289
+ return symbol(klass[1] === "class" ? "class" : "struct", klass[2], line);
290
+ const enumMatch = line.match(/^enum(?:\s+class)?\s+([A-Za-z_]\w*)/);
291
+ if (enumMatch?.[1])
292
+ return symbol("enum", enumMatch[1], line);
293
+ }
294
+ else {
295
+ const struct = line.match(/^struct\s+([A-Za-z_]\w*)/);
296
+ if (struct?.[1])
297
+ return symbol("struct", struct[1], line);
298
+ const enumMatch = line.match(/^enum\s+([A-Za-z_]\w*)/);
299
+ if (enumMatch?.[1])
300
+ return symbol("enum", enumMatch[1], line);
301
+ }
302
+ const functionName = cLikeFunctionName(line);
303
+ if (functionName)
304
+ return symbol("function", functionName, line);
305
+ return null;
306
+ }
307
+ function jvmOrCsharpLightSymbol(line, language) {
308
+ for (const [keyword, kind] of [
309
+ ["class", "class"],
310
+ ["interface", "interface"],
311
+ ["enum", "enum"],
312
+ ...(language === "csharp" ? [["struct", "struct"]] : []),
313
+ ]) {
314
+ const found = line.match(new RegExp(`^(?:[\\w\\s]+\\s+)?${keyword}\\s+([A-Za-z_]\\w*)`));
315
+ if (found?.[1])
316
+ return symbol(kind, found[1], line);
317
+ }
318
+ const methodName = cLikeFunctionName(line);
319
+ if (methodName)
320
+ return symbol("method", methodName, line);
321
+ return null;
322
+ }
323
+ function cLikeFunctionName(line) {
324
+ if (!line.includes("(") || line.endsWith(";") || line.startsWith("#"))
325
+ return "";
326
+ const firstToken = line.split(/\s+/, 1)[0] ?? "";
327
+ if (["if", "for", "while", "switch", "catch", "return", "new", "throw"].includes(firstToken))
328
+ return "";
329
+ const beforeParen = line.slice(0, line.indexOf("(")).trim();
330
+ const name = beforeParen.match(/(?:^|[\s:*&~])([A-Za-z_]\w*)$/)?.[1] ?? "";
331
+ if (["if", "for", "while", "switch", "catch", "return", "sizeof"].includes(name))
332
+ return "";
333
+ return name;
334
+ }
335
+ function symbol(kind, name, line) {
336
+ return { kind, name, signature: (0, shared_1.oneLine)(line) };
337
+ }
@@ -81,11 +81,16 @@ function extractionProfile(relativePath, language, parserMode) {
81
81
  return "python-light";
82
82
  if (language === "go")
83
83
  return "go-light";
84
+ if (isGenericLightLanguage(language))
85
+ return light_languages_1.genericLightProfileByLanguage[language];
84
86
  return "inventory-only";
85
87
  }
86
88
  function isJavaScriptLikeProfileInput(language) {
87
89
  return language === "javascript" || language === "typescript";
88
90
  }
91
+ function isGenericLightLanguage(language) {
92
+ return ["c", "cpp", "csharp", "java", "kotlin", "php", "rust", "swift"].includes(language);
93
+ }
89
94
  function createExtractionBackendRegistry(fail) {
90
95
  const extractionBackends = [
91
96
  {
@@ -109,6 +114,13 @@ function createExtractionBackendRegistry(fail) {
109
114
  profile: "go-light",
110
115
  strength: "light",
111
116
  },
117
+ ...Object.entries(light_languages_1.genericLightProfileByLanguage).map(([language, profile]) => ({
118
+ id: "regex-light",
119
+ index: (file, statements) => (0, light_languages_1.indexGenericLight)(file, statements, language),
120
+ label: `${language} lightweight regex`,
121
+ profile,
122
+ strength: "light",
123
+ })),
112
124
  ...(0, tree_sitter_1.treeSitterBackends)(fail),
113
125
  {
114
126
  id: "config-key-value",
@@ -7,7 +7,24 @@ exports.insertEdge = insertEdge;
7
7
  exports.insertMatches = insertMatches;
8
8
  exports.insertGoImport = insertGoImport;
9
9
  function oneLine(text) {
10
- return text.replace(/\s+/g, " ").trim().slice(0, 240);
10
+ let output = "";
11
+ let pendingSpace = false;
12
+ for (let index = 0; index < text.length && output.length < 240; index += 1) {
13
+ const code = text.charCodeAt(index);
14
+ if (code === 9 || code === 10 || code === 11 || code === 12 || code === 13 || code === 32) {
15
+ if (output.length > 0)
16
+ pendingSpace = true;
17
+ continue;
18
+ }
19
+ if (pendingSpace) {
20
+ output += " ";
21
+ pendingSpace = false;
22
+ if (output.length >= 240)
23
+ break;
24
+ }
25
+ output += text[index];
26
+ }
27
+ return output;
11
28
  }
12
29
  function lineNumber(text, index) {
13
30
  return text.slice(0, index).split(/\r?\n/).length;
@@ -138,18 +138,22 @@ function signatureFor(node, sourceFile) {
138
138
  return (0, shared_1.oneLine)(node.getText(sourceFile));
139
139
  }
140
140
  function indexJavaScriptLike(file, statements) {
141
- const sourceFile = ts.createSourceFile(file.path, file.text, ts.ScriptTarget.Latest, true, scriptKindForPath(file.path));
141
+ const sourceFile = ts.createSourceFile(file.path, file.text, ts.ScriptTarget.Latest, false, scriptKindForPath(file.path));
142
142
  function visit(node, context) {
143
143
  let nextContext = context;
144
144
  if (ts.isFunctionDeclaration(node)) {
145
145
  const name = node.name?.text ?? "";
146
- (0, shared_1.insertSymbol)(statements, name, "function", file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
146
+ const line = tsLine(sourceFile, node);
147
+ const signature = signatureFor(node, sourceFile);
148
+ (0, shared_1.insertSymbol)(statements, name, "function", file, line, signature);
147
149
  if (name)
148
150
  nextContext = name;
149
151
  }
150
152
  else if (ts.isClassDeclaration(node)) {
151
153
  const name = node.name?.text ?? "";
152
- (0, shared_1.insertSymbol)(statements, name, "class", file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
154
+ const line = tsLine(sourceFile, node);
155
+ const signature = signatureFor(node, sourceFile);
156
+ (0, shared_1.insertSymbol)(statements, name, "class", file, line, signature);
153
157
  if (name)
154
158
  nextContext = name;
155
159
  }
@@ -164,45 +168,55 @@ function indexJavaScriptLike(file, statements) {
164
168
  }
165
169
  else if (ts.isMethodDeclaration(node)) {
166
170
  const name = propertyNameText(node.name, sourceFile);
167
- (0, shared_1.insertSymbol)(statements, name, "method", file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
171
+ const line = tsLine(sourceFile, node);
172
+ const signature = signatureFor(node, sourceFile);
173
+ (0, shared_1.insertSymbol)(statements, name, "method", file, line, signature);
168
174
  for (const route of routeFromDecorator(node, sourceFile)) {
169
- statements.insertRoute.run(route.method, route.route, file.path, tsLine(sourceFile, node), name);
170
- (0, shared_1.insertEdge)(statements, "route_to_handler", "route", `${route.method} ${route.route}`, "symbol", name, file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
175
+ statements.insertRoute.run(route.method, route.route, file.path, line, name);
176
+ (0, shared_1.insertEdge)(statements, "route_to_handler", "route", `${route.method} ${route.route}`, "symbol", name, file, line, signature);
171
177
  }
172
178
  if (name)
173
179
  nextContext = name;
174
180
  }
175
181
  else if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {
176
182
  const symbolKind = node.initializer && (ts.isArrowFunction(node.initializer) || ts.isFunctionExpression(node.initializer)) ? "function" : "variable";
177
- (0, shared_1.insertSymbol)(statements, node.name.text, symbolKind, file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
183
+ const line = tsLine(sourceFile, node);
184
+ const signature = signatureFor(node, sourceFile);
185
+ (0, shared_1.insertSymbol)(statements, node.name.text, symbolKind, file, line, signature);
178
186
  if (symbolKind === "function")
179
187
  nextContext = node.name.text;
180
188
  }
181
189
  else if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
182
190
  const imported = importBindingText(node.importClause, sourceFile);
183
- statements.insertImport.run(file.path, node.moduleSpecifier.text, imported, tsLine(sourceFile, node), signatureFor(node, sourceFile));
184
- (0, shared_1.insertEdge)(statements, "import", "file", file.path, "module", node.moduleSpecifier.text, file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
191
+ const line = tsLine(sourceFile, node);
192
+ const signature = signatureFor(node, sourceFile);
193
+ statements.insertImport.run(file.path, node.moduleSpecifier.text, imported, line, signature);
194
+ (0, shared_1.insertEdge)(statements, "import", "file", file.path, "module", node.moduleSpecifier.text, file, line, signature);
185
195
  }
186
196
  else if (ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
187
197
  const exported = node.exportClause ? (0, shared_1.oneLine)(node.exportClause.getText(sourceFile)) : "";
188
- statements.insertImport.run(file.path, node.moduleSpecifier.text, exported, tsLine(sourceFile, node), signatureFor(node, sourceFile));
189
- (0, shared_1.insertEdge)(statements, "export", "file", file.path, "module", node.moduleSpecifier.text, file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
198
+ const line = tsLine(sourceFile, node);
199
+ const signature = signatureFor(node, sourceFile);
200
+ statements.insertImport.run(file.path, node.moduleSpecifier.text, exported, line, signature);
201
+ (0, shared_1.insertEdge)(statements, "export", "file", file.path, "module", node.moduleSpecifier.text, file, line, signature);
190
202
  }
191
203
  else if (ts.isCallExpression(node)) {
204
+ const line = tsLine(sourceFile, node);
205
+ const signature = signatureFor(node, sourceFile);
192
206
  const route = routeFromCall(node, sourceFile);
193
207
  if (route) {
194
- statements.insertRoute.run(route.method, route.route, file.path, tsLine(sourceFile, node), route.handler);
195
- (0, shared_1.insertEdge)(statements, "route_to_handler", "route", `${route.method} ${route.route}`, "symbol", route.handler, file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
208
+ statements.insertRoute.run(route.method, route.route, file.path, line, route.handler);
209
+ (0, shared_1.insertEdge)(statements, "route_to_handler", "route", `${route.method} ${route.route}`, "symbol", route.handler, file, line, signature);
196
210
  }
197
211
  if (ts.isIdentifier(node.expression) && node.expression.text === "require") {
198
212
  const moduleName = stringArg(node.arguments[0]);
199
213
  if (moduleName) {
200
- statements.insertImport.run(file.path, moduleName, "", tsLine(sourceFile, node), signatureFor(node, sourceFile));
201
- (0, shared_1.insertEdge)(statements, "import", "file", file.path, "module", moduleName, file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
214
+ statements.insertImport.run(file.path, moduleName, "", line, signature);
215
+ (0, shared_1.insertEdge)(statements, "import", "file", file.path, "module", moduleName, file, line, signature);
202
216
  }
203
217
  }
204
218
  else {
205
- (0, shared_1.insertEdge)(statements, "call", context ? "symbol" : "file", context || file.path, "symbol", callTarget(node.expression, sourceFile), file, tsLine(sourceFile, node), signatureFor(node, sourceFile));
219
+ (0, shared_1.insertEdge)(statements, "call", context ? "symbol" : "file", context || file.path, "symbol", callTarget(node.expression, sourceFile), file, line, signature);
206
220
  }
207
221
  }
208
222
  ts.forEachChild(node, (child) => visit(child, nextContext));