codeseeker 1.7.2 → 1.7.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.
@@ -22,10 +22,10 @@ class AnalysisRepository {
22
22
  try {
23
23
  const pgClient = await this.dbConnections.getPostgresConnection();
24
24
  const id = (0, uuid_1.v4)();
25
- const query = `
26
- INSERT INTO analysis_results (id, project_id, tool_name, timestamp, analysis, summary, file_count, has_issues)
27
- VALUES ($1, $2, $3, NOW(), $4, $5, $6, $7)
28
- RETURNING id
25
+ const query = `
26
+ INSERT INTO analysis_results (id, project_id, tool_name, timestamp, analysis, summary, file_count, has_issues)
27
+ VALUES ($1, $2, $3, NOW(), $4, $5, $6, $7)
28
+ RETURNING id
29
29
  `;
30
30
  const values = [
31
31
  id,
@@ -51,10 +51,10 @@ class AnalysisRepository {
51
51
  async getAnalysisHistory(projectId, toolName, limit = 10) {
52
52
  try {
53
53
  const pgClient = await this.dbConnections.getPostgresConnection();
54
- let query = `
55
- SELECT id, project_id, tool_name, timestamp, analysis, summary, file_count, has_issues
56
- FROM analysis_results
57
- WHERE project_id = $1
54
+ let query = `
55
+ SELECT id, project_id, tool_name, timestamp, analysis, summary, file_count, has_issues
56
+ FROM analysis_results
57
+ WHERE project_id = $1
58
58
  `;
59
59
  const values = [projectId];
60
60
  if (toolName) {
@@ -92,12 +92,12 @@ class AnalysisRepository {
92
92
  async getLatestAnalysis(projectId, toolName) {
93
93
  try {
94
94
  const pgClient = await this.dbConnections.getPostgresConnection();
95
- const query = `
96
- SELECT id, project_id, tool_name, timestamp, analysis, summary, file_count, has_issues
97
- FROM analysis_results
98
- WHERE project_id = $1 AND tool_name = $2
99
- ORDER BY timestamp DESC
100
- LIMIT 1
95
+ const query = `
96
+ SELECT id, project_id, tool_name, timestamp, analysis, summary, file_count, has_issues
97
+ FROM analysis_results
98
+ WHERE project_id = $1 AND tool_name = $2
99
+ ORDER BY timestamp DESC
100
+ LIMIT 1
101
101
  `;
102
102
  const result = await pgClient.query(query, [projectId, toolName]);
103
103
  if (result.rows.length === 0) {
@@ -126,17 +126,17 @@ class AnalysisRepository {
126
126
  async searchAnalysis(projectId, query) {
127
127
  try {
128
128
  const pgClient = await this.dbConnections.getPostgresConnection();
129
- const searchQuery = `
130
- SELECT id, project_id, tool_name, timestamp, analysis, summary, file_count, has_issues
131
- FROM analysis_results
132
- WHERE project_id = $1
133
- AND (
134
- tool_name ILIKE $2
135
- OR summary ILIKE $2
136
- OR analysis::text ILIKE $2
137
- )
138
- ORDER BY timestamp DESC
139
- LIMIT 50
129
+ const searchQuery = `
130
+ SELECT id, project_id, tool_name, timestamp, analysis, summary, file_count, has_issues
131
+ FROM analysis_results
132
+ WHERE project_id = $1
133
+ AND (
134
+ tool_name ILIKE $2
135
+ OR summary ILIKE $2
136
+ OR analysis::text ILIKE $2
137
+ )
138
+ ORDER BY timestamp DESC
139
+ LIMIT 50
140
140
  `;
141
141
  const searchPattern = `%${query}%`;
142
142
  const result = await pgClient.query(searchQuery, [projectId, searchPattern]);
@@ -164,9 +164,9 @@ class AnalysisRepository {
164
164
  async deleteProjectAnalysis(projectId) {
165
165
  try {
166
166
  const pgClient = await this.dbConnections.getPostgresConnection();
167
- const query = `
168
- DELETE FROM analysis_results
169
- WHERE project_id = $1
167
+ const query = `
168
+ DELETE FROM analysis_results
169
+ WHERE project_id = $1
170
170
  `;
171
171
  const result = await pgClient.query(query, [projectId]);
172
172
  this.logger.info(`Deleted ${result.rowCount} analysis records for project ${projectId}`);
@@ -452,28 +452,28 @@ class DocumentationRAGService {
452
452
  // Database operations
453
453
  async createDocumentationTables() {
454
454
  const client = await this.dbConnections.getPostgresConnection();
455
- await client.query(`
456
- CREATE TABLE IF NOT EXISTS documentation_chunks (
457
- id VARCHAR(64) PRIMARY KEY,
458
- file_path TEXT NOT NULL,
459
- title TEXT NOT NULL,
460
- content TEXT NOT NULL,
461
- chunk_index INTEGER NOT NULL,
462
- hash VARCHAR(64) NOT NULL,
463
- document_type VARCHAR(32) NOT NULL,
464
- metadata JSONB NOT NULL,
465
- embedding vector(384),
466
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
467
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
468
- );
469
-
470
- CREATE INDEX IF NOT EXISTS idx_documentation_chunks_embedding ON documentation_chunks
471
- USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
472
-
473
- CREATE INDEX IF NOT EXISTS idx_documentation_chunks_type ON documentation_chunks (document_type);
474
- CREATE INDEX IF NOT EXISTS idx_documentation_chunks_file_path ON documentation_chunks (file_path);
475
- CREATE INDEX IF NOT EXISTS idx_documentation_chunks_tech_stack ON documentation_chunks
476
- USING gin ((metadata->'techStack'));
455
+ await client.query(`
456
+ CREATE TABLE IF NOT EXISTS documentation_chunks (
457
+ id VARCHAR(64) PRIMARY KEY,
458
+ file_path TEXT NOT NULL,
459
+ title TEXT NOT NULL,
460
+ content TEXT NOT NULL,
461
+ chunk_index INTEGER NOT NULL,
462
+ hash VARCHAR(64) NOT NULL,
463
+ document_type VARCHAR(32) NOT NULL,
464
+ metadata JSONB NOT NULL,
465
+ embedding vector(384),
466
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
467
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
468
+ );
469
+
470
+ CREATE INDEX IF NOT EXISTS idx_documentation_chunks_embedding ON documentation_chunks
471
+ USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
472
+
473
+ CREATE INDEX IF NOT EXISTS idx_documentation_chunks_type ON documentation_chunks (document_type);
474
+ CREATE INDEX IF NOT EXISTS idx_documentation_chunks_file_path ON documentation_chunks (file_path);
475
+ CREATE INDEX IF NOT EXISTS idx_documentation_chunks_tech_stack ON documentation_chunks
476
+ USING gin ((metadata->'techStack'));
477
477
  `);
478
478
  this.logger.debug('📚 Documentation tables created/verified');
479
479
  }
@@ -481,15 +481,15 @@ class DocumentationRAGService {
481
481
  const client = await this.dbConnections.getPostgresConnection();
482
482
  // Generate embedding
483
483
  const embedding = await this.embeddingService.generateEmbedding(`${chunk.title}\n${chunk.content}`, chunk.filePath);
484
- await client.query(`
485
- INSERT INTO documentation_chunks (
486
- id, file_path, title, content, chunk_index, hash, document_type, metadata, embedding
487
- ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
488
- ON CONFLICT (id) DO UPDATE SET
489
- content = EXCLUDED.content,
490
- metadata = EXCLUDED.metadata,
491
- embedding = EXCLUDED.embedding,
492
- updated_at = CURRENT_TIMESTAMP
484
+ await client.query(`
485
+ INSERT INTO documentation_chunks (
486
+ id, file_path, title, content, chunk_index, hash, document_type, metadata, embedding
487
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
488
+ ON CONFLICT (id) DO UPDATE SET
489
+ content = EXCLUDED.content,
490
+ metadata = EXCLUDED.metadata,
491
+ embedding = EXCLUDED.embedding,
492
+ updated_at = CURRENT_TIMESTAMP
493
493
  `, [
494
494
  chunk.id,
495
495
  chunk.filePath,
@@ -517,15 +517,15 @@ class DocumentationRAGService {
517
517
  params.push(techStack);
518
518
  paramIndex++;
519
519
  }
520
- const query = `
521
- SELECT
522
- id, file_path, title, content, chunk_index, hash, document_type, metadata,
523
- 1 - (embedding <=> $1::vector) as similarity
524
- FROM documentation_chunks
525
- WHERE 1 - (embedding <=> $1::vector) > ${minSimilarity}
526
- ${whereClause}
527
- ORDER BY embedding <=> $1::vector
528
- LIMIT $2
520
+ const query = `
521
+ SELECT
522
+ id, file_path, title, content, chunk_index, hash, document_type, metadata,
523
+ 1 - (embedding <=> $1::vector) as similarity
524
+ FROM documentation_chunks
525
+ WHERE 1 - (embedding <=> $1::vector) > ${minSimilarity}
526
+ ${whereClause}
527
+ ORDER BY embedding <=> $1::vector
528
+ LIMIT $2
529
529
  `;
530
530
  const result = await client.query(query, params);
531
531
  return result.rows.map(row => ({
@@ -77,20 +77,20 @@ class SQLiteVectorStore {
77
77
  }
78
78
  initializeSchema() {
79
79
  // Main documents table
80
- this.db.exec(`
81
- CREATE TABLE IF NOT EXISTS documents (
82
- id TEXT PRIMARY KEY,
83
- project_id TEXT NOT NULL,
84
- file_path TEXT NOT NULL,
85
- content TEXT NOT NULL,
86
- embedding BLOB NOT NULL,
87
- metadata TEXT,
88
- created_at TEXT NOT NULL,
89
- updated_at TEXT NOT NULL
90
- );
91
-
92
- CREATE INDEX IF NOT EXISTS idx_documents_project ON documents(project_id);
93
- CREATE INDEX IF NOT EXISTS idx_documents_file ON documents(file_path);
80
+ this.db.exec(`
81
+ CREATE TABLE IF NOT EXISTS documents (
82
+ id TEXT PRIMARY KEY,
83
+ project_id TEXT NOT NULL,
84
+ file_path TEXT NOT NULL,
85
+ content TEXT NOT NULL,
86
+ embedding BLOB NOT NULL,
87
+ metadata TEXT,
88
+ created_at TEXT NOT NULL,
89
+ updated_at TEXT NOT NULL
90
+ );
91
+
92
+ CREATE INDEX IF NOT EXISTS idx_documents_project ON documents(project_id);
93
+ CREATE INDEX IF NOT EXISTS idx_documents_file ON documents(file_path);
94
94
  `);
95
95
  // Note: FTS5 virtual table removed - now using MiniSearch for text search
96
96
  // MiniSearch provides better reliability (no sync issues) and synonym support
@@ -139,16 +139,16 @@ class SQLiteVectorStore {
139
139
  const now = new Date().toISOString();
140
140
  const embeddingBlob = this.serializeEmbedding(doc.embedding);
141
141
  const metadata = doc.metadata ? JSON.stringify(doc.metadata) : null;
142
- const stmt = this.db.prepare(`
143
- INSERT INTO documents (id, project_id, file_path, content, embedding, metadata, created_at, updated_at)
144
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
145
- ON CONFLICT(id) DO UPDATE SET
146
- project_id = excluded.project_id,
147
- file_path = excluded.file_path,
148
- content = excluded.content,
149
- embedding = excluded.embedding,
150
- metadata = excluded.metadata,
151
- updated_at = excluded.updated_at
142
+ const stmt = this.db.prepare(`
143
+ INSERT INTO documents (id, project_id, file_path, content, embedding, metadata, created_at, updated_at)
144
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
145
+ ON CONFLICT(id) DO UPDATE SET
146
+ project_id = excluded.project_id,
147
+ file_path = excluded.file_path,
148
+ content = excluded.content,
149
+ embedding = excluded.embedding,
150
+ metadata = excluded.metadata,
151
+ updated_at = excluded.updated_at
152
152
  `);
153
153
  stmt.run(doc.id, doc.projectId, doc.filePath, doc.content, embeddingBlob, metadata, now, now);
154
154
  // Also index in MiniSearch for text search
@@ -163,16 +163,16 @@ class SQLiteVectorStore {
163
163
  }
164
164
  async upsertMany(docs) {
165
165
  const now = new Date().toISOString();
166
- const stmt = this.db.prepare(`
167
- INSERT INTO documents (id, project_id, file_path, content, embedding, metadata, created_at, updated_at)
168
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
169
- ON CONFLICT(id) DO UPDATE SET
170
- project_id = excluded.project_id,
171
- file_path = excluded.file_path,
172
- content = excluded.content,
173
- embedding = excluded.embedding,
174
- metadata = excluded.metadata,
175
- updated_at = excluded.updated_at
166
+ const stmt = this.db.prepare(`
167
+ INSERT INTO documents (id, project_id, file_path, content, embedding, metadata, created_at, updated_at)
168
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
169
+ ON CONFLICT(id) DO UPDATE SET
170
+ project_id = excluded.project_id,
171
+ file_path = excluded.file_path,
172
+ content = excluded.content,
173
+ embedding = excluded.embedding,
174
+ metadata = excluded.metadata,
175
+ updated_at = excluded.updated_at
176
176
  `);
177
177
  const insertMany = this.db.transaction((documents) => {
178
178
  for (const doc of documents) {
@@ -194,10 +194,10 @@ class SQLiteVectorStore {
194
194
  }
195
195
  async searchByVector(embedding, projectId, limit = 10) {
196
196
  // Get all documents for this project
197
- const stmt = this.db.prepare(`
198
- SELECT id, project_id, file_path, content, embedding, metadata, created_at, updated_at
199
- FROM documents
200
- WHERE project_id = ?
197
+ const stmt = this.db.prepare(`
198
+ SELECT id, project_id, file_path, content, embedding, metadata, created_at, updated_at
199
+ FROM documents
200
+ WHERE project_id = ?
201
201
  `);
202
202
  const rows = stmt.all(projectId);
203
203
  // Compute similarities
@@ -231,10 +231,10 @@ class SQLiteVectorStore {
231
231
  // Get full document data with embeddings from SQLite
232
232
  const results = [];
233
233
  for (const textResult of textResults) {
234
- const row = this.db.prepare(`
235
- SELECT id, project_id, file_path, content, embedding, metadata, created_at, updated_at
236
- FROM documents
237
- WHERE id = ?
234
+ const row = this.db.prepare(`
235
+ SELECT id, project_id, file_path, content, embedding, metadata, created_at, updated_at
236
+ FROM documents
237
+ WHERE id = ?
238
238
  `).get(textResult.document.id);
239
239
  if (row) {
240
240
  results.push({
@@ -402,15 +402,15 @@ class SQLiteVectorStore {
402
402
  return 0;
403
403
  // Get IDs of documents to delete for MiniSearch removal
404
404
  const placeholders = filePaths.map(() => '?').join(',');
405
- const selectStmt = this.db.prepare(`
406
- SELECT id FROM documents
407
- WHERE project_id = ? AND file_path IN (${placeholders})
405
+ const selectStmt = this.db.prepare(`
406
+ SELECT id FROM documents
407
+ WHERE project_id = ? AND file_path IN (${placeholders})
408
408
  `);
409
409
  const docsToDelete = selectStmt.all(projectId, ...filePaths);
410
410
  // Delete from SQLite
411
- const deleteStmt = this.db.prepare(`
412
- DELETE FROM documents
413
- WHERE project_id = ? AND file_path IN (${placeholders})
411
+ const deleteStmt = this.db.prepare(`
412
+ DELETE FROM documents
413
+ WHERE project_id = ? AND file_path IN (${placeholders})
414
414
  `);
415
415
  const result = deleteStmt.run(projectId, ...filePaths);
416
416
  // Also remove from MiniSearch
@@ -443,10 +443,10 @@ class SQLiteVectorStore {
443
443
  // Returns hash + indexedAt for two-stage change detection:
444
444
  // 1. Quick mtime check (~0.1ms) - if file mtime <= indexedAt, skip
445
445
  // 2. Hash check only if mtime changed (~1-5ms)
446
- const stmt = this.db.prepare(`
447
- SELECT metadata FROM documents
448
- WHERE project_id = ? AND file_path = ?
449
- LIMIT 1
446
+ const stmt = this.db.prepare(`
447
+ SELECT metadata FROM documents
448
+ WHERE project_id = ? AND file_path = ?
449
+ LIMIT 1
450
450
  `);
451
451
  const result = stmt.get(projectId, filePath);
452
452
  if (!result?.metadata) {
@@ -466,11 +466,11 @@ class SQLiteVectorStore {
466
466
  async getFileHashes(projectId) {
467
467
  // Get all unique file paths and their hashes for incremental indexing
468
468
  // Uses DISTINCT ON equivalent via GROUP BY to get one row per file
469
- const stmt = this.db.prepare(`
470
- SELECT file_path, metadata
471
- FROM documents
472
- WHERE project_id = ?
473
- GROUP BY file_path
469
+ const stmt = this.db.prepare(`
470
+ SELECT file_path, metadata
471
+ FROM documents
472
+ WHERE project_id = ?
473
+ GROUP BY file_path
474
474
  `);
475
475
  const results = stmt.all(projectId);
476
476
  const hashes = new Map();
@@ -38,17 +38,17 @@ class Neo4jGraphStore {
38
38
  const session = this.driver.session({ database: this.database });
39
39
  try {
40
40
  // Create indexes for fast lookups
41
- await session.run(`
42
- CREATE INDEX node_id IF NOT EXISTS FOR (n:CodeNode) ON (n.id)
41
+ await session.run(`
42
+ CREATE INDEX node_id IF NOT EXISTS FOR (n:CodeNode) ON (n.id)
43
43
  `);
44
- await session.run(`
45
- CREATE INDEX node_project IF NOT EXISTS FOR (n:CodeNode) ON (n.projectId)
44
+ await session.run(`
45
+ CREATE INDEX node_project IF NOT EXISTS FOR (n:CodeNode) ON (n.projectId)
46
46
  `);
47
- await session.run(`
48
- CREATE INDEX node_type IF NOT EXISTS FOR (n:CodeNode) ON (n.type)
47
+ await session.run(`
48
+ CREATE INDEX node_type IF NOT EXISTS FOR (n:CodeNode) ON (n.type)
49
49
  `);
50
- await session.run(`
51
- CREATE INDEX node_filepath IF NOT EXISTS FOR (n:CodeNode) ON (n.filePath)
50
+ await session.run(`
51
+ CREATE INDEX node_filepath IF NOT EXISTS FOR (n:CodeNode) ON (n.filePath)
52
52
  `);
53
53
  this.initialized = true;
54
54
  }
@@ -60,13 +60,13 @@ class Neo4jGraphStore {
60
60
  await this.initialize();
61
61
  const session = this.driver.session({ database: this.database });
62
62
  try {
63
- await session.run(`
64
- MERGE (n:CodeNode {id: $id})
65
- SET n.type = $type,
66
- n.name = $name,
67
- n.filePath = $filePath,
68
- n.projectId = $projectId,
69
- n.properties = $properties
63
+ await session.run(`
64
+ MERGE (n:CodeNode {id: $id})
65
+ SET n.type = $type,
66
+ n.name = $name,
67
+ n.filePath = $filePath,
68
+ n.projectId = $projectId,
69
+ n.properties = $properties
70
70
  `, {
71
71
  id: node.id,
72
72
  type: node.type,
@@ -86,11 +86,11 @@ class Neo4jGraphStore {
86
86
  try {
87
87
  // Use dynamic relationship type
88
88
  const relType = edge.type.toUpperCase();
89
- await session.run(`
90
- MATCH (source:CodeNode {id: $sourceId})
91
- MATCH (target:CodeNode {id: $targetId})
92
- MERGE (source)-[r:${relType} {id: $edgeId}]->(target)
93
- SET r.properties = $properties
89
+ await session.run(`
90
+ MATCH (source:CodeNode {id: $sourceId})
91
+ MATCH (target:CodeNode {id: $targetId})
92
+ MERGE (source)-[r:${relType} {id: $edgeId}]->(target)
93
+ SET r.properties = $properties
94
94
  `, {
95
95
  sourceId: edge.source,
96
96
  targetId: edge.target,
@@ -108,13 +108,13 @@ class Neo4jGraphStore {
108
108
  try {
109
109
  await session.executeWrite(async (tx) => {
110
110
  for (const node of nodes) {
111
- await tx.run(`
112
- MERGE (n:CodeNode {id: $id})
113
- SET n.type = $type,
114
- n.name = $name,
115
- n.filePath = $filePath,
116
- n.projectId = $projectId,
117
- n.properties = $properties
111
+ await tx.run(`
112
+ MERGE (n:CodeNode {id: $id})
113
+ SET n.type = $type,
114
+ n.name = $name,
115
+ n.filePath = $filePath,
116
+ n.projectId = $projectId,
117
+ n.properties = $properties
118
118
  `, {
119
119
  id: node.id,
120
120
  type: node.type,
@@ -137,11 +137,11 @@ class Neo4jGraphStore {
137
137
  await session.executeWrite(async (tx) => {
138
138
  for (const edge of edges) {
139
139
  const relType = edge.type.toUpperCase();
140
- await tx.run(`
141
- MATCH (source:CodeNode {id: $sourceId})
142
- MATCH (target:CodeNode {id: $targetId})
143
- MERGE (source)-[r:${relType} {id: $edgeId}]->(target)
144
- SET r.properties = $properties
140
+ await tx.run(`
141
+ MATCH (source:CodeNode {id: $sourceId})
142
+ MATCH (target:CodeNode {id: $targetId})
143
+ MERGE (source)-[r:${relType} {id: $edgeId}]->(target)
144
+ SET r.properties = $properties
145
145
  `, {
146
146
  sourceId: edge.source,
147
147
  targetId: edge.target,
@@ -162,18 +162,18 @@ class Neo4jGraphStore {
162
162
  let query;
163
163
  let params;
164
164
  if (type) {
165
- query = `
166
- MATCH (n:CodeNode)
167
- WHERE n.projectId = $projectId AND n.type = $type
168
- RETURN n
165
+ query = `
166
+ MATCH (n:CodeNode)
167
+ WHERE n.projectId = $projectId AND n.type = $type
168
+ RETURN n
169
169
  `;
170
170
  params = { projectId, type };
171
171
  }
172
172
  else {
173
- query = `
174
- MATCH (n:CodeNode)
175
- WHERE n.projectId = $projectId
176
- RETURN n
173
+ query = `
174
+ MATCH (n:CodeNode)
175
+ WHERE n.projectId = $projectId
176
+ RETURN n
177
177
  `;
178
178
  params = { projectId };
179
179
  }
@@ -188,9 +188,9 @@ class Neo4jGraphStore {
188
188
  await this.initialize();
189
189
  const session = this.driver.session({ database: this.database });
190
190
  try {
191
- const result = await session.run(`
192
- MATCH (n:CodeNode {id: $id})
193
- RETURN n
191
+ const result = await session.run(`
192
+ MATCH (n:CodeNode {id: $id})
193
+ RETURN n
194
194
  `, { id });
195
195
  if (result.records.length === 0)
196
196
  return null;
@@ -206,25 +206,25 @@ class Neo4jGraphStore {
206
206
  try {
207
207
  let query;
208
208
  if (direction === 'out') {
209
- query = `
210
- MATCH (n:CodeNode {id: $nodeId})-[r]->(target)
211
- RETURN r, n.id as sourceId, target.id as targetId, type(r) as relType
209
+ query = `
210
+ MATCH (n:CodeNode {id: $nodeId})-[r]->(target)
211
+ RETURN r, n.id as sourceId, target.id as targetId, type(r) as relType
212
212
  `;
213
213
  }
214
214
  else if (direction === 'in') {
215
- query = `
216
- MATCH (source)-[r]->(n:CodeNode {id: $nodeId})
217
- RETURN r, source.id as sourceId, n.id as targetId, type(r) as relType
215
+ query = `
216
+ MATCH (source)-[r]->(n:CodeNode {id: $nodeId})
217
+ RETURN r, source.id as sourceId, n.id as targetId, type(r) as relType
218
218
  `;
219
219
  }
220
220
  else {
221
- query = `
222
- MATCH (n:CodeNode {id: $nodeId})-[r]-(other)
223
- WITH r,
224
- CASE WHEN startNode(r).id = $nodeId THEN startNode(r).id ELSE endNode(r).id END as sourceId,
225
- CASE WHEN startNode(r).id = $nodeId THEN endNode(r).id ELSE startNode(r).id END as targetId,
226
- type(r) as relType
227
- RETURN DISTINCT r, sourceId, targetId, relType
221
+ query = `
222
+ MATCH (n:CodeNode {id: $nodeId})-[r]-(other)
223
+ WITH r,
224
+ CASE WHEN startNode(r).id = $nodeId THEN startNode(r).id ELSE endNode(r).id END as sourceId,
225
+ CASE WHEN startNode(r).id = $nodeId THEN endNode(r).id ELSE startNode(r).id END as targetId,
226
+ type(r) as relType
227
+ RETURN DISTINCT r, sourceId, targetId, relType
228
228
  `;
229
229
  }
230
230
  const result = await session.run(query, { nodeId });
@@ -242,15 +242,15 @@ class Neo4jGraphStore {
242
242
  const params = { nodeId };
243
243
  if (edgeType) {
244
244
  const relType = edgeType.toUpperCase();
245
- query = `
246
- MATCH (n:CodeNode {id: $nodeId})-[:${relType}]-(neighbor)
247
- RETURN DISTINCT neighbor
245
+ query = `
246
+ MATCH (n:CodeNode {id: $nodeId})-[:${relType}]-(neighbor)
247
+ RETURN DISTINCT neighbor
248
248
  `;
249
249
  }
250
250
  else {
251
- query = `
252
- MATCH (n:CodeNode {id: $nodeId})--(neighbor)
253
- RETURN DISTINCT neighbor
251
+ query = `
252
+ MATCH (n:CodeNode {id: $nodeId})--(neighbor)
253
+ RETURN DISTINCT neighbor
254
254
  `;
255
255
  }
256
256
  const result = await session.run(query, params);
@@ -264,11 +264,11 @@ class Neo4jGraphStore {
264
264
  await this.initialize();
265
265
  const session = this.driver.session({ database: this.database });
266
266
  try {
267
- const result = await session.run(`
268
- MATCH path = shortestPath(
269
- (source:CodeNode {id: $sourceId})-[*1..${maxDepth}]-(target:CodeNode {id: $targetId})
270
- )
271
- RETURN nodes(path) as pathNodes
267
+ const result = await session.run(`
268
+ MATCH path = shortestPath(
269
+ (source:CodeNode {id: $sourceId})-[*1..${maxDepth}]-(target:CodeNode {id: $targetId})
270
+ )
271
+ RETURN nodes(path) as pathNodes
272
272
  `, { sourceId, targetId });
273
273
  if (result.records.length === 0)
274
274
  return [];
@@ -283,10 +283,10 @@ class Neo4jGraphStore {
283
283
  await this.initialize();
284
284
  const session = this.driver.session({ database: this.database });
285
285
  try {
286
- const result = await session.run(`
287
- MATCH (n:CodeNode {projectId: $projectId})
288
- DETACH DELETE n
289
- RETURN count(n) as deleted
286
+ const result = await session.run(`
287
+ MATCH (n:CodeNode {projectId: $projectId})
288
+ DETACH DELETE n
289
+ RETURN count(n) as deleted
290
290
  `, { projectId });
291
291
  return result.records[0]?.get('deleted')?.toNumber() || 0;
292
292
  }
@@ -302,13 +302,13 @@ class Neo4jGraphStore {
302
302
  try {
303
303
  // Delete nodes that match any of the file paths
304
304
  // Handles both filePath property and relativePath property
305
- const result = await session.run(`
306
- MATCH (n:CodeNode {projectId: $projectId})
307
- WHERE n.filePath IN $filePaths
308
- OR n.relativePath IN $filePaths
309
- OR ANY(fp IN $filePaths WHERE n.id CONTAINS replace(replace(fp, '/', '-'), '\\\\', '-'))
310
- DETACH DELETE n
311
- RETURN count(n) as deleted
305
+ const result = await session.run(`
306
+ MATCH (n:CodeNode {projectId: $projectId})
307
+ WHERE n.filePath IN $filePaths
308
+ OR n.relativePath IN $filePaths
309
+ OR ANY(fp IN $filePaths WHERE n.id CONTAINS replace(replace(fp, '/', '-'), '\\\\', '-'))
310
+ DETACH DELETE n
311
+ RETURN count(n) as deleted
312
312
  `, { projectId, filePaths });
313
313
  return result.records[0]?.get('deleted')?.toNumber() || 0;
314
314
  }
@@ -320,9 +320,9 @@ class Neo4jGraphStore {
320
320
  await this.initialize();
321
321
  const session = this.driver.session({ database: this.database });
322
322
  try {
323
- const result = await session.run(`
324
- MATCH (n:CodeNode {projectId: $projectId})
325
- RETURN count(n) as count
323
+ const result = await session.run(`
324
+ MATCH (n:CodeNode {projectId: $projectId})
325
+ RETURN count(n) as count
326
326
  `, { projectId });
327
327
  return result.records[0]?.get('count')?.toNumber() || 0;
328
328
  }