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.
- package/CHANGELOG.md +128 -0
- package/LICENSE +21 -0
- package/MCP-API-REFERENCE.md +690 -0
- package/README.md +314 -0
- package/build/commands/files.d.ts +28 -0
- package/build/commands/files.js +124 -0
- package/build/commands/index.d.ts +14 -0
- package/build/commands/index.js +14 -0
- package/build/commands/init.d.ts +24 -0
- package/build/commands/init.js +396 -0
- package/build/commands/link.d.ts +45 -0
- package/build/commands/link.js +167 -0
- package/build/commands/note.d.ts +29 -0
- package/build/commands/note.js +105 -0
- package/build/commands/query.d.ts +36 -0
- package/build/commands/query.js +176 -0
- package/build/commands/scan.d.ts +25 -0
- package/build/commands/scan.js +104 -0
- package/build/commands/session.d.ts +52 -0
- package/build/commands/session.js +216 -0
- package/build/commands/signature.d.ts +52 -0
- package/build/commands/signature.js +171 -0
- package/build/commands/summary.d.ts +56 -0
- package/build/commands/summary.js +324 -0
- package/build/commands/update.d.ts +36 -0
- package/build/commands/update.js +273 -0
- package/build/constants.d.ts +10 -0
- package/build/constants.js +10 -0
- package/build/db/database.d.ts +69 -0
- package/build/db/database.js +126 -0
- package/build/db/index.d.ts +7 -0
- package/build/db/index.js +6 -0
- package/build/db/queries.d.ts +163 -0
- package/build/db/queries.js +273 -0
- package/build/db/schema.sql +136 -0
- package/build/index.d.ts +13 -0
- package/build/index.js +74 -0
- package/build/parser/extractor.d.ts +41 -0
- package/build/parser/extractor.js +249 -0
- package/build/parser/index.d.ts +7 -0
- package/build/parser/index.js +7 -0
- package/build/parser/languages/c.d.ts +28 -0
- package/build/parser/languages/c.js +70 -0
- package/build/parser/languages/cpp.d.ts +28 -0
- package/build/parser/languages/cpp.js +91 -0
- package/build/parser/languages/csharp.d.ts +32 -0
- package/build/parser/languages/csharp.js +97 -0
- package/build/parser/languages/go.d.ts +28 -0
- package/build/parser/languages/go.js +83 -0
- package/build/parser/languages/index.d.ts +21 -0
- package/build/parser/languages/index.js +107 -0
- package/build/parser/languages/java.d.ts +28 -0
- package/build/parser/languages/java.js +58 -0
- package/build/parser/languages/php.d.ts +28 -0
- package/build/parser/languages/php.js +75 -0
- package/build/parser/languages/python.d.ts +28 -0
- package/build/parser/languages/python.js +67 -0
- package/build/parser/languages/ruby.d.ts +28 -0
- package/build/parser/languages/ruby.js +68 -0
- package/build/parser/languages/rust.d.ts +28 -0
- package/build/parser/languages/rust.js +73 -0
- package/build/parser/languages/typescript.d.ts +28 -0
- package/build/parser/languages/typescript.js +82 -0
- package/build/parser/tree-sitter.d.ts +30 -0
- package/build/parser/tree-sitter.js +132 -0
- package/build/server/mcp-server.d.ts +7 -0
- package/build/server/mcp-server.js +36 -0
- package/build/server/tools.d.ts +18 -0
- package/build/server/tools.js +1245 -0
- package/build/viewer/git-status.d.ts +25 -0
- package/build/viewer/git-status.js +163 -0
- package/build/viewer/index.d.ts +5 -0
- package/build/viewer/index.js +5 -0
- package/build/viewer/server.d.ts +12 -0
- package/build/viewer/server.js +1122 -0
- 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,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
|