sqlcipher-mcp-server 1.0.4 → 2.0.0

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.
@@ -1,55 +1,395 @@
1
- /**
2
- * Database Service
3
- * Service layer that wraps database operations with error handling
4
- */
5
-
6
- import { connectDatabase, executeQuery, closeConnection } from '../../lib/database.js';
7
-
8
- /**
9
- * Execute a query on a database
10
- * Handles connection, query execution, and cleanup
11
- * @param {string} dbPath - Path to the database file
12
- * @param {string|undefined} password - Database password (optional)
13
- * @param {string} query - SQL query to execute
14
- * @returns {Promise<Object>} Query results
15
- * @throws {Error} If connection or query execution fails
16
- */
17
- export async function executeQueryOnDatabase(dbPath, password, query) {
18
- let db = null;
19
-
20
- try {
21
- // Connect to database
22
- db = await connectDatabase(dbPath, password);
23
-
24
- // Execute query
25
- const result = await executeQuery(db, query);
26
-
27
- return result;
28
- } finally {
29
- // Always close the database connection
30
- if (db) {
31
- closeConnection(db);
32
- }
33
- }
34
- }
35
-
36
- /**
37
- * Test database connection
38
- * @param {string} dbPath - Path to the database file
39
- * @param {string|undefined} password - Database password (optional)
40
- * @returns {Promise<boolean>} True if connection successful
41
- */
42
- export async function testDatabaseConnection(dbPath, password) {
43
- let db = null;
44
-
45
- try {
46
- db = await connectDatabase(dbPath, password);
47
- return true;
48
- } catch (error) {
49
- throw new Error(`Failed to connect to database: ${error.message}`);
50
- } finally {
51
- if (db) {
52
- closeConnection(db);
53
- }
54
- }
55
- }
1
+ /**
2
+ * Database Service
3
+ * Service layer that wraps database operations with error handling
4
+ */
5
+
6
+ import {
7
+ connectDatabase,
8
+ executeQuery,
9
+ closeConnection,
10
+ getTableList,
11
+ getTableSchema,
12
+ getForeignKeys,
13
+ getIndexes,
14
+ getDatabaseInfo,
15
+ getTableInfo,
16
+ testConnection,
17
+ explainQueryPlan,
18
+ getTableStatistics,
19
+ sampleTableData,
20
+ getColumnStatistics,
21
+ searchTables,
22
+ searchColumns,
23
+ findRelatedTables
24
+ } from '../utils/database-operations.js';
25
+
26
+ /**
27
+ * Execute a query on a database
28
+ * Handles connection, query execution, and cleanup
29
+ * @param {string} dbPath - Path to the database file
30
+ * @param {string|undefined} password - Database password (optional)
31
+ * @param {string} query - SQL query to execute
32
+ * @returns {Promise<Object>} Query results
33
+ * @throws {Error} If connection or query execution fails
34
+ */
35
+ export async function executeQueryOnDatabase(dbPath, password, query) {
36
+ let db = null;
37
+
38
+ try {
39
+ // Connect to database
40
+ db = await connectDatabase(dbPath, password);
41
+
42
+ // Execute query
43
+ const result = await executeQuery(db, query);
44
+
45
+ return result;
46
+ } finally {
47
+ // Always close the database connection
48
+ if (db) {
49
+ closeConnection(db);
50
+ }
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Test database connection
56
+ * @param {string} dbPath - Path to the database file
57
+ * @param {string|undefined} password - Database password (optional)
58
+ * @returns {Promise<boolean>} True if connection successful
59
+ */
60
+ export async function testDatabaseConnection(dbPath, password) {
61
+ let db = null;
62
+
63
+ try {
64
+ db = await connectDatabase(dbPath, password);
65
+ await testConnection(db);
66
+ return true;
67
+ } catch (error) {
68
+ throw new Error(`Failed to connect to database: ${error.message}`);
69
+ } finally {
70
+ if (db) {
71
+ closeConnection(db);
72
+ }
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Get list of tables from database
78
+ * @param {string} dbPath - Path to the database file
79
+ * @param {string|undefined} password - Database password (optional)
80
+ * @param {string[]} tableNames - Optional array of table names to filter
81
+ * @returns {Promise<Array>} Array of table objects
82
+ */
83
+ export async function getTableListFromDatabase(dbPath, password, tableNames = null) {
84
+ let db = null;
85
+
86
+ try {
87
+ db = await connectDatabase(dbPath, password);
88
+ const tables = await getTableList(db, tableNames);
89
+
90
+ // Get row counts for each table
91
+ const tablesWithCounts = await Promise.all(
92
+ tables.map(async (table) => {
93
+ try {
94
+ const info = await getTableInfo(db, table.name);
95
+ return {
96
+ ...table,
97
+ row_count: info.row_count
98
+ };
99
+ } catch (error) {
100
+ return {
101
+ ...table,
102
+ row_count: 0
103
+ };
104
+ }
105
+ })
106
+ );
107
+
108
+ return tablesWithCounts;
109
+ } finally {
110
+ if (db) {
111
+ closeConnection(db);
112
+ }
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Get table schema from database
118
+ * @param {string} dbPath - Path to the database file
119
+ * @param {string|undefined} password - Database password (optional)
120
+ * @param {string|string[]} tableName - Table name or array of table names
121
+ * @returns {Promise<Object|Array>} Table schema or array of schemas
122
+ */
123
+ export async function getTableSchemaFromDatabase(dbPath, password, tableName) {
124
+ let db = null;
125
+
126
+ try {
127
+ db = await connectDatabase(dbPath, password);
128
+
129
+ // Handle batch operation
130
+ if (Array.isArray(tableName)) {
131
+ const schemas = await Promise.all(
132
+ tableName.map(async (name) => {
133
+ try {
134
+ const schema = await getTableSchema(db, name);
135
+ const fks = await getForeignKeys(db, name);
136
+ const indexes = await getIndexes(db, name);
137
+ return {
138
+ ...schema,
139
+ foreign_keys: fks,
140
+ indexes: indexes
141
+ };
142
+ } catch (error) {
143
+ return {
144
+ tableName: name,
145
+ error: error.message
146
+ };
147
+ }
148
+ })
149
+ );
150
+ return schemas;
151
+ } else {
152
+ // Single table
153
+ const schema = await getTableSchema(db, tableName);
154
+ const fks = await getForeignKeys(db, tableName);
155
+ const indexes = await getIndexes(db, tableName);
156
+ return {
157
+ ...schema,
158
+ foreign_keys: fks,
159
+ indexes: indexes
160
+ };
161
+ }
162
+ } finally {
163
+ if (db) {
164
+ closeConnection(db);
165
+ }
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Get foreign keys from database
171
+ * @param {string} dbPath - Path to the database file
172
+ * @param {string|undefined} password - Database password (optional)
173
+ * @param {string} tableName - Optional table name
174
+ * @returns {Promise<Array>} Array of foreign key relationships
175
+ */
176
+ export async function getForeignKeysFromDatabase(dbPath, password, tableName = null) {
177
+ let db = null;
178
+
179
+ try {
180
+ db = await connectDatabase(dbPath, password);
181
+ return await getForeignKeys(db, tableName);
182
+ } finally {
183
+ if (db) {
184
+ closeConnection(db);
185
+ }
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Get indexes from database
191
+ * @param {string} dbPath - Path to the database file
192
+ * @param {string|undefined} password - Database password (optional)
193
+ * @param {string} tableName - Optional table name
194
+ * @returns {Promise<Array>} Array of index information
195
+ */
196
+ export async function getIndexesFromDatabase(dbPath, password, tableName = null) {
197
+ let db = null;
198
+
199
+ try {
200
+ db = await connectDatabase(dbPath, password);
201
+ return await getIndexes(db, tableName);
202
+ } finally {
203
+ if (db) {
204
+ closeConnection(db);
205
+ }
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Get database info
211
+ * @param {string} dbPath - Path to the database file
212
+ * @param {string|undefined} password - Database password (optional)
213
+ * @returns {Promise<Object>} Database metadata
214
+ */
215
+ export async function getDatabaseInfoFromDatabase(dbPath, password) {
216
+ let db = null;
217
+
218
+ try {
219
+ db = await connectDatabase(dbPath, password);
220
+ return await getDatabaseInfo(db, dbPath);
221
+ } finally {
222
+ if (db) {
223
+ closeConnection(db);
224
+ }
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Get table info
230
+ * @param {string} dbPath - Path to the database file
231
+ * @param {string|undefined} password - Database password (optional)
232
+ * @param {string} tableName - Table name
233
+ * @returns {Promise<Object>} Table information
234
+ */
235
+ export async function getTableInfoFromDatabase(dbPath, password, tableName) {
236
+ let db = null;
237
+
238
+ try {
239
+ db = await connectDatabase(dbPath, password);
240
+ return await getTableInfo(db, tableName);
241
+ } finally {
242
+ if (db) {
243
+ closeConnection(db);
244
+ }
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Explain query plan
250
+ * @param {string} dbPath - Path to the database file
251
+ * @param {string|undefined} password - Database password (optional)
252
+ * @param {string} query - SQL query
253
+ * @returns {Promise<Array>} Query execution plan
254
+ */
255
+ export async function explainQueryPlanFromDatabase(dbPath, password, query) {
256
+ let db = null;
257
+
258
+ try {
259
+ db = await connectDatabase(dbPath, password);
260
+ return await explainQueryPlan(db, query);
261
+ } finally {
262
+ if (db) {
263
+ closeConnection(db);
264
+ }
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Get table statistics
270
+ * @param {string} dbPath - Path to the database file
271
+ * @param {string|undefined} password - Database password (optional)
272
+ * @param {string} tableName - Table name
273
+ * @param {number} maxSampleSize - Maximum sample size
274
+ * @returns {Promise<Object>} Table statistics
275
+ */
276
+ export async function getTableStatisticsFromDatabase(dbPath, password, tableName, maxSampleSize = 10000) {
277
+ let db = null;
278
+
279
+ try {
280
+ db = await connectDatabase(dbPath, password);
281
+ return await getTableStatistics(db, tableName, maxSampleSize);
282
+ } finally {
283
+ if (db) {
284
+ closeConnection(db);
285
+ }
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Sample table data
291
+ * @param {string} dbPath - Path to the database file
292
+ * @param {string|undefined} password - Database password (optional)
293
+ * @param {string} tableName - Table name
294
+ * @param {number} limit - Row limit
295
+ * @param {number} offset - Row offset
296
+ * @param {string[]} columns - Optional column filter
297
+ * @returns {Promise<Object>} Sample data
298
+ */
299
+ export async function sampleTableDataFromDatabase(dbPath, password, tableName, limit = 10, offset = 0, columns = null) {
300
+ let db = null;
301
+
302
+ try {
303
+ db = await connectDatabase(dbPath, password);
304
+ return await sampleTableData(db, tableName, limit, offset, columns);
305
+ } finally {
306
+ if (db) {
307
+ closeConnection(db);
308
+ }
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Get column statistics
314
+ * @param {string} dbPath - Path to the database file
315
+ * @param {string|undefined} password - Database password (optional)
316
+ * @param {string} tableName - Table name
317
+ * @param {string|string[]} columnName - Column name or array of column names
318
+ * @param {number} maxSampleSize - Maximum sample size
319
+ * @returns {Promise<Array>} Column statistics
320
+ */
321
+ export async function getColumnStatisticsFromDatabase(dbPath, password, tableName, columnName, maxSampleSize = 10000) {
322
+ let db = null;
323
+
324
+ try {
325
+ db = await connectDatabase(dbPath, password);
326
+
327
+ // Handle single column or array
328
+ const columnNames = Array.isArray(columnName) ? columnName : [columnName];
329
+ return await getColumnStatistics(db, tableName, columnNames, maxSampleSize);
330
+ } finally {
331
+ if (db) {
332
+ closeConnection(db);
333
+ }
334
+ }
335
+ }
336
+
337
+ /**
338
+ * Search tables
339
+ * @param {string} dbPath - Path to the database file
340
+ * @param {string|undefined} password - Database password (optional)
341
+ * @param {string} pattern - Search pattern
342
+ * @returns {Promise<Array>} Matching tables
343
+ */
344
+ export async function searchTablesInDatabase(dbPath, password, pattern) {
345
+ let db = null;
346
+
347
+ try {
348
+ db = await connectDatabase(dbPath, password);
349
+ return await searchTables(db, pattern);
350
+ } finally {
351
+ if (db) {
352
+ closeConnection(db);
353
+ }
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Search columns
359
+ * @param {string} dbPath - Path to the database file
360
+ * @param {string|undefined} password - Database password (optional)
361
+ * @param {string} pattern - Search pattern
362
+ * @returns {Promise<Array>} Matching columns
363
+ */
364
+ export async function searchColumnsInDatabase(dbPath, password, pattern) {
365
+ let db = null;
366
+
367
+ try {
368
+ db = await connectDatabase(dbPath, password);
369
+ return await searchColumns(db, pattern);
370
+ } finally {
371
+ if (db) {
372
+ closeConnection(db);
373
+ }
374
+ }
375
+ }
376
+
377
+ /**
378
+ * Find related tables
379
+ * @param {string} dbPath - Path to the database file
380
+ * @param {string|undefined} password - Database password (optional)
381
+ * @param {string} tableName - Table name
382
+ * @returns {Promise<Object>} Related tables information
383
+ */
384
+ export async function findRelatedTablesInDatabase(dbPath, password, tableName) {
385
+ let db = null;
386
+
387
+ try {
388
+ db = await connectDatabase(dbPath, password);
389
+ return await findRelatedTables(db, tableName);
390
+ } finally {
391
+ if (db) {
392
+ closeConnection(db);
393
+ }
394
+ }
395
+ }