aidex-mcp 1.4.1

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 (76) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/LICENSE +21 -0
  3. package/MCP-API-REFERENCE.md +690 -0
  4. package/README.md +314 -0
  5. package/build/commands/files.d.ts +28 -0
  6. package/build/commands/files.js +124 -0
  7. package/build/commands/index.d.ts +14 -0
  8. package/build/commands/index.js +14 -0
  9. package/build/commands/init.d.ts +24 -0
  10. package/build/commands/init.js +396 -0
  11. package/build/commands/link.d.ts +45 -0
  12. package/build/commands/link.js +167 -0
  13. package/build/commands/note.d.ts +29 -0
  14. package/build/commands/note.js +105 -0
  15. package/build/commands/query.d.ts +36 -0
  16. package/build/commands/query.js +176 -0
  17. package/build/commands/scan.d.ts +25 -0
  18. package/build/commands/scan.js +104 -0
  19. package/build/commands/session.d.ts +52 -0
  20. package/build/commands/session.js +216 -0
  21. package/build/commands/signature.d.ts +52 -0
  22. package/build/commands/signature.js +171 -0
  23. package/build/commands/summary.d.ts +56 -0
  24. package/build/commands/summary.js +324 -0
  25. package/build/commands/update.d.ts +36 -0
  26. package/build/commands/update.js +273 -0
  27. package/build/constants.d.ts +10 -0
  28. package/build/constants.js +10 -0
  29. package/build/db/database.d.ts +69 -0
  30. package/build/db/database.js +126 -0
  31. package/build/db/index.d.ts +7 -0
  32. package/build/db/index.js +6 -0
  33. package/build/db/queries.d.ts +163 -0
  34. package/build/db/queries.js +273 -0
  35. package/build/db/schema.sql +136 -0
  36. package/build/index.d.ts +13 -0
  37. package/build/index.js +74 -0
  38. package/build/parser/extractor.d.ts +41 -0
  39. package/build/parser/extractor.js +249 -0
  40. package/build/parser/index.d.ts +7 -0
  41. package/build/parser/index.js +7 -0
  42. package/build/parser/languages/c.d.ts +28 -0
  43. package/build/parser/languages/c.js +70 -0
  44. package/build/parser/languages/cpp.d.ts +28 -0
  45. package/build/parser/languages/cpp.js +91 -0
  46. package/build/parser/languages/csharp.d.ts +32 -0
  47. package/build/parser/languages/csharp.js +97 -0
  48. package/build/parser/languages/go.d.ts +28 -0
  49. package/build/parser/languages/go.js +83 -0
  50. package/build/parser/languages/index.d.ts +21 -0
  51. package/build/parser/languages/index.js +107 -0
  52. package/build/parser/languages/java.d.ts +28 -0
  53. package/build/parser/languages/java.js +58 -0
  54. package/build/parser/languages/php.d.ts +28 -0
  55. package/build/parser/languages/php.js +75 -0
  56. package/build/parser/languages/python.d.ts +28 -0
  57. package/build/parser/languages/python.js +67 -0
  58. package/build/parser/languages/ruby.d.ts +28 -0
  59. package/build/parser/languages/ruby.js +68 -0
  60. package/build/parser/languages/rust.d.ts +28 -0
  61. package/build/parser/languages/rust.js +73 -0
  62. package/build/parser/languages/typescript.d.ts +28 -0
  63. package/build/parser/languages/typescript.js +82 -0
  64. package/build/parser/tree-sitter.d.ts +30 -0
  65. package/build/parser/tree-sitter.js +132 -0
  66. package/build/server/mcp-server.d.ts +7 -0
  67. package/build/server/mcp-server.js +36 -0
  68. package/build/server/tools.d.ts +18 -0
  69. package/build/server/tools.js +1245 -0
  70. package/build/viewer/git-status.d.ts +25 -0
  71. package/build/viewer/git-status.js +163 -0
  72. package/build/viewer/index.d.ts +5 -0
  73. package/build/viewer/index.js +5 -0
  74. package/build/viewer/server.d.ts +12 -0
  75. package/build/viewer/server.js +1122 -0
  76. package/package.json +66 -0
@@ -0,0 +1,69 @@
1
+ /**
2
+ * SQLite Database wrapper for AiDex
3
+ */
4
+ import Database from 'better-sqlite3';
5
+ export interface DatabaseConfig {
6
+ dbPath: string;
7
+ readonly?: boolean;
8
+ }
9
+ export declare class AiDexDatabase {
10
+ private db;
11
+ private dbPath;
12
+ constructor(config: DatabaseConfig);
13
+ /**
14
+ * Initialize database with schema
15
+ */
16
+ initSchema(): void;
17
+ /**
18
+ * Set metadata value
19
+ */
20
+ setMetadata(key: string, value: string | null): void;
21
+ /**
22
+ * Get metadata value
23
+ */
24
+ getMetadata(key: string): string | null;
25
+ /**
26
+ * Delete metadata entry
27
+ */
28
+ deleteMetadata(key: string): void;
29
+ /**
30
+ * Run a function in a transaction
31
+ */
32
+ transaction<T>(fn: () => T): T;
33
+ /**
34
+ * Get the underlying better-sqlite3 database instance
35
+ */
36
+ getDb(): Database.Database;
37
+ /**
38
+ * Get database file path
39
+ */
40
+ getPath(): string;
41
+ /**
42
+ * Get database statistics
43
+ */
44
+ getStats(): {
45
+ files: number;
46
+ lines: number;
47
+ items: number;
48
+ occurrences: number;
49
+ methods: number;
50
+ types: number;
51
+ dependencies: number;
52
+ sizeBytes: number;
53
+ };
54
+ /**
55
+ * Close database connection
56
+ */
57
+ close(): void;
58
+ }
59
+ /**
60
+ * Open or create an AiDex database
61
+ */
62
+ export declare function openDatabase(dbPath: string, readonly?: boolean): AiDexDatabase;
63
+ /**
64
+ * Create and initialize a new AiDex database
65
+ * If incremental=true, keeps existing data for incremental updates
66
+ * If incremental=false (default), clears all data for fresh re-index
67
+ */
68
+ export declare function createDatabase(dbPath: string, projectName?: string, projectRoot?: string, incremental?: boolean): AiDexDatabase;
69
+ //# sourceMappingURL=database.d.ts.map
@@ -0,0 +1,126 @@
1
+ /**
2
+ * SQLite Database wrapper for AiDex
3
+ */
4
+ import Database from 'better-sqlite3';
5
+ import { readFileSync } from 'fs';
6
+ import { dirname, join } from 'path';
7
+ import { fileURLToPath } from 'url';
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+ export class AiDexDatabase {
10
+ db;
11
+ dbPath;
12
+ constructor(config) {
13
+ this.dbPath = config.dbPath;
14
+ this.db = new Database(config.dbPath, {
15
+ readonly: config.readonly ?? false,
16
+ });
17
+ // Enable WAL mode and foreign keys
18
+ this.db.pragma('journal_mode = WAL');
19
+ this.db.pragma('foreign_keys = ON');
20
+ }
21
+ /**
22
+ * Initialize database with schema
23
+ */
24
+ initSchema() {
25
+ const schemaPath = join(__dirname, 'schema.sql');
26
+ const schema = readFileSync(schemaPath, 'utf-8');
27
+ this.db.exec(schema);
28
+ // Set initial metadata if not exists
29
+ const stmt = this.db.prepare('INSERT OR IGNORE INTO metadata (key, value) VALUES (?, ?)');
30
+ stmt.run('schema_version', '1.0');
31
+ stmt.run('created_at', Date.now().toString());
32
+ }
33
+ /**
34
+ * Set metadata value
35
+ */
36
+ setMetadata(key, value) {
37
+ this.db.prepare('INSERT OR REPLACE INTO metadata (key, value) VALUES (?, ?)').run(key, value);
38
+ }
39
+ /**
40
+ * Get metadata value
41
+ */
42
+ getMetadata(key) {
43
+ const row = this.db.prepare('SELECT value FROM metadata WHERE key = ?').get(key);
44
+ return row?.value ?? null;
45
+ }
46
+ /**
47
+ * Delete metadata entry
48
+ */
49
+ deleteMetadata(key) {
50
+ this.db.prepare('DELETE FROM metadata WHERE key = ?').run(key);
51
+ }
52
+ /**
53
+ * Run a function in a transaction
54
+ */
55
+ transaction(fn) {
56
+ return this.db.transaction(fn)();
57
+ }
58
+ /**
59
+ * Get the underlying better-sqlite3 database instance
60
+ */
61
+ getDb() {
62
+ return this.db;
63
+ }
64
+ /**
65
+ * Get database file path
66
+ */
67
+ getPath() {
68
+ return this.dbPath;
69
+ }
70
+ /**
71
+ * Get database statistics
72
+ */
73
+ getStats() {
74
+ const counts = {
75
+ files: this.db.prepare('SELECT COUNT(*) as c FROM files').get().c,
76
+ lines: this.db.prepare('SELECT COUNT(*) as c FROM lines').get().c,
77
+ items: this.db.prepare('SELECT COUNT(*) as c FROM items').get().c,
78
+ occurrences: this.db.prepare('SELECT COUNT(*) as c FROM occurrences').get().c,
79
+ methods: this.db.prepare('SELECT COUNT(*) as c FROM methods').get().c,
80
+ types: this.db.prepare('SELECT COUNT(*) as c FROM types').get().c,
81
+ dependencies: this.db.prepare('SELECT COUNT(*) as c FROM dependencies').get().c,
82
+ };
83
+ // Get file size
84
+ const pragmaResult = this.db.pragma('page_count');
85
+ const pageSizeResult = this.db.pragma('page_size');
86
+ const pageCount = pragmaResult[0]?.page_count ?? 0;
87
+ const pageSize = pageSizeResult[0]?.page_size ?? 4096;
88
+ const sizeBytes = pageCount * pageSize;
89
+ return { ...counts, sizeBytes };
90
+ }
91
+ /**
92
+ * Close database connection
93
+ */
94
+ close() {
95
+ this.db.close();
96
+ }
97
+ }
98
+ /**
99
+ * Open or create an AiDex database
100
+ */
101
+ export function openDatabase(dbPath, readonly = false) {
102
+ return new AiDexDatabase({ dbPath, readonly });
103
+ }
104
+ /**
105
+ * Create and initialize a new AiDex database
106
+ * If incremental=true, keeps existing data for incremental updates
107
+ * If incremental=false (default), clears all data for fresh re-index
108
+ */
109
+ export function createDatabase(dbPath, projectName, projectRoot, incremental = false) {
110
+ const db = new AiDexDatabase({ dbPath });
111
+ db.initSchema();
112
+ if (!incremental) {
113
+ // Clear all data for fresh re-index (ON DELETE CASCADE handles related tables)
114
+ db.getDb().exec('DELETE FROM files');
115
+ db.getDb().exec('DELETE FROM items');
116
+ }
117
+ if (projectName) {
118
+ db.setMetadata('project_name', projectName);
119
+ }
120
+ if (projectRoot) {
121
+ db.setMetadata('project_root', projectRoot);
122
+ }
123
+ db.setMetadata('last_indexed', Date.now().toString());
124
+ return db;
125
+ }
126
+ //# sourceMappingURL=database.js.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Database module exports
3
+ */
4
+ export { AiDexDatabase, openDatabase, createDatabase } from './database.js';
5
+ export { Queries, createQueries } from './queries.js';
6
+ export type { FileRow, LineRow, ItemRow, OccurrenceRow, SignatureRow, MethodRow, TypeRow, DependencyRow, } from './queries.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Database module exports
3
+ */
4
+ export { AiDexDatabase, openDatabase, createDatabase } from './database.js';
5
+ export { Queries, createQueries } from './queries.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Prepared statements and query helpers for AiDex
3
+ */
4
+ import type { AiDexDatabase } from './database.js';
5
+ export interface FileRow {
6
+ id: number;
7
+ path: string;
8
+ hash: string;
9
+ last_indexed: number;
10
+ }
11
+ export interface LineRow {
12
+ id: number;
13
+ file_id: number;
14
+ line_number: number;
15
+ line_type: 'code' | 'comment' | 'struct' | 'method' | 'property' | 'string';
16
+ line_hash: string | null;
17
+ modified: number | null;
18
+ }
19
+ export interface ItemRow {
20
+ id: number;
21
+ term: string;
22
+ }
23
+ export interface OccurrenceRow {
24
+ item_id: number;
25
+ file_id: number;
26
+ line_id: number;
27
+ }
28
+ export interface SignatureRow {
29
+ file_id: number;
30
+ header_comments: string | null;
31
+ }
32
+ export interface MethodRow {
33
+ id: number;
34
+ file_id: number;
35
+ name: string;
36
+ prototype: string;
37
+ line_number: number;
38
+ visibility: string | null;
39
+ is_static: number;
40
+ is_async: number;
41
+ }
42
+ export interface TypeRow {
43
+ id: number;
44
+ file_id: number;
45
+ name: string;
46
+ kind: 'class' | 'struct' | 'interface' | 'enum' | 'type';
47
+ line_number: number;
48
+ }
49
+ export interface DependencyRow {
50
+ id: number;
51
+ path: string;
52
+ name: string | null;
53
+ last_checked: number | null;
54
+ }
55
+ export interface ProjectFileRow {
56
+ id: number;
57
+ path: string;
58
+ type: 'dir' | 'code' | 'config' | 'doc' | 'asset' | 'test' | 'other';
59
+ extension: string | null;
60
+ indexed: number;
61
+ }
62
+ export declare class Queries {
63
+ private db;
64
+ private _insertFile?;
65
+ private _updateFileHash?;
66
+ private _getFileByPath?;
67
+ private _getFileById?;
68
+ private _getAllFiles?;
69
+ private _deleteFile?;
70
+ private _insertLine?;
71
+ private _getLinesByFile?;
72
+ private _deleteLinesByFile?;
73
+ private _updateLineNumbers?;
74
+ private _insertItem?;
75
+ private _getItemByTerm?;
76
+ private _getItemById?;
77
+ private _deleteUnusedItems?;
78
+ private _insertOccurrence?;
79
+ private _getOccurrencesByItem?;
80
+ private _getOccurrencesByFile?;
81
+ private _deleteOccurrencesByFile?;
82
+ private _insertSignature?;
83
+ private _getSignatureByFile?;
84
+ private _deleteSignatureByFile?;
85
+ private _insertMethod?;
86
+ private _getMethodsByFile?;
87
+ private _deleteMethodsByFile?;
88
+ private _insertType?;
89
+ private _getTypesByFile?;
90
+ private _deleteTypesByFile?;
91
+ constructor(database: AiDexDatabase);
92
+ insertFile(path: string, hash: string): number;
93
+ updateFileHash(id: number, hash: string): void;
94
+ getFileByPath(path: string): FileRow | undefined;
95
+ getFileById(id: number): FileRow | undefined;
96
+ getAllFiles(): FileRow[];
97
+ deleteFile(id: number): void;
98
+ insertLine(fileId: number, lineId: number, lineNumber: number, lineType: LineRow['line_type'], lineHash?: string, modified?: number): void;
99
+ getLinesByFile(fileId: number): LineRow[];
100
+ deleteLinesByFile(fileId: number): void;
101
+ updateLineNumbers(fileId: number, fromLine: number, offset: number): void;
102
+ insertItem(term: string): number;
103
+ getOrCreateItem(term: string): number;
104
+ getItemByTerm(term: string): ItemRow | undefined;
105
+ getItemById(id: number): ItemRow | undefined;
106
+ deleteUnusedItems(): number;
107
+ insertOccurrence(itemId: number, fileId: number, lineId: number): void;
108
+ getOccurrencesByItem(itemId: number): Array<{
109
+ file_id: number;
110
+ line_id: number;
111
+ line_number: number;
112
+ path: string;
113
+ line_type: string;
114
+ modified: number | null;
115
+ }>;
116
+ getOccurrencesByFile(fileId: number): OccurrenceRow[];
117
+ deleteOccurrencesByFile(fileId: number): void;
118
+ insertSignature(fileId: number, headerComments: string | null): void;
119
+ getSignatureByFile(fileId: number): SignatureRow | undefined;
120
+ deleteSignatureByFile(fileId: number): void;
121
+ insertMethod(fileId: number, name: string, prototype: string, lineNumber: number, visibility?: string | null, isStatic?: boolean, isAsync?: boolean): number;
122
+ getMethodsByFile(fileId: number): MethodRow[];
123
+ deleteMethodsByFile(fileId: number): void;
124
+ insertType(fileId: number, name: string, kind: TypeRow['kind'], lineNumber: number): number;
125
+ getTypesByFile(fileId: number): TypeRow[];
126
+ deleteTypesByFile(fileId: number): void;
127
+ searchItems(term: string, mode?: 'exact' | 'contains' | 'starts_with', limit?: number): ItemRow[];
128
+ /**
129
+ * Clear all data for a file (before re-indexing)
130
+ */
131
+ clearFileData(fileId: number): void;
132
+ /**
133
+ * Bulk insert lines
134
+ */
135
+ bulkInsertLines(fileId: number, lines: Array<{
136
+ lineId: number;
137
+ lineNumber: number;
138
+ lineType: LineRow['line_type'];
139
+ lineHash?: string;
140
+ modified?: number;
141
+ }>): void;
142
+ /**
143
+ * Bulk insert occurrences
144
+ */
145
+ bulkInsertOccurrences(occurrences: Array<{
146
+ itemId: number;
147
+ fileId: number;
148
+ lineId: number;
149
+ }>): void;
150
+ private _insertProjectFile?;
151
+ private _getProjectFiles?;
152
+ private _getProjectFilesByType?;
153
+ private _clearProjectFiles?;
154
+ insertProjectFile(path: string, type: ProjectFileRow['type'], extension: string | null, indexed: boolean): void;
155
+ getProjectFiles(): ProjectFileRow[];
156
+ getProjectFilesByType(type: ProjectFileRow['type']): ProjectFileRow[];
157
+ clearProjectFiles(): void;
158
+ }
159
+ /**
160
+ * Create a Queries instance for the given database
161
+ */
162
+ export declare function createQueries(database: AiDexDatabase): Queries;
163
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1,273 @@
1
+ /**
2
+ * Prepared statements and query helpers for AiDex
3
+ */
4
+ // ============================================================
5
+ // Query class with prepared statements
6
+ // ============================================================
7
+ export class Queries {
8
+ db;
9
+ // Prepared statements (lazily initialized)
10
+ _insertFile;
11
+ _updateFileHash;
12
+ _getFileByPath;
13
+ _getFileById;
14
+ _getAllFiles;
15
+ _deleteFile;
16
+ _insertLine;
17
+ _getLinesByFile;
18
+ _deleteLinesByFile;
19
+ _updateLineNumbers;
20
+ _insertItem;
21
+ _getItemByTerm;
22
+ _getItemById;
23
+ _deleteUnusedItems;
24
+ _insertOccurrence;
25
+ _getOccurrencesByItem;
26
+ _getOccurrencesByFile;
27
+ _deleteOccurrencesByFile;
28
+ _insertSignature;
29
+ _getSignatureByFile;
30
+ _deleteSignatureByFile;
31
+ _insertMethod;
32
+ _getMethodsByFile;
33
+ _deleteMethodsByFile;
34
+ _insertType;
35
+ _getTypesByFile;
36
+ _deleteTypesByFile;
37
+ constructor(database) {
38
+ this.db = database.getDb();
39
+ }
40
+ // --------------------------------------------------------
41
+ // Files
42
+ // --------------------------------------------------------
43
+ insertFile(path, hash) {
44
+ this._insertFile ??= this.db.prepare('INSERT INTO files (path, hash, last_indexed) VALUES (?, ?, ?)');
45
+ const result = this._insertFile.run(path, hash, Date.now());
46
+ return result.lastInsertRowid;
47
+ }
48
+ updateFileHash(id, hash) {
49
+ this._updateFileHash ??= this.db.prepare('UPDATE files SET hash = ?, last_indexed = ? WHERE id = ?');
50
+ this._updateFileHash.run(hash, Date.now(), id);
51
+ }
52
+ getFileByPath(path) {
53
+ this._getFileByPath ??= this.db.prepare('SELECT * FROM files WHERE path = ?');
54
+ return this._getFileByPath.get(path);
55
+ }
56
+ getFileById(id) {
57
+ this._getFileById ??= this.db.prepare('SELECT * FROM files WHERE id = ?');
58
+ return this._getFileById.get(id);
59
+ }
60
+ getAllFiles() {
61
+ this._getAllFiles ??= this.db.prepare('SELECT * FROM files ORDER BY path');
62
+ return this._getAllFiles.all();
63
+ }
64
+ deleteFile(id) {
65
+ this._deleteFile ??= this.db.prepare('DELETE FROM files WHERE id = ?');
66
+ this._deleteFile.run(id);
67
+ }
68
+ // --------------------------------------------------------
69
+ // Lines
70
+ // --------------------------------------------------------
71
+ insertLine(fileId, lineId, lineNumber, lineType, lineHash, modified) {
72
+ this._insertLine ??= this.db.prepare('INSERT INTO lines (file_id, id, line_number, line_type, line_hash, modified) VALUES (?, ?, ?, ?, ?, ?)');
73
+ this._insertLine.run(fileId, lineId, lineNumber, lineType, lineHash ?? null, modified ?? Date.now());
74
+ }
75
+ getLinesByFile(fileId) {
76
+ this._getLinesByFile ??= this.db.prepare('SELECT * FROM lines WHERE file_id = ? ORDER BY line_number');
77
+ return this._getLinesByFile.all(fileId);
78
+ }
79
+ deleteLinesByFile(fileId) {
80
+ this._deleteLinesByFile ??= this.db.prepare('DELETE FROM lines WHERE file_id = ?');
81
+ this._deleteLinesByFile.run(fileId);
82
+ }
83
+ updateLineNumbers(fileId, fromLine, offset) {
84
+ this._updateLineNumbers ??= this.db.prepare('UPDATE lines SET line_number = line_number + ? WHERE file_id = ? AND line_number >= ?');
85
+ this._updateLineNumbers.run(offset, fileId, fromLine);
86
+ }
87
+ // --------------------------------------------------------
88
+ // Items
89
+ // --------------------------------------------------------
90
+ insertItem(term) {
91
+ this._insertItem ??= this.db.prepare('INSERT INTO items (term) VALUES (?)');
92
+ const result = this._insertItem.run(term);
93
+ return result.lastInsertRowid;
94
+ }
95
+ getOrCreateItem(term) {
96
+ const existing = this.getItemByTerm(term);
97
+ if (existing) {
98
+ return existing.id;
99
+ }
100
+ return this.insertItem(term);
101
+ }
102
+ getItemByTerm(term) {
103
+ this._getItemByTerm ??= this.db.prepare('SELECT * FROM items WHERE term = ? COLLATE NOCASE');
104
+ return this._getItemByTerm.get(term);
105
+ }
106
+ getItemById(id) {
107
+ this._getItemById ??= this.db.prepare('SELECT * FROM items WHERE id = ?');
108
+ return this._getItemById.get(id);
109
+ }
110
+ deleteUnusedItems() {
111
+ this._deleteUnusedItems ??= this.db.prepare('DELETE FROM items WHERE id NOT IN (SELECT DISTINCT item_id FROM occurrences)');
112
+ const result = this._deleteUnusedItems.run();
113
+ return result.changes;
114
+ }
115
+ // --------------------------------------------------------
116
+ // Occurrences
117
+ // --------------------------------------------------------
118
+ insertOccurrence(itemId, fileId, lineId) {
119
+ this._insertOccurrence ??= this.db.prepare('INSERT OR IGNORE INTO occurrences (item_id, file_id, line_id) VALUES (?, ?, ?)');
120
+ this._insertOccurrence.run(itemId, fileId, lineId);
121
+ }
122
+ getOccurrencesByItem(itemId) {
123
+ this._getOccurrencesByItem ??= this.db.prepare(`
124
+ SELECT o.file_id, o.line_id, l.line_number, f.path, l.line_type, l.modified
125
+ FROM occurrences o
126
+ JOIN lines l ON o.file_id = l.file_id AND o.line_id = l.id
127
+ JOIN files f ON o.file_id = f.id
128
+ WHERE o.item_id = ?
129
+ ORDER BY f.path, l.line_number
130
+ `);
131
+ return this._getOccurrencesByItem.all(itemId);
132
+ }
133
+ getOccurrencesByFile(fileId) {
134
+ this._getOccurrencesByFile ??= this.db.prepare('SELECT * FROM occurrences WHERE file_id = ?');
135
+ return this._getOccurrencesByFile.all(fileId);
136
+ }
137
+ deleteOccurrencesByFile(fileId) {
138
+ this._deleteOccurrencesByFile ??= this.db.prepare('DELETE FROM occurrences WHERE file_id = ?');
139
+ this._deleteOccurrencesByFile.run(fileId);
140
+ }
141
+ // --------------------------------------------------------
142
+ // Signatures
143
+ // --------------------------------------------------------
144
+ insertSignature(fileId, headerComments) {
145
+ this._insertSignature ??= this.db.prepare('INSERT OR REPLACE INTO signatures (file_id, header_comments) VALUES (?, ?)');
146
+ this._insertSignature.run(fileId, headerComments);
147
+ }
148
+ getSignatureByFile(fileId) {
149
+ this._getSignatureByFile ??= this.db.prepare('SELECT * FROM signatures WHERE file_id = ?');
150
+ return this._getSignatureByFile.get(fileId);
151
+ }
152
+ deleteSignatureByFile(fileId) {
153
+ this._deleteSignatureByFile ??= this.db.prepare('DELETE FROM signatures WHERE file_id = ?');
154
+ this._deleteSignatureByFile.run(fileId);
155
+ }
156
+ // --------------------------------------------------------
157
+ // Methods
158
+ // --------------------------------------------------------
159
+ insertMethod(fileId, name, prototype, lineNumber, visibility = null, isStatic = false, isAsync = false) {
160
+ this._insertMethod ??= this.db.prepare('INSERT INTO methods (file_id, name, prototype, line_number, visibility, is_static, is_async) VALUES (?, ?, ?, ?, ?, ?, ?)');
161
+ const result = this._insertMethod.run(fileId, name, prototype, lineNumber, visibility, isStatic ? 1 : 0, isAsync ? 1 : 0);
162
+ return result.lastInsertRowid;
163
+ }
164
+ getMethodsByFile(fileId) {
165
+ this._getMethodsByFile ??= this.db.prepare('SELECT * FROM methods WHERE file_id = ? ORDER BY line_number');
166
+ return this._getMethodsByFile.all(fileId);
167
+ }
168
+ deleteMethodsByFile(fileId) {
169
+ this._deleteMethodsByFile ??= this.db.prepare('DELETE FROM methods WHERE file_id = ?');
170
+ this._deleteMethodsByFile.run(fileId);
171
+ }
172
+ // --------------------------------------------------------
173
+ // Types
174
+ // --------------------------------------------------------
175
+ insertType(fileId, name, kind, lineNumber) {
176
+ this._insertType ??= this.db.prepare('INSERT INTO types (file_id, name, kind, line_number) VALUES (?, ?, ?, ?)');
177
+ const result = this._insertType.run(fileId, name, kind, lineNumber);
178
+ return result.lastInsertRowid;
179
+ }
180
+ getTypesByFile(fileId) {
181
+ this._getTypesByFile ??= this.db.prepare('SELECT * FROM types WHERE file_id = ? ORDER BY line_number');
182
+ return this._getTypesByFile.all(fileId);
183
+ }
184
+ deleteTypesByFile(fileId) {
185
+ this._deleteTypesByFile ??= this.db.prepare('DELETE FROM types WHERE file_id = ?');
186
+ this._deleteTypesByFile.run(fileId);
187
+ }
188
+ // --------------------------------------------------------
189
+ // Query: Search items
190
+ // --------------------------------------------------------
191
+ searchItems(term, mode = 'exact', limit = 100) {
192
+ let sql;
193
+ let param;
194
+ switch (mode) {
195
+ case 'exact':
196
+ sql = 'SELECT * FROM items WHERE term = ? COLLATE NOCASE LIMIT ?';
197
+ param = term;
198
+ break;
199
+ case 'contains':
200
+ sql = 'SELECT * FROM items WHERE term LIKE ? COLLATE NOCASE LIMIT ?';
201
+ param = `%${term}%`;
202
+ break;
203
+ case 'starts_with':
204
+ sql = 'SELECT * FROM items WHERE term LIKE ? COLLATE NOCASE LIMIT ?';
205
+ param = `${term}%`;
206
+ break;
207
+ }
208
+ return this.db.prepare(sql).all(param, limit);
209
+ }
210
+ // --------------------------------------------------------
211
+ // Bulk operations
212
+ // --------------------------------------------------------
213
+ /**
214
+ * Clear all data for a file (before re-indexing)
215
+ */
216
+ clearFileData(fileId) {
217
+ // Order matters due to foreign keys
218
+ this.deleteOccurrencesByFile(fileId);
219
+ this.deleteMethodsByFile(fileId);
220
+ this.deleteTypesByFile(fileId);
221
+ this.deleteSignatureByFile(fileId);
222
+ this.deleteLinesByFile(fileId);
223
+ }
224
+ /**
225
+ * Bulk insert lines
226
+ */
227
+ bulkInsertLines(fileId, lines) {
228
+ const stmt = this.db.prepare('INSERT INTO lines (file_id, id, line_number, line_type, line_hash, modified) VALUES (?, ?, ?, ?, ?, ?)');
229
+ const now = Date.now();
230
+ for (const line of lines) {
231
+ stmt.run(fileId, line.lineId, line.lineNumber, line.lineType, line.lineHash ?? null, line.modified ?? now);
232
+ }
233
+ }
234
+ /**
235
+ * Bulk insert occurrences
236
+ */
237
+ bulkInsertOccurrences(occurrences) {
238
+ const stmt = this.db.prepare('INSERT OR IGNORE INTO occurrences (item_id, file_id, line_id) VALUES (?, ?, ?)');
239
+ for (const occ of occurrences) {
240
+ stmt.run(occ.itemId, occ.fileId, occ.lineId);
241
+ }
242
+ }
243
+ // --------------------------------------------------------
244
+ // Project Files (project structure)
245
+ // --------------------------------------------------------
246
+ _insertProjectFile;
247
+ _getProjectFiles;
248
+ _getProjectFilesByType;
249
+ _clearProjectFiles;
250
+ insertProjectFile(path, type, extension, indexed) {
251
+ this._insertProjectFile ??= this.db.prepare('INSERT OR REPLACE INTO project_files (path, type, extension, indexed) VALUES (?, ?, ?, ?)');
252
+ this._insertProjectFile.run(path, type, extension, indexed ? 1 : 0);
253
+ }
254
+ getProjectFiles() {
255
+ this._getProjectFiles ??= this.db.prepare('SELECT * FROM project_files ORDER BY path');
256
+ return this._getProjectFiles.all();
257
+ }
258
+ getProjectFilesByType(type) {
259
+ this._getProjectFilesByType ??= this.db.prepare('SELECT * FROM project_files WHERE type = ? ORDER BY path');
260
+ return this._getProjectFilesByType.all(type);
261
+ }
262
+ clearProjectFiles() {
263
+ this._clearProjectFiles ??= this.db.prepare('DELETE FROM project_files');
264
+ this._clearProjectFiles.run();
265
+ }
266
+ }
267
+ /**
268
+ * Create a Queries instance for the given database
269
+ */
270
+ export function createQueries(database) {
271
+ return new Queries(database);
272
+ }
273
+ //# sourceMappingURL=queries.js.map