@pilat/mcp-datalink 1.0.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/README.md +442 -0
- package/databases.example.json +18 -0
- package/dist/__integration__/global-setup.d.ts +8 -0
- package/dist/__integration__/global-setup.d.ts.map +1 -0
- package/dist/__integration__/global-setup.js +34 -0
- package/dist/__integration__/global-setup.js.map +1 -0
- package/dist/__integration__/global-teardown.d.ts +8 -0
- package/dist/__integration__/global-teardown.d.ts.map +1 -0
- package/dist/__integration__/global-teardown.js +17 -0
- package/dist/__integration__/global-teardown.js.map +1 -0
- package/dist/__integration__/helpers.d.ts +58 -0
- package/dist/__integration__/helpers.d.ts.map +1 -0
- package/dist/__integration__/helpers.js +568 -0
- package/dist/__integration__/helpers.js.map +1 -0
- package/dist/__integration__/setup.d.ts +79 -0
- package/dist/__integration__/setup.d.ts.map +1 -0
- package/dist/__integration__/setup.js +230 -0
- package/dist/__integration__/setup.js.map +1 -0
- package/dist/adapters/factory.d.ts +40 -0
- package/dist/adapters/factory.d.ts.map +1 -0
- package/dist/adapters/factory.js +114 -0
- package/dist/adapters/factory.js.map +1 -0
- package/dist/adapters/index.d.ts +31 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +34 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/mysql/adapter.d.ts +61 -0
- package/dist/adapters/mysql/adapter.d.ts.map +1 -0
- package/dist/adapters/mysql/adapter.js +567 -0
- package/dist/adapters/mysql/adapter.js.map +1 -0
- package/dist/adapters/postgresql/adapter.d.ts +52 -0
- package/dist/adapters/postgresql/adapter.d.ts.map +1 -0
- package/dist/adapters/postgresql/adapter.js +429 -0
- package/dist/adapters/postgresql/adapter.js.map +1 -0
- package/dist/adapters/sqlite/adapter.d.ts +56 -0
- package/dist/adapters/sqlite/adapter.d.ts.map +1 -0
- package/dist/adapters/sqlite/adapter.js +582 -0
- package/dist/adapters/sqlite/adapter.js.map +1 -0
- package/dist/adapters/types.d.ts +155 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +7 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/config/loader.d.ts +11 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +127 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +191 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/describe-table.d.ts +11 -0
- package/dist/tools/describe-table.d.ts.map +1 -0
- package/dist/tools/describe-table.js +23 -0
- package/dist/tools/describe-table.js.map +1 -0
- package/dist/tools/execute.d.ts +22 -0
- package/dist/tools/execute.d.ts.map +1 -0
- package/dist/tools/execute.js +48 -0
- package/dist/tools/execute.js.map +1 -0
- package/dist/tools/explain.d.ts +25 -0
- package/dist/tools/explain.d.ts.map +1 -0
- package/dist/tools/explain.js +81 -0
- package/dist/tools/explain.js.map +1 -0
- package/dist/tools/list-databases.d.ts +18 -0
- package/dist/tools/list-databases.d.ts.map +1 -0
- package/dist/tools/list-databases.js +17 -0
- package/dist/tools/list-databases.js.map +1 -0
- package/dist/tools/list-tables.d.ts +22 -0
- package/dist/tools/list-tables.d.ts.map +1 -0
- package/dist/tools/list-tables.js +43 -0
- package/dist/tools/list-tables.js.map +1 -0
- package/dist/tools/query.d.ts +25 -0
- package/dist/tools/query.d.ts.map +1 -0
- package/dist/tools/query.js +109 -0
- package/dist/tools/query.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/errors.d.ts +22 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +41 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/formatter.d.ts +13 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +56 -0
- package/dist/utils/formatter.js.map +1 -0
- package/dist/utils/truncate.d.ts +37 -0
- package/dist/utils/truncate.d.ts.map +1 -0
- package/dist/utils/truncate.js +91 -0
- package/dist/utils/truncate.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite Database Adapter
|
|
3
|
+
*
|
|
4
|
+
* Implements DatabaseAdapter interface for SQLite databases.
|
|
5
|
+
* Uses better-sqlite3 library for synchronous database access.
|
|
6
|
+
*/
|
|
7
|
+
import Database from 'better-sqlite3';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import { DbMcpError, ErrorCode } from '../../utils/errors.js';
|
|
11
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
12
|
+
// SQL Dialect helpers (formerly in dialect.ts)
|
|
13
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
14
|
+
/**
|
|
15
|
+
* Dangerous SQL operations that are always blocked
|
|
16
|
+
*/
|
|
17
|
+
const DANGEROUS_OPERATIONS = [
|
|
18
|
+
'DROP',
|
|
19
|
+
'TRUNCATE',
|
|
20
|
+
'ALTER',
|
|
21
|
+
'CREATE',
|
|
22
|
+
'GRANT',
|
|
23
|
+
'REVOKE',
|
|
24
|
+
'ATTACH',
|
|
25
|
+
'DETACH',
|
|
26
|
+
'VACUUM',
|
|
27
|
+
'REINDEX',
|
|
28
|
+
];
|
|
29
|
+
/**
|
|
30
|
+
* Strip SQL comments from a query
|
|
31
|
+
*/
|
|
32
|
+
function stripComments(sql) {
|
|
33
|
+
let result = '';
|
|
34
|
+
let i = 0;
|
|
35
|
+
let inString = false;
|
|
36
|
+
let stringChar = '';
|
|
37
|
+
while (i < sql.length) {
|
|
38
|
+
if (!inString && (sql[i] === "'" || sql[i] === '"')) {
|
|
39
|
+
inString = true;
|
|
40
|
+
stringChar = sql[i];
|
|
41
|
+
result += sql[i];
|
|
42
|
+
i++;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (inString) {
|
|
46
|
+
if (sql[i] === stringChar) {
|
|
47
|
+
if (i + 1 < sql.length && sql[i + 1] === stringChar) {
|
|
48
|
+
result += sql[i] + sql[i + 1];
|
|
49
|
+
i += 2;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
inString = false;
|
|
54
|
+
result += sql[i];
|
|
55
|
+
i++;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
result += sql[i];
|
|
60
|
+
i++;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (sql[i] === '-' && i + 1 < sql.length && sql[i + 1] === '-') {
|
|
64
|
+
while (i < sql.length && sql[i] !== '\n') {
|
|
65
|
+
i++;
|
|
66
|
+
}
|
|
67
|
+
if (i < sql.length) {
|
|
68
|
+
result += ' ';
|
|
69
|
+
i++;
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (sql[i] === '/' && i + 1 < sql.length && sql[i + 1] === '*') {
|
|
74
|
+
i += 2;
|
|
75
|
+
while (i < sql.length - 1 && !(sql[i] === '*' && sql[i + 1] === '/')) {
|
|
76
|
+
i++;
|
|
77
|
+
}
|
|
78
|
+
if (i < sql.length - 1) {
|
|
79
|
+
i += 2;
|
|
80
|
+
}
|
|
81
|
+
result += ' ';
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
result += sql[i];
|
|
85
|
+
i++;
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Split SQL by semicolons, respecting string literals
|
|
91
|
+
*/
|
|
92
|
+
function splitStatements(sql) {
|
|
93
|
+
const statements = [];
|
|
94
|
+
let current = '';
|
|
95
|
+
let inString = false;
|
|
96
|
+
let stringChar = '';
|
|
97
|
+
for (let i = 0; i < sql.length; i++) {
|
|
98
|
+
const char = sql[i];
|
|
99
|
+
if (!inString && (char === "'" || char === '"')) {
|
|
100
|
+
inString = true;
|
|
101
|
+
stringChar = char;
|
|
102
|
+
current += char;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (inString && char === stringChar) {
|
|
106
|
+
if (i + 1 < sql.length && sql[i + 1] === stringChar) {
|
|
107
|
+
current += char + sql[i + 1];
|
|
108
|
+
i++;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
inString = false;
|
|
113
|
+
current += char;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (char === ';' && !inString) {
|
|
118
|
+
if (current.trim()) {
|
|
119
|
+
statements.push(current.trim());
|
|
120
|
+
}
|
|
121
|
+
current = '';
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
current += char;
|
|
125
|
+
}
|
|
126
|
+
if (current.trim()) {
|
|
127
|
+
statements.push(current.trim());
|
|
128
|
+
}
|
|
129
|
+
return statements;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Detect query type from normalized SQL
|
|
133
|
+
*/
|
|
134
|
+
function detectQueryType(normalizedSql) {
|
|
135
|
+
if (normalizedSql.startsWith('SELECT') || normalizedSql.startsWith('WITH')) {
|
|
136
|
+
return 'select';
|
|
137
|
+
}
|
|
138
|
+
if (normalizedSql.startsWith('INSERT')) {
|
|
139
|
+
return 'insert';
|
|
140
|
+
}
|
|
141
|
+
if (normalizedSql.startsWith('UPDATE')) {
|
|
142
|
+
return 'update';
|
|
143
|
+
}
|
|
144
|
+
if (normalizedSql.startsWith('DELETE')) {
|
|
145
|
+
return 'delete';
|
|
146
|
+
}
|
|
147
|
+
return 'other';
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Check if SQL contains a dangerous operation
|
|
151
|
+
*/
|
|
152
|
+
function checkDangerous(normalizedSql) {
|
|
153
|
+
for (const operation of DANGEROUS_OPERATIONS) {
|
|
154
|
+
if (normalizedSql.startsWith(operation) ||
|
|
155
|
+
normalizedSql.startsWith(operation + ' ') ||
|
|
156
|
+
normalizedSql.includes(' ' + operation + ' ')) {
|
|
157
|
+
return {
|
|
158
|
+
isDangerous: true,
|
|
159
|
+
reason: `${operation} statements are not allowed`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (normalizedSql.startsWith('PRAGMA')) {
|
|
164
|
+
if (normalizedSql.includes('=')) {
|
|
165
|
+
return {
|
|
166
|
+
isDangerous: true,
|
|
167
|
+
reason: 'PRAGMA modifications are not allowed',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return { isDangerous: false };
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Check if a SELECT query has a LIMIT clause
|
|
175
|
+
*/
|
|
176
|
+
function hasLimitClause(sql) {
|
|
177
|
+
return /\bLIMIT\s+\d+/i.test(sql);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Parse SQLite URL to extract file path
|
|
181
|
+
*
|
|
182
|
+
* Supported formats:
|
|
183
|
+
* - sqlite:///absolute/path.db
|
|
184
|
+
* - sqlite://./relative/path.db
|
|
185
|
+
* - sqlite://:memory:
|
|
186
|
+
* - /absolute/path.db (plain file path)
|
|
187
|
+
* - ./relative/path.db (plain file path)
|
|
188
|
+
*
|
|
189
|
+
* @param url - SQLite connection URL or file path
|
|
190
|
+
* @returns Resolved absolute file path or :memory:
|
|
191
|
+
*/
|
|
192
|
+
function parseSqliteUrl(url) {
|
|
193
|
+
if (url.startsWith('sqlite://')) {
|
|
194
|
+
const pathPart = url.slice('sqlite://'.length);
|
|
195
|
+
// Special case: :memory:
|
|
196
|
+
if (pathPart === ':memory:') {
|
|
197
|
+
return ':memory:';
|
|
198
|
+
}
|
|
199
|
+
// Handle both absolute (/path) and relative (./path) paths
|
|
200
|
+
return pathPart;
|
|
201
|
+
}
|
|
202
|
+
// Plain file path (no sqlite:// prefix)
|
|
203
|
+
return url;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Validate and resolve SQLite database path
|
|
207
|
+
*
|
|
208
|
+
* SECURITY: Prevents path traversal attacks by:
|
|
209
|
+
* 1. Resolving to absolute path
|
|
210
|
+
* 2. Ensuring path doesn't contain suspicious patterns
|
|
211
|
+
* 3. Checking file exists (unless :memory:)
|
|
212
|
+
*
|
|
213
|
+
* @param rawPath - Raw path from config
|
|
214
|
+
* @param basePath - Base directory for relative paths (process.cwd())
|
|
215
|
+
* @returns Validated absolute path
|
|
216
|
+
* @throws DbMcpError if path is invalid or file not found
|
|
217
|
+
*/
|
|
218
|
+
function validateAndResolvePath(rawPath, basePath) {
|
|
219
|
+
// :memory: is always valid
|
|
220
|
+
if (rawPath === ':memory:') {
|
|
221
|
+
return ':memory:';
|
|
222
|
+
}
|
|
223
|
+
// Resolve to absolute path
|
|
224
|
+
const absolutePath = path.isAbsolute(rawPath) ? rawPath : path.resolve(basePath, rawPath);
|
|
225
|
+
// Normalize to remove any .. or . components
|
|
226
|
+
const normalizedPath = path.normalize(absolutePath);
|
|
227
|
+
// SECURITY: Check for path traversal attempts
|
|
228
|
+
// After normalization, path should not go above the base directory for relative paths
|
|
229
|
+
if (!path.isAbsolute(rawPath)) {
|
|
230
|
+
// For relative paths, ensure the resolved path is still within reasonable bounds
|
|
231
|
+
// This prevents sqlite://../../etc/passwd type attacks
|
|
232
|
+
const relativeToCwd = path.relative(basePath, normalizedPath);
|
|
233
|
+
if (relativeToCwd.startsWith('..')) {
|
|
234
|
+
throw new DbMcpError(ErrorCode.CONFIG_INVALID, 'Path traversal detected. SQLite path must not escape the working directory.', { path: rawPath, resolved: normalizedPath });
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Check file exists
|
|
238
|
+
if (!fs.existsSync(normalizedPath)) {
|
|
239
|
+
throw new DbMcpError(ErrorCode.CONNECTION_FAILED, `SQLite database file not found: ${normalizedPath}`, { path: rawPath, resolved: normalizedPath });
|
|
240
|
+
}
|
|
241
|
+
return normalizedPath;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* SQLite database adapter
|
|
245
|
+
*
|
|
246
|
+
* Creates new database handles for each request.
|
|
247
|
+
*
|
|
248
|
+
* Note: better-sqlite3 is synchronous, but we wrap in async for interface
|
|
249
|
+
* compatibility with other adapters.
|
|
250
|
+
*/
|
|
251
|
+
export class SqliteAdapter {
|
|
252
|
+
type = 'sqlite';
|
|
253
|
+
dbPath;
|
|
254
|
+
timeout;
|
|
255
|
+
readonly;
|
|
256
|
+
constructor(config) {
|
|
257
|
+
const rawPath = parseSqliteUrl(config.database.url);
|
|
258
|
+
this.dbPath = validateAndResolvePath(rawPath, process.cwd());
|
|
259
|
+
this.timeout = config.defaults.timeout;
|
|
260
|
+
this.readonly = config.database.readonly;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Get the default schema name for SQLite
|
|
264
|
+
*/
|
|
265
|
+
getDefaultSchema() {
|
|
266
|
+
return 'main';
|
|
267
|
+
}
|
|
268
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
269
|
+
// SQL Dialect methods
|
|
270
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
271
|
+
/**
|
|
272
|
+
* Parse and validate a SQLite SQL query
|
|
273
|
+
*/
|
|
274
|
+
parseQuery(sql) {
|
|
275
|
+
const withoutComments = stripComments(sql);
|
|
276
|
+
const statements = splitStatements(withoutComments);
|
|
277
|
+
if (statements.length === 0) {
|
|
278
|
+
throw new DbMcpError(ErrorCode.INVALID_SQL, 'No valid SQL statement found', { sql });
|
|
279
|
+
}
|
|
280
|
+
if (statements.length > 1) {
|
|
281
|
+
throw new DbMcpError(ErrorCode.MULTI_STATEMENT, 'Multiple SQL statements are not allowed. Please provide a single statement.', { sql, statementCount: statements.length });
|
|
282
|
+
}
|
|
283
|
+
const statement = statements[0];
|
|
284
|
+
const normalizedSql = statement.trim().toUpperCase();
|
|
285
|
+
const { isDangerous, reason } = checkDangerous(normalizedSql);
|
|
286
|
+
const queryType = detectQueryType(normalizedSql);
|
|
287
|
+
const hasLimit = queryType === 'select' && hasLimitClause(statement);
|
|
288
|
+
return {
|
|
289
|
+
type: queryType,
|
|
290
|
+
hasLimit,
|
|
291
|
+
isDangerous,
|
|
292
|
+
dangerousReason: reason,
|
|
293
|
+
sql: statement,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Inject a LIMIT clause into a SELECT query if it doesn't have one
|
|
298
|
+
*/
|
|
299
|
+
injectLimit(sql, limit) {
|
|
300
|
+
if (hasLimitClause(sql)) {
|
|
301
|
+
return sql;
|
|
302
|
+
}
|
|
303
|
+
const trimmed = sql.replace(/;\s*$/, '').trim();
|
|
304
|
+
return `${trimmed} LIMIT ${limit}`;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Validate that a SQL query is appropriate for a specific tool
|
|
308
|
+
*/
|
|
309
|
+
validateQueryForTool(sql, tool) {
|
|
310
|
+
const parsed = this.parseQuery(sql);
|
|
311
|
+
if (tool === 'query') {
|
|
312
|
+
if (parsed.type !== 'select') {
|
|
313
|
+
throw new DbMcpError(ErrorCode.QUERY_BLOCKED, 'The query tool only accepts SELECT statements. Use the execute tool for ' +
|
|
314
|
+
parsed.type.toUpperCase() +
|
|
315
|
+
' statements.', { sql, queryType: parsed.type, tool });
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
else if (tool === 'execute') {
|
|
319
|
+
if (parsed.type === 'select') {
|
|
320
|
+
throw new DbMcpError(ErrorCode.QUERY_BLOCKED, 'The execute tool does not accept SELECT statements. Use the query tool instead.', { sql, queryType: parsed.type, tool });
|
|
321
|
+
}
|
|
322
|
+
if (parsed.isDangerous) {
|
|
323
|
+
throw new DbMcpError(ErrorCode.QUERY_BLOCKED, parsed.dangerousReason ?? 'This operation is not allowed', { sql, queryType: parsed.type, tool });
|
|
324
|
+
}
|
|
325
|
+
const allowedTypes = ['insert', 'update', 'delete'];
|
|
326
|
+
if (!allowedTypes.includes(parsed.type)) {
|
|
327
|
+
throw new DbMcpError(ErrorCode.QUERY_BLOCKED, 'The execute tool only accepts INSERT, UPDATE, or DELETE statements.', { sql, queryType: parsed.type, tool });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Get the EXPLAIN prefix for SQLite
|
|
333
|
+
*/
|
|
334
|
+
getExplainPrefix(_analyze) {
|
|
335
|
+
return 'EXPLAIN QUERY PLAN ';
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Convert $1, $2 style placeholders to ? style for SQLite
|
|
339
|
+
*/
|
|
340
|
+
convertPlaceholders(sql) {
|
|
341
|
+
let result = '';
|
|
342
|
+
let inString = false;
|
|
343
|
+
let stringChar = '';
|
|
344
|
+
let i = 0;
|
|
345
|
+
while (i < sql.length) {
|
|
346
|
+
if (!inString && (sql[i] === "'" || sql[i] === '"')) {
|
|
347
|
+
inString = true;
|
|
348
|
+
stringChar = sql[i];
|
|
349
|
+
result += sql[i];
|
|
350
|
+
i++;
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
if (inString && sql[i] === stringChar) {
|
|
354
|
+
if (i + 1 < sql.length && sql[i + 1] === stringChar) {
|
|
355
|
+
result += sql[i] + sql[i + 1];
|
|
356
|
+
i += 2;
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
inString = false;
|
|
361
|
+
result += sql[i];
|
|
362
|
+
i++;
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
if (!inString && sql[i] === '$') {
|
|
367
|
+
let j = i + 1;
|
|
368
|
+
while (j < sql.length && /\d/.test(sql[j])) {
|
|
369
|
+
j++;
|
|
370
|
+
}
|
|
371
|
+
if (j > i + 1) {
|
|
372
|
+
result += '?';
|
|
373
|
+
i = j;
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
result += sql[i];
|
|
378
|
+
i++;
|
|
379
|
+
}
|
|
380
|
+
return result;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Execute a function with a managed SQLite connection
|
|
384
|
+
*/
|
|
385
|
+
async withConnection(fn) {
|
|
386
|
+
// Open database (create new handle per request)
|
|
387
|
+
const db = new Database(this.dbPath, {
|
|
388
|
+
readonly: this.readonly,
|
|
389
|
+
// busy_timeout handles lock contention (different from query timeout)
|
|
390
|
+
timeout: this.timeout,
|
|
391
|
+
});
|
|
392
|
+
try {
|
|
393
|
+
// Create connection wrapper and execute user function
|
|
394
|
+
const connection = new SqliteConnection(db);
|
|
395
|
+
return await fn(connection);
|
|
396
|
+
}
|
|
397
|
+
finally {
|
|
398
|
+
db.close();
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Clean up resources (no persistent resources in this adapter)
|
|
403
|
+
*/
|
|
404
|
+
async dispose() {
|
|
405
|
+
// No persistent resources to clean up
|
|
406
|
+
// Each database handle is opened and closed per request
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* SQLite connection wrapper
|
|
411
|
+
*
|
|
412
|
+
* Provides AdapterConnection interface over better-sqlite3 Database.
|
|
413
|
+
* Handles SQLite-specific query execution and metadata retrieval.
|
|
414
|
+
*
|
|
415
|
+
* Note: better-sqlite3 is synchronous, wrapped in async for interface.
|
|
416
|
+
*/
|
|
417
|
+
class SqliteConnection {
|
|
418
|
+
db;
|
|
419
|
+
constructor(db) {
|
|
420
|
+
this.db = db;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Execute a parameterized query
|
|
424
|
+
*
|
|
425
|
+
* SECURITY: All user SQL MUST go through this method with parameters.
|
|
426
|
+
* Uses better-sqlite3 prepared statements.
|
|
427
|
+
*
|
|
428
|
+
* Note: better-sqlite3 uses ? placeholders (not $1, $2 like PostgreSQL).
|
|
429
|
+
* The SqliteDialect.convertPlaceholders() should be called before this if needed.
|
|
430
|
+
*/
|
|
431
|
+
async query(sql, params) {
|
|
432
|
+
const stmt = this.db.prepare(sql);
|
|
433
|
+
// Check if statement returns data (SELECT) or not (INSERT/UPDATE/DELETE)
|
|
434
|
+
if (stmt.reader) {
|
|
435
|
+
// SELECT query - returns rows
|
|
436
|
+
const rows = stmt.all(...(params ?? []));
|
|
437
|
+
// Get column names from first row or statement
|
|
438
|
+
const columns = stmt.columns();
|
|
439
|
+
const columnNames = columns.map((c) => c.name);
|
|
440
|
+
// Convert object rows to array rows for consistent interface
|
|
441
|
+
const arrayRows = rows.map((row) => columnNames.map((col) => row[col]));
|
|
442
|
+
return {
|
|
443
|
+
fields: columnNames.map((name) => ({ name })),
|
|
444
|
+
rows: arrayRows,
|
|
445
|
+
rowCount: rows.length,
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
// Non-SELECT query (INSERT/UPDATE/DELETE)
|
|
450
|
+
const result = stmt.run(...(params ?? []));
|
|
451
|
+
return {
|
|
452
|
+
fields: [],
|
|
453
|
+
rows: [],
|
|
454
|
+
rowCount: result.changes,
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Execute a raw SQL statement
|
|
460
|
+
*
|
|
461
|
+
* SECURITY WARNING: Only use for validated internal commands
|
|
462
|
+
* For SQLite this is primarily used for PRAGMA and transaction commands
|
|
463
|
+
*/
|
|
464
|
+
async execute(sql) {
|
|
465
|
+
this.db.exec(sql);
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* List tables in SQLite database
|
|
469
|
+
*
|
|
470
|
+
* SQLite doesn't have schemas - we ignore the schema parameter and
|
|
471
|
+
* always report "main" as the schema.
|
|
472
|
+
*/
|
|
473
|
+
async listTables(_schema, _maxTables) {
|
|
474
|
+
// Query sqlite_master for tables and views
|
|
475
|
+
// Filter out internal sqlite_ tables
|
|
476
|
+
const sql = `
|
|
477
|
+
SELECT
|
|
478
|
+
name,
|
|
479
|
+
type
|
|
480
|
+
FROM sqlite_master
|
|
481
|
+
WHERE type IN ('table', 'view')
|
|
482
|
+
AND name NOT LIKE 'sqlite_%'
|
|
483
|
+
ORDER BY name
|
|
484
|
+
`;
|
|
485
|
+
const stmt = this.db.prepare(sql);
|
|
486
|
+
const rows = stmt.all();
|
|
487
|
+
const tables = rows.map((row) => ({
|
|
488
|
+
name: row.name,
|
|
489
|
+
schema: 'main',
|
|
490
|
+
type: row.type,
|
|
491
|
+
rows_estimate: null,
|
|
492
|
+
}));
|
|
493
|
+
return {
|
|
494
|
+
tables,
|
|
495
|
+
totalAvailable: tables.length,
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Describe a SQLite table
|
|
500
|
+
*
|
|
501
|
+
* Uses PRAGMA commands to get table structure.
|
|
502
|
+
* Schema parameter is ignored since SQLite doesn't have schemas.
|
|
503
|
+
*/
|
|
504
|
+
async describeTable(table, _schema, limits) {
|
|
505
|
+
// Validate table name to prevent injection in PRAGMA commands
|
|
506
|
+
// Table names in SQLite can contain almost anything, but we use quotes
|
|
507
|
+
const safeTable = this.escapeIdentifier(table);
|
|
508
|
+
const columnsStmt = this.db.prepare(`PRAGMA table_info(${safeTable})`);
|
|
509
|
+
const columnRows = columnsStmt.all();
|
|
510
|
+
const indexListStmt = this.db.prepare(`PRAGMA index_list(${safeTable})`);
|
|
511
|
+
const indexListRows = indexListStmt.all();
|
|
512
|
+
const fkStmt = this.db.prepare(`PRAGMA foreign_key_list(${safeTable})`);
|
|
513
|
+
const fkRows = fkStmt.all();
|
|
514
|
+
// Build columns array
|
|
515
|
+
const allColumns = columnRows.map((row) => ({
|
|
516
|
+
name: row.name,
|
|
517
|
+
type: row.type || 'TEXT', // SQLite allows typeless columns
|
|
518
|
+
nullable: row.notnull === 0,
|
|
519
|
+
default: row.dflt_value,
|
|
520
|
+
primaryKey: row.pk > 0,
|
|
521
|
+
}));
|
|
522
|
+
const allIndexes = indexListRows.map((idx) => {
|
|
523
|
+
// Get columns for this index
|
|
524
|
+
const indexInfoStmt = this.db.prepare(`PRAGMA index_info(${this.escapeIdentifier(idx.name)})`);
|
|
525
|
+
const indexInfoRows = indexInfoStmt.all();
|
|
526
|
+
const columns = indexInfoRows
|
|
527
|
+
.sort((a, b) => a.seqno - b.seqno)
|
|
528
|
+
.map((info) => info.name);
|
|
529
|
+
return {
|
|
530
|
+
name: idx.name,
|
|
531
|
+
columns,
|
|
532
|
+
unique: idx.unique === 1,
|
|
533
|
+
primary: idx.origin === 'pk',
|
|
534
|
+
};
|
|
535
|
+
});
|
|
536
|
+
// Build foreign keys array
|
|
537
|
+
const foreignKeys = fkRows.map((fk) => ({
|
|
538
|
+
column: fk.from,
|
|
539
|
+
references: {
|
|
540
|
+
table: fk.table,
|
|
541
|
+
column: fk.to,
|
|
542
|
+
},
|
|
543
|
+
}));
|
|
544
|
+
// Apply limits and track truncation
|
|
545
|
+
let truncated = false;
|
|
546
|
+
const truncationReasons = [];
|
|
547
|
+
const columns = allColumns.length > limits.maxColumns
|
|
548
|
+
? ((truncated = true),
|
|
549
|
+
truncationReasons.push(`columns (${allColumns.length} > ${limits.maxColumns})`),
|
|
550
|
+
allColumns.slice(0, limits.maxColumns))
|
|
551
|
+
: allColumns;
|
|
552
|
+
const indexes = allIndexes.length > limits.maxIndexes
|
|
553
|
+
? ((truncated = true),
|
|
554
|
+
truncationReasons.push(`indexes (${allIndexes.length} > ${limits.maxIndexes})`),
|
|
555
|
+
allIndexes.slice(0, limits.maxIndexes))
|
|
556
|
+
: allIndexes;
|
|
557
|
+
return {
|
|
558
|
+
table,
|
|
559
|
+
schema: 'main',
|
|
560
|
+
columns,
|
|
561
|
+
indexes,
|
|
562
|
+
foreignKeys,
|
|
563
|
+
truncated,
|
|
564
|
+
...(truncated && { truncationReason: truncationReasons.join(', ') }),
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Escape a SQLite identifier (table/column name)
|
|
569
|
+
*
|
|
570
|
+
* SQLite uses double quotes for identifiers.
|
|
571
|
+
* Double any existing double quotes to escape them.
|
|
572
|
+
*
|
|
573
|
+
* @param name - Identifier to escape
|
|
574
|
+
* @returns Safely quoted identifier
|
|
575
|
+
*/
|
|
576
|
+
escapeIdentifier(name) {
|
|
577
|
+
// Replace any double quotes with two double quotes (escape)
|
|
578
|
+
const escaped = name.replace(/"/g, '""');
|
|
579
|
+
return `"${escaped}"`;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/adapters/sqlite/adapter.ts"],"names":[],"mappings":"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"}
|