sdl-mcp 0.9.2 → 0.9.3

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.
@@ -2,27 +2,27 @@ import { exec, queryAll, querySingle, toNumber, toBoolean, assertSafeInt, withTr
2
2
  import { logger } from "../util/logger.js";
3
3
  const MAX_BATCH_WARNING_THRESHOLD = 5000;
4
4
  export async function upsertSymbol(conn, symbol) {
5
- await exec(conn, `MATCH (r:Repo {repoId: $repoId})
6
- MATCH (f:File {fileId: $fileId})
7
- MERGE (s:Symbol {symbolId: $symbolId})
8
- SET s.kind = $kind,
9
- s.name = $name,
10
- s.exported = $exported,
11
- s.visibility = $visibility,
12
- s.language = $language,
13
- s.rangeStartLine = $rangeStartLine,
14
- s.rangeStartCol = $rangeStartCol,
15
- s.rangeEndLine = $rangeEndLine,
16
- s.rangeEndCol = $rangeEndCol,
17
- s.astFingerprint = $astFingerprint,
18
- s.signatureJson = $signatureJson,
19
- s.summary = $summary,
20
- s.invariantsJson = $invariantsJson,
21
- s.sideEffectsJson = $sideEffectsJson,
22
- s.roleTagsJson = $roleTagsJson,
23
- s.searchText = $searchText,
24
- s.updatedAt = $updatedAt
25
- MERGE (s)-[:SYMBOL_IN_FILE]->(f)
5
+ await exec(conn, `MATCH (r:Repo {repoId: $repoId})
6
+ MATCH (f:File {fileId: $fileId})
7
+ MERGE (s:Symbol {symbolId: $symbolId})
8
+ SET s.kind = $kind,
9
+ s.name = $name,
10
+ s.exported = $exported,
11
+ s.visibility = $visibility,
12
+ s.language = $language,
13
+ s.rangeStartLine = $rangeStartLine,
14
+ s.rangeStartCol = $rangeStartCol,
15
+ s.rangeEndLine = $rangeEndLine,
16
+ s.rangeEndCol = $rangeEndCol,
17
+ s.astFingerprint = $astFingerprint,
18
+ s.signatureJson = $signatureJson,
19
+ s.summary = $summary,
20
+ s.invariantsJson = $invariantsJson,
21
+ s.sideEffectsJson = $sideEffectsJson,
22
+ s.roleTagsJson = $roleTagsJson,
23
+ s.searchText = $searchText,
24
+ s.updatedAt = $updatedAt
25
+ MERGE (s)-[:SYMBOL_IN_FILE]->(f)
26
26
  MERGE (s)-[:SYMBOL_IN_REPO]->(r)`, {
27
27
  symbolId: symbol.symbolId,
28
28
  repoId: symbol.repoId,
@@ -47,25 +47,25 @@ export async function upsertSymbol(conn, symbol) {
47
47
  });
48
48
  }
49
49
  export async function getSymbol(conn, symbolId) {
50
- const row = await querySingle(conn, `MATCH (s:Symbol {symbolId: $symbolId})-[:SYMBOL_IN_FILE]->(f:File)
51
- MATCH (s)-[:SYMBOL_IN_REPO]->(r:Repo)
52
- RETURN s.symbolId AS symbolId,
53
- r.repoId AS repoId,
54
- f.fileId AS fileId,
55
- s.kind AS kind,
56
- s.name AS name,
57
- s.exported AS exported,
58
- s.visibility AS visibility,
59
- s.language AS language,
60
- s.rangeStartLine AS rangeStartLine,
61
- s.rangeStartCol AS rangeStartCol,
62
- s.rangeEndLine AS rangeEndLine,
63
- s.rangeEndCol AS rangeEndCol,
64
- s.astFingerprint AS astFingerprint,
65
- s.signatureJson AS signatureJson,
66
- s.summary AS summary,
67
- s.invariantsJson AS invariantsJson,
68
- s.sideEffectsJson AS sideEffectsJson,
50
+ const row = await querySingle(conn, `MATCH (s:Symbol {symbolId: $symbolId})-[:SYMBOL_IN_FILE]->(f:File)
51
+ MATCH (s)-[:SYMBOL_IN_REPO]->(r:Repo)
52
+ RETURN s.symbolId AS symbolId,
53
+ r.repoId AS repoId,
54
+ f.fileId AS fileId,
55
+ s.kind AS kind,
56
+ s.name AS name,
57
+ s.exported AS exported,
58
+ s.visibility AS visibility,
59
+ s.language AS language,
60
+ s.rangeStartLine AS rangeStartLine,
61
+ s.rangeStartCol AS rangeStartCol,
62
+ s.rangeEndLine AS rangeEndLine,
63
+ s.rangeEndCol AS rangeEndCol,
64
+ s.astFingerprint AS astFingerprint,
65
+ s.signatureJson AS signatureJson,
66
+ s.summary AS summary,
67
+ s.invariantsJson AS invariantsJson,
68
+ s.sideEffectsJson AS sideEffectsJson,
69
69
  s.updatedAt AS updatedAt`, { symbolId });
70
70
  if (!row)
71
71
  return null;
@@ -91,31 +91,31 @@ export async function getSymbol(conn, symbolId) {
91
91
  };
92
92
  }
93
93
  export async function updateSymbolSummary(conn, symbolId, summary, updatedAt = new Date().toISOString()) {
94
- await exec(conn, `MATCH (s:Symbol {symbolId: $symbolId})
95
- SET s.summary = $summary,
94
+ await exec(conn, `MATCH (s:Symbol {symbolId: $symbolId})
95
+ SET s.summary = $summary,
96
96
  s.updatedAt = $updatedAt`, { symbolId, summary, updatedAt });
97
97
  }
98
98
  export async function getSymbolsByFile(conn, fileId) {
99
- const rows = await queryAll(conn, `MATCH (f:File {fileId: $fileId})<-[:SYMBOL_IN_FILE]-(s:Symbol)
100
- MATCH (s)-[:SYMBOL_IN_REPO]->(r:Repo)
101
- RETURN s.symbolId AS symbolId,
102
- r.repoId AS repoId,
103
- s.kind AS kind,
104
- s.name AS name,
105
- s.exported AS exported,
106
- s.visibility AS visibility,
107
- s.language AS language,
108
- s.rangeStartLine AS rangeStartLine,
109
- s.rangeStartCol AS rangeStartCol,
110
- s.rangeEndLine AS rangeEndLine,
111
- s.rangeEndCol AS rangeEndCol,
112
- s.astFingerprint AS astFingerprint,
113
- s.signatureJson AS signatureJson,
114
- s.summary AS summary,
115
- s.invariantsJson AS invariantsJson,
116
- s.sideEffectsJson AS sideEffectsJson,
117
- s.roleTagsJson AS roleTagsJson,
118
- s.searchText AS searchText,
99
+ const rows = await queryAll(conn, `MATCH (f:File {fileId: $fileId})<-[:SYMBOL_IN_FILE]-(s:Symbol)
100
+ MATCH (s)-[:SYMBOL_IN_REPO]->(r:Repo)
101
+ RETURN s.symbolId AS symbolId,
102
+ r.repoId AS repoId,
103
+ s.kind AS kind,
104
+ s.name AS name,
105
+ s.exported AS exported,
106
+ s.visibility AS visibility,
107
+ s.language AS language,
108
+ s.rangeStartLine AS rangeStartLine,
109
+ s.rangeStartCol AS rangeStartCol,
110
+ s.rangeEndLine AS rangeEndLine,
111
+ s.rangeEndCol AS rangeEndCol,
112
+ s.astFingerprint AS astFingerprint,
113
+ s.signatureJson AS signatureJson,
114
+ s.summary AS summary,
115
+ s.invariantsJson AS invariantsJson,
116
+ s.sideEffectsJson AS sideEffectsJson,
117
+ s.roleTagsJson AS roleTagsJson,
118
+ s.searchText AS searchText,
119
119
  s.updatedAt AS updatedAt`, { fileId });
120
120
  return rows.map((row) => ({
121
121
  symbolId: row.symbolId,
@@ -141,18 +141,18 @@ export async function getSymbolsByFile(conn, fileId) {
141
141
  }));
142
142
  }
143
143
  export async function getSymbolIdsByFile(conn, fileId) {
144
- const rows = await queryAll(conn, `MATCH (f:File {fileId: $fileId})<-[:SYMBOL_IN_FILE]-(s:Symbol)
144
+ const rows = await queryAll(conn, `MATCH (f:File {fileId: $fileId})<-[:SYMBOL_IN_FILE]-(s:Symbol)
145
145
  RETURN s.symbolId AS symbolId`, { fileId });
146
146
  return rows.map((row) => row.symbolId);
147
147
  }
148
148
  export async function getSymbolsByRepoLite(conn, repoId) {
149
- const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
150
- MATCH (s)-[:SYMBOL_IN_FILE]->(f:File)
151
- RETURN s.symbolId AS symbolId,
152
- r.repoId AS repoId,
153
- f.fileId AS fileId,
154
- s.name AS name,
155
- s.kind AS kind,
149
+ const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
150
+ MATCH (s)-[:SYMBOL_IN_FILE]->(f:File)
151
+ RETURN s.symbolId AS symbolId,
152
+ r.repoId AS repoId,
153
+ f.fileId AS fileId,
154
+ s.name AS name,
155
+ s.kind AS kind,
156
156
  s.exported AS exported`, { repoId });
157
157
  return rows.map((row) => ({
158
158
  symbolId: row.symbolId,
@@ -164,31 +164,31 @@ export async function getSymbolsByRepoLite(conn, repoId) {
164
164
  }));
165
165
  }
166
166
  export async function getSymbolIdsByRepo(conn, repoId) {
167
- const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
167
+ const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
168
168
  RETURN s.symbolId AS symbolId`, { repoId });
169
169
  return rows.map((row) => row.symbolId);
170
170
  }
171
171
  export async function getSymbolsByRepo(conn, repoId) {
172
- const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
173
- MATCH (s)-[:SYMBOL_IN_FILE]->(f:File)
174
- RETURN s.symbolId AS symbolId,
175
- f.fileId AS fileId,
176
- s.kind AS kind,
177
- s.name AS name,
178
- s.exported AS exported,
179
- s.visibility AS visibility,
180
- s.language AS language,
181
- s.rangeStartLine AS rangeStartLine,
182
- s.rangeStartCol AS rangeStartCol,
183
- s.rangeEndLine AS rangeEndLine,
184
- s.rangeEndCol AS rangeEndCol,
185
- s.astFingerprint AS astFingerprint,
186
- s.signatureJson AS signatureJson,
187
- s.summary AS summary,
188
- s.invariantsJson AS invariantsJson,
189
- s.sideEffectsJson AS sideEffectsJson,
190
- s.roleTagsJson AS roleTagsJson,
191
- s.searchText AS searchText,
172
+ const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
173
+ MATCH (s)-[:SYMBOL_IN_FILE]->(f:File)
174
+ RETURN s.symbolId AS symbolId,
175
+ f.fileId AS fileId,
176
+ s.kind AS kind,
177
+ s.name AS name,
178
+ s.exported AS exported,
179
+ s.visibility AS visibility,
180
+ s.language AS language,
181
+ s.rangeStartLine AS rangeStartLine,
182
+ s.rangeStartCol AS rangeStartCol,
183
+ s.rangeEndLine AS rangeEndLine,
184
+ s.rangeEndCol AS rangeEndCol,
185
+ s.astFingerprint AS astFingerprint,
186
+ s.signatureJson AS signatureJson,
187
+ s.summary AS summary,
188
+ s.invariantsJson AS invariantsJson,
189
+ s.sideEffectsJson AS sideEffectsJson,
190
+ s.roleTagsJson AS roleTagsJson,
191
+ s.searchText AS searchText,
192
192
  s.updatedAt AS updatedAt`, { repoId });
193
193
  return rows.map((row) => ({
194
194
  symbolId: row.symbolId,
@@ -214,17 +214,17 @@ export async function getSymbolsByRepo(conn, repoId) {
214
214
  }));
215
215
  }
216
216
  export async function getSymbolsByRepoForSnapshot(conn, repoId) {
217
- const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
218
- RETURN s.symbolId AS symbolId,
219
- s.astFingerprint AS astFingerprint,
220
- s.signatureJson AS signatureJson,
221
- s.summary AS summary,
222
- s.invariantsJson AS invariantsJson,
217
+ const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
218
+ RETURN s.symbolId AS symbolId,
219
+ s.astFingerprint AS astFingerprint,
220
+ s.signatureJson AS signatureJson,
221
+ s.summary AS summary,
222
+ s.invariantsJson AS invariantsJson,
223
223
  s.sideEffectsJson AS sideEffectsJson`, { repoId });
224
224
  return rows;
225
225
  }
226
226
  export async function getSymbolCount(conn, repoId) {
227
- const row = await querySingle(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
227
+ const row = await querySingle(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)
228
228
  RETURN count(s) AS count`, { repoId });
229
229
  return row ? toNumber(row.count) : 0;
230
230
  }
@@ -237,29 +237,29 @@ export async function getSymbolsByIds(conn, symbolIds) {
237
237
  threshold: MAX_BATCH_WARNING_THRESHOLD,
238
238
  });
239
239
  }
240
- const rows = await queryAll(conn, `MATCH (s:Symbol)
241
- WHERE s.symbolId IN $symbolIds
242
- MATCH (s)-[:SYMBOL_IN_FILE]->(f:File)
243
- MATCH (s)-[:SYMBOL_IN_REPO]->(r:Repo)
244
- RETURN s.symbolId AS symbolId,
245
- r.repoId AS repoId,
246
- f.fileId AS fileId,
247
- s.kind AS kind,
248
- s.name AS name,
249
- s.exported AS exported,
250
- s.visibility AS visibility,
251
- s.language AS language,
252
- s.rangeStartLine AS rangeStartLine,
253
- s.rangeStartCol AS rangeStartCol,
254
- s.rangeEndLine AS rangeEndLine,
255
- s.rangeEndCol AS rangeEndCol,
256
- s.astFingerprint AS astFingerprint,
257
- s.signatureJson AS signatureJson,
258
- s.summary AS summary,
259
- s.invariantsJson AS invariantsJson,
260
- s.sideEffectsJson AS sideEffectsJson,
261
- s.roleTagsJson AS roleTagsJson,
262
- s.searchText AS searchText,
240
+ const rows = await queryAll(conn, `MATCH (s:Symbol)
241
+ WHERE s.symbolId IN $symbolIds
242
+ MATCH (s)-[:SYMBOL_IN_FILE]->(f:File)
243
+ MATCH (s)-[:SYMBOL_IN_REPO]->(r:Repo)
244
+ RETURN s.symbolId AS symbolId,
245
+ r.repoId AS repoId,
246
+ f.fileId AS fileId,
247
+ s.kind AS kind,
248
+ s.name AS name,
249
+ s.exported AS exported,
250
+ s.visibility AS visibility,
251
+ s.language AS language,
252
+ s.rangeStartLine AS rangeStartLine,
253
+ s.rangeStartCol AS rangeStartCol,
254
+ s.rangeEndLine AS rangeEndLine,
255
+ s.rangeEndCol AS rangeEndCol,
256
+ s.astFingerprint AS astFingerprint,
257
+ s.signatureJson AS signatureJson,
258
+ s.summary AS summary,
259
+ s.invariantsJson AS invariantsJson,
260
+ s.sideEffectsJson AS sideEffectsJson,
261
+ s.roleTagsJson AS roleTagsJson,
262
+ s.searchText AS searchText,
263
263
  s.updatedAt AS updatedAt`, { symbolIds });
264
264
  const result = new Map();
265
265
  for (const row of rows) {
@@ -298,10 +298,10 @@ export async function getSymbolsByIdsLite(conn, symbolIds) {
298
298
  threshold: MAX_BATCH_WARNING_THRESHOLD,
299
299
  });
300
300
  }
301
- const rows = await queryAll(conn, `MATCH (s:Symbol)
302
- WHERE s.symbolId IN $symbolIds
303
- RETURN s.symbolId AS symbolId,
304
- coalesce(s.name, '') AS name,
301
+ const rows = await queryAll(conn, `MATCH (s:Symbol)
302
+ WHERE s.symbolId IN $symbolIds
303
+ RETURN s.symbolId AS symbolId,
304
+ coalesce(s.name, '') AS name,
305
305
  coalesce(s.kind, '') AS kind`, { symbolIds });
306
306
  for (const row of rows) {
307
307
  result.set(row.symbolId, {
@@ -313,33 +313,33 @@ export async function getSymbolsByIdsLite(conn, symbolIds) {
313
313
  return result;
314
314
  }
315
315
  export async function findSymbolsInRange(conn, repoId, fileId, startLine, endLine) {
316
- const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)-[:SYMBOL_IN_FILE]->(f:File {fileId: $fileId})
317
- WHERE s.rangeStartLine <= $endLine AND s.rangeEndLine >= $startLine
318
- WITH s,
319
- CASE
320
- WHEN s.rangeStartLine >= $startLine AND s.rangeEndLine <= $endLine THEN 0
321
- WHEN s.rangeStartLine <= $startLine AND s.rangeEndLine >= $endLine THEN 1
322
- WHEN s.rangeStartLine >= $startLine AND s.rangeStartLine <= $endLine THEN 2
323
- WHEN s.rangeEndLine >= $startLine AND s.rangeEndLine <= $endLine THEN 3
324
- ELSE 4
325
- END AS containmentRank,
326
- abs(s.rangeStartLine - $startLine) AS dist
327
- RETURN s.symbolId AS symbolId,
328
- s.kind AS kind,
329
- s.name AS name,
330
- s.exported AS exported,
331
- s.visibility AS visibility,
332
- s.language AS language,
333
- s.rangeStartLine AS rangeStartLine,
334
- s.rangeStartCol AS rangeStartCol,
335
- s.rangeEndLine AS rangeEndLine,
336
- s.rangeEndCol AS rangeEndCol,
337
- s.astFingerprint AS astFingerprint,
338
- s.signatureJson AS signatureJson,
339
- s.summary AS summary,
340
- s.invariantsJson AS invariantsJson,
341
- s.sideEffectsJson AS sideEffectsJson,
342
- s.updatedAt AS updatedAt
316
+ const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)-[:SYMBOL_IN_FILE]->(f:File {fileId: $fileId})
317
+ WHERE s.rangeStartLine <= $endLine AND s.rangeEndLine >= $startLine
318
+ WITH s,
319
+ CASE
320
+ WHEN s.rangeStartLine >= $startLine AND s.rangeEndLine <= $endLine THEN 0
321
+ WHEN s.rangeStartLine <= $startLine AND s.rangeEndLine >= $endLine THEN 1
322
+ WHEN s.rangeStartLine >= $startLine AND s.rangeStartLine <= $endLine THEN 2
323
+ WHEN s.rangeEndLine >= $startLine AND s.rangeEndLine <= $endLine THEN 3
324
+ ELSE 4
325
+ END AS containmentRank,
326
+ abs(s.rangeStartLine - $startLine) AS dist
327
+ RETURN s.symbolId AS symbolId,
328
+ s.kind AS kind,
329
+ s.name AS name,
330
+ s.exported AS exported,
331
+ s.visibility AS visibility,
332
+ s.language AS language,
333
+ s.rangeStartLine AS rangeStartLine,
334
+ s.rangeStartCol AS rangeStartCol,
335
+ s.rangeEndLine AS rangeEndLine,
336
+ s.rangeEndCol AS rangeEndCol,
337
+ s.astFingerprint AS astFingerprint,
338
+ s.signatureJson AS signatureJson,
339
+ s.summary AS summary,
340
+ s.invariantsJson AS invariantsJson,
341
+ s.sideEffectsJson AS sideEffectsJson,
342
+ s.updatedAt AS updatedAt
343
343
  ORDER BY containmentRank, dist`, { repoId, fileId, startLine, endLine });
344
344
  return rows.map((row) => ({
345
345
  symbolId: row.symbolId,
@@ -364,54 +364,54 @@ export async function findSymbolsInRange(conn, repoId, fileId, startLine, endLin
364
364
  }
365
365
  export async function deleteSymbolsByFileId(conn, fileId) {
366
366
  await withTransaction(conn, async (txConn) => {
367
- const symbolRows = await queryAll(txConn, `MATCH (f:File {fileId: $fileId})<-[:SYMBOL_IN_FILE]-(s:Symbol)
367
+ const symbolRows = await queryAll(txConn, `MATCH (f:File {fileId: $fileId})<-[:SYMBOL_IN_FILE]-(s:Symbol)
368
368
  RETURN s.symbolId AS symbolId`, { fileId });
369
369
  if (symbolRows.length === 0)
370
370
  return;
371
371
  const symbolIds = symbolRows.map((r) => r.symbolId);
372
372
  // Batch delete all relationships and nodes for the collected symbols
373
- await exec(txConn, `MATCH (s:Symbol)-[d:DEPENDS_ON]->(:Symbol)
374
- WHERE s.symbolId IN $symbolIds
373
+ await exec(txConn, `MATCH (s:Symbol)-[d:DEPENDS_ON]->(:Symbol)
374
+ WHERE s.symbolId IN $symbolIds
375
375
  DELETE d`, { symbolIds });
376
- await exec(txConn, `MATCH (:Symbol)-[d:DEPENDS_ON]->(s:Symbol)
377
- WHERE s.symbolId IN $symbolIds
376
+ await exec(txConn, `MATCH (:Symbol)-[d:DEPENDS_ON]->(s:Symbol)
377
+ WHERE s.symbolId IN $symbolIds
378
378
  DELETE d`, { symbolIds });
379
- await exec(txConn, `MATCH (s:Symbol)-[r:SYMBOL_IN_REPO]->(:Repo)
380
- WHERE s.symbolId IN $symbolIds
379
+ await exec(txConn, `MATCH (s:Symbol)-[r:SYMBOL_IN_REPO]->(:Repo)
380
+ WHERE s.symbolId IN $symbolIds
381
381
  DELETE r`, { symbolIds });
382
- await exec(txConn, `MATCH (s:Symbol)-[r:SYMBOL_IN_FILE]->(:File {fileId: $fileId})
383
- WHERE s.symbolId IN $symbolIds
382
+ await exec(txConn, `MATCH (s:Symbol)-[r:SYMBOL_IN_FILE]->(:File {fileId: $fileId})
383
+ WHERE s.symbolId IN $symbolIds
384
384
  DELETE r`, { symbolIds, fileId });
385
- await exec(txConn, `MATCH (s:Symbol)-[r:BELONGS_TO_CLUSTER]->(:Cluster)
386
- WHERE s.symbolId IN $symbolIds
385
+ await exec(txConn, `MATCH (s:Symbol)-[r:BELONGS_TO_CLUSTER]->(:Cluster)
386
+ WHERE s.symbolId IN $symbolIds
387
387
  DELETE r`, { symbolIds });
388
- await exec(txConn, `MATCH (s:Symbol)-[r:PARTICIPATES_IN]->(:Process)
389
- WHERE s.symbolId IN $symbolIds
388
+ await exec(txConn, `MATCH (s:Symbol)-[r:PARTICIPATES_IN]->(:Process)
389
+ WHERE s.symbolId IN $symbolIds
390
390
  DELETE r`, { symbolIds });
391
- await exec(txConn, `MATCH (m:Metrics)
392
- WHERE m.symbolId IN $symbolIds
391
+ await exec(txConn, `MATCH (m:Metrics)
392
+ WHERE m.symbolId IN $symbolIds
393
393
  DELETE m`, { symbolIds });
394
394
  // Delete SymbolEmbedding nodes
395
- await exec(txConn, `MATCH (e:SymbolEmbedding)
396
- WHERE e.symbolId IN $symbolIds
395
+ await exec(txConn, `MATCH (e:SymbolEmbedding)
396
+ WHERE e.symbolId IN $symbolIds
397
397
  DELETE e`, { symbolIds });
398
398
  // Delete SummaryCache nodes
399
- await exec(txConn, `MATCH (sc:SummaryCache)
400
- WHERE sc.symbolId IN $symbolIds
399
+ await exec(txConn, `MATCH (sc:SummaryCache)
400
+ WHERE sc.symbolId IN $symbolIds
401
401
  DELETE sc`, { symbolIds });
402
402
  // Delete SymbolReference nodes for this file
403
- await exec(txConn, `MATCH (sr:SymbolReference)
404
- WHERE sr.fileId = $fileId
403
+ await exec(txConn, `MATCH (sr:SymbolReference)
404
+ WHERE sr.fileId = $fileId
405
405
  DELETE sr`, { fileId });
406
406
  // Delete MEMORY_OF edges (Memory -> deleted Symbol)
407
- await exec(txConn, `MATCH (mem:Memory)-[r:MEMORY_OF]->(s:Symbol)
408
- WHERE s.symbolId IN $symbolIds
407
+ await exec(txConn, `MATCH (mem:Memory)-[r:MEMORY_OF]->(s:Symbol)
408
+ WHERE s.symbolId IN $symbolIds
409
409
  DELETE r`, { symbolIds });
410
410
  // Delete MEMORY_OF_FILE edges (Memory -> deleted File)
411
- await exec(txConn, `MATCH (mem:Memory)-[r:MEMORY_OF_FILE]->(f:File {fileId: $fileId})
411
+ await exec(txConn, `MATCH (mem:Memory)-[r:MEMORY_OF_FILE]->(f:File {fileId: $fileId})
412
412
  DELETE r`, { fileId });
413
- await exec(txConn, `MATCH (s:Symbol)
414
- WHERE s.symbolId IN $symbolIds
413
+ await exec(txConn, `MATCH (s:Symbol)
414
+ WHERE s.symbolId IN $symbolIds
415
415
  DELETE s`, { symbolIds });
416
416
  });
417
417
  }
@@ -438,57 +438,57 @@ function mapSearchSymbolRow(row, repoId) {
438
438
  };
439
439
  }
440
440
  async function searchSymbolsSingleTerm(conn, repoId, term) {
441
- return queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)-[:SYMBOL_IN_FILE]->(f:File)
442
- WHERE lower(s.name) CONTAINS lower($query)
443
- OR lower(coalesce(s.summary, '')) CONTAINS lower($query)
444
- OR lower(coalesce(s.searchText, '')) CONTAINS lower($query)
445
- WITH s, f,
446
- CASE WHEN s.name = $query THEN 0 ELSE 1 END AS exactNameRank,
447
- CASE WHEN lower(s.name) = lower($query) THEN 0 ELSE 1 END AS ciExactNameRank,
448
- CASE
449
- WHEN lower(coalesce(s.searchText, '')) CONTAINS $queryPadded
450
- OR lower(coalesce(s.searchText, '')) STARTS WITH $queryStart
451
- OR lower(coalesce(s.searchText, '')) ENDS WITH $queryEnd
452
- THEN 0 ELSE 1
453
- END AS wordBoundaryRank,
454
- CASE
455
- WHEN f.relPath CONTAINS '/adapter/' THEN 2
456
- WHEN f.relPath CONTAINS '/tests/' OR f.relPath STARTS WITH 'tests/' THEN 2
457
- WHEN f.relPath STARTS WITH 'scripts/' THEN 2
458
- WHEN f.relPath CONTAINS '.test.' OR f.relPath CONTAINS '.spec.' THEN 2
459
- WHEN f.relPath CONTAINS 'target/' THEN 2
460
- WHEN f.relPath CONTAINS 'vendor/' THEN 2
461
- ELSE 0
462
- END AS filePenalty,
463
- CASE s.kind
464
- WHEN 'class' THEN 0
465
- WHEN 'function' THEN 1
466
- WHEN 'interface' THEN 2
467
- WHEN 'type' THEN 3
468
- WHEN 'method' THEN 4
469
- WHEN 'constructor' THEN 5
470
- WHEN 'module' THEN 6
471
- ELSE 7
472
- END AS kindRank,
473
- CASE WHEN lower(s.name) CONTAINS lower($query) THEN 0 ELSE 1 END AS nameMatchRank
474
- RETURN s.symbolId AS symbolId,
475
- f.fileId AS fileId,
476
- s.kind AS kind,
477
- s.name AS name,
478
- s.exported AS exported,
479
- s.visibility AS visibility,
480
- s.language AS language,
481
- s.rangeStartLine AS rangeStartLine,
482
- s.rangeStartCol AS rangeStartCol,
483
- s.rangeEndLine AS rangeEndLine,
484
- s.rangeEndCol AS rangeEndCol,
485
- s.astFingerprint AS astFingerprint,
486
- s.signatureJson AS signatureJson,
487
- s.summary AS summary,
488
- s.invariantsJson AS invariantsJson,
489
- s.sideEffectsJson AS sideEffectsJson,
490
- s.updatedAt AS updatedAt
491
- ORDER BY exactNameRank, ciExactNameRank, wordBoundaryRank, filePenalty, kindRank, nameMatchRank
441
+ return queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)-[:SYMBOL_IN_FILE]->(f:File)
442
+ WHERE lower(s.name) CONTAINS lower($query)
443
+ OR lower(coalesce(s.summary, '')) CONTAINS lower($query)
444
+ OR lower(coalesce(s.searchText, '')) CONTAINS lower($query)
445
+ WITH s, f,
446
+ CASE WHEN s.name = $query THEN 0 ELSE 1 END AS exactNameRank,
447
+ CASE WHEN lower(s.name) = lower($query) THEN 0 ELSE 1 END AS ciExactNameRank,
448
+ CASE
449
+ WHEN lower(coalesce(s.searchText, '')) CONTAINS $queryPadded
450
+ OR lower(coalesce(s.searchText, '')) STARTS WITH $queryStart
451
+ OR lower(coalesce(s.searchText, '')) ENDS WITH $queryEnd
452
+ THEN 0 ELSE 1
453
+ END AS wordBoundaryRank,
454
+ CASE
455
+ WHEN f.relPath CONTAINS '/adapter/' THEN 2
456
+ WHEN f.relPath CONTAINS '/tests/' OR f.relPath STARTS WITH 'tests/' THEN 2
457
+ WHEN f.relPath STARTS WITH 'scripts/' THEN 2
458
+ WHEN f.relPath CONTAINS '.test.' OR f.relPath CONTAINS '.spec.' THEN 2
459
+ WHEN f.relPath CONTAINS 'target/' THEN 2
460
+ WHEN f.relPath CONTAINS 'vendor/' THEN 2
461
+ ELSE 0
462
+ END AS filePenalty,
463
+ CASE s.kind
464
+ WHEN 'class' THEN 0
465
+ WHEN 'function' THEN 1
466
+ WHEN 'interface' THEN 2
467
+ WHEN 'type' THEN 3
468
+ WHEN 'method' THEN 4
469
+ WHEN 'constructor' THEN 5
470
+ WHEN 'module' THEN 6
471
+ ELSE 7
472
+ END AS kindRank,
473
+ CASE WHEN lower(s.name) CONTAINS lower($query) THEN 0 ELSE 1 END AS nameMatchRank
474
+ RETURN s.symbolId AS symbolId,
475
+ f.fileId AS fileId,
476
+ s.kind AS kind,
477
+ s.name AS name,
478
+ s.exported AS exported,
479
+ s.visibility AS visibility,
480
+ s.language AS language,
481
+ s.rangeStartLine AS rangeStartLine,
482
+ s.rangeStartCol AS rangeStartCol,
483
+ s.rangeEndLine AS rangeEndLine,
484
+ s.rangeEndCol AS rangeEndCol,
485
+ s.astFingerprint AS astFingerprint,
486
+ s.signatureJson AS signatureJson,
487
+ s.summary AS summary,
488
+ s.invariantsJson AS invariantsJson,
489
+ s.sideEffectsJson AS sideEffectsJson,
490
+ s.updatedAt AS updatedAt
491
+ ORDER BY exactNameRank, ciExactNameRank, wordBoundaryRank, filePenalty, kindRank, nameMatchRank
492
492
  LIMIT $limit`, { repoId, query: term, queryPadded: ` ${term.toLowerCase()} `, queryStart: `${term.toLowerCase()} `, queryEnd: ` ${term.toLowerCase()}`, limit: 200 });
493
493
  }
494
494
  export async function searchSymbols(conn, repoId, query, limit) {
@@ -541,44 +541,44 @@ export function splitSearchTerms(query) {
541
541
  return trimmed.split(/\s+/).filter((t) => t.length > 0);
542
542
  }
543
543
  async function searchSymbolsLiteSingleTerm(conn, repoId, term) {
544
- return queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)-[:SYMBOL_IN_FILE]->(f:File)
545
- WHERE lower(s.name) CONTAINS lower($query)
546
- OR lower(coalesce(s.summary, '')) CONTAINS lower($query)
547
- OR lower(coalesce(s.searchText, '')) CONTAINS lower($query)
548
- WITH s, f,
549
- CASE WHEN s.name = $query THEN 0 ELSE 1 END AS exactNameRank,
550
- CASE WHEN lower(s.name) = lower($query) THEN 0 ELSE 1 END AS ciExactNameRank,
551
- CASE
552
- WHEN lower(coalesce(s.searchText, '')) CONTAINS $queryPadded
553
- OR lower(coalesce(s.searchText, '')) STARTS WITH $queryStart
554
- OR lower(coalesce(s.searchText, '')) ENDS WITH $queryEnd
555
- THEN 0 ELSE 1
556
- END AS wordBoundaryRank,
557
- CASE
558
- WHEN f.relPath CONTAINS '/adapter/' THEN 2
559
- WHEN f.relPath CONTAINS '/tests/' OR f.relPath STARTS WITH 'tests/' THEN 2
560
- WHEN f.relPath STARTS WITH 'scripts/' THEN 2
561
- WHEN f.relPath CONTAINS '.test.' OR f.relPath CONTAINS '.spec.' THEN 2
562
- WHEN f.relPath CONTAINS 'target/' THEN 2
563
- WHEN f.relPath CONTAINS 'vendor/' THEN 2
564
- ELSE 0
565
- END AS filePenalty,
566
- CASE s.kind
567
- WHEN 'class' THEN 0
568
- WHEN 'function' THEN 1
569
- WHEN 'interface' THEN 2
570
- WHEN 'type' THEN 3
571
- WHEN 'method' THEN 4
572
- WHEN 'constructor' THEN 5
573
- WHEN 'module' THEN 6
574
- ELSE 7
575
- END AS kindRank,
576
- CASE WHEN lower(s.name) CONTAINS lower($query) THEN 0 ELSE 1 END AS nameMatchRank
577
- RETURN s.symbolId AS symbolId,
578
- s.name AS name,
579
- f.fileId AS fileId,
580
- s.kind AS kind
581
- ORDER BY exactNameRank, ciExactNameRank, wordBoundaryRank, filePenalty, kindRank, nameMatchRank
544
+ return queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol)-[:SYMBOL_IN_FILE]->(f:File)
545
+ WHERE lower(s.name) CONTAINS lower($query)
546
+ OR lower(coalesce(s.summary, '')) CONTAINS lower($query)
547
+ OR lower(coalesce(s.searchText, '')) CONTAINS lower($query)
548
+ WITH s, f,
549
+ CASE WHEN s.name = $query THEN 0 ELSE 1 END AS exactNameRank,
550
+ CASE WHEN lower(s.name) = lower($query) THEN 0 ELSE 1 END AS ciExactNameRank,
551
+ CASE
552
+ WHEN lower(coalesce(s.searchText, '')) CONTAINS $queryPadded
553
+ OR lower(coalesce(s.searchText, '')) STARTS WITH $queryStart
554
+ OR lower(coalesce(s.searchText, '')) ENDS WITH $queryEnd
555
+ THEN 0 ELSE 1
556
+ END AS wordBoundaryRank,
557
+ CASE
558
+ WHEN f.relPath CONTAINS '/adapter/' THEN 2
559
+ WHEN f.relPath CONTAINS '/tests/' OR f.relPath STARTS WITH 'tests/' THEN 2
560
+ WHEN f.relPath STARTS WITH 'scripts/' THEN 2
561
+ WHEN f.relPath CONTAINS '.test.' OR f.relPath CONTAINS '.spec.' THEN 2
562
+ WHEN f.relPath CONTAINS 'target/' THEN 2
563
+ WHEN f.relPath CONTAINS 'vendor/' THEN 2
564
+ ELSE 0
565
+ END AS filePenalty,
566
+ CASE s.kind
567
+ WHEN 'class' THEN 0
568
+ WHEN 'function' THEN 1
569
+ WHEN 'interface' THEN 2
570
+ WHEN 'type' THEN 3
571
+ WHEN 'method' THEN 4
572
+ WHEN 'constructor' THEN 5
573
+ WHEN 'module' THEN 6
574
+ ELSE 7
575
+ END AS kindRank,
576
+ CASE WHEN lower(s.name) CONTAINS lower($query) THEN 0 ELSE 1 END AS nameMatchRank
577
+ RETURN s.symbolId AS symbolId,
578
+ s.name AS name,
579
+ f.fileId AS fileId,
580
+ s.kind AS kind
581
+ ORDER BY exactNameRank, ciExactNameRank, wordBoundaryRank, filePenalty, kindRank, nameMatchRank
582
582
  LIMIT $limit`, { repoId, query: term, queryPadded: ` ${term.toLowerCase()} `, queryStart: `${term.toLowerCase()} `, queryEnd: ` ${term.toLowerCase()}`, limit: 200 });
583
583
  }
584
584
  export async function searchSymbolsLite(conn, repoId, query, limit) {
@@ -622,19 +622,19 @@ export async function searchSymbolsLite(conn, repoId, query, limit) {
622
622
  */
623
623
  export async function resolveSymbolByShorthand(conn, repoId, relPath, symbolName) {
624
624
  const normalizedPath = relPath.replace(/\\/g, "/");
625
- const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol {name: $name})-[:SYMBOL_IN_FILE]->(f:File)
626
- WHERE f.relPath ENDS WITH $relPath
627
- RETURN s.symbolId AS symbolId, s.kind AS kind
628
- ORDER BY CASE s.kind
629
- WHEN 'class' THEN 0
630
- WHEN 'function' THEN 1
631
- WHEN 'interface' THEN 2
632
- WHEN 'type' THEN 3
633
- WHEN 'method' THEN 4
634
- WHEN 'constructor' THEN 5
635
- WHEN 'module' THEN 6
636
- ELSE 7
637
- END
625
+ const rows = await queryAll(conn, `MATCH (r:Repo {repoId: $repoId})<-[:SYMBOL_IN_REPO]-(s:Symbol {name: $name})-[:SYMBOL_IN_FILE]->(f:File)
626
+ WHERE f.relPath ENDS WITH $relPath
627
+ RETURN s.symbolId AS symbolId, s.kind AS kind
628
+ ORDER BY CASE s.kind
629
+ WHEN 'class' THEN 0
630
+ WHEN 'function' THEN 1
631
+ WHEN 'interface' THEN 2
632
+ WHEN 'type' THEN 3
633
+ WHEN 'method' THEN 4
634
+ WHEN 'constructor' THEN 5
635
+ WHEN 'module' THEN 6
636
+ ELSE 7
637
+ END
638
638
  LIMIT 5`, { repoId, name: symbolName, relPath: normalizedPath });
639
639
  if (rows.length === 0)
640
640
  return null;