@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.
Files changed (95) hide show
  1. package/README.md +442 -0
  2. package/databases.example.json +18 -0
  3. package/dist/__integration__/global-setup.d.ts +8 -0
  4. package/dist/__integration__/global-setup.d.ts.map +1 -0
  5. package/dist/__integration__/global-setup.js +34 -0
  6. package/dist/__integration__/global-setup.js.map +1 -0
  7. package/dist/__integration__/global-teardown.d.ts +8 -0
  8. package/dist/__integration__/global-teardown.d.ts.map +1 -0
  9. package/dist/__integration__/global-teardown.js +17 -0
  10. package/dist/__integration__/global-teardown.js.map +1 -0
  11. package/dist/__integration__/helpers.d.ts +58 -0
  12. package/dist/__integration__/helpers.d.ts.map +1 -0
  13. package/dist/__integration__/helpers.js +568 -0
  14. package/dist/__integration__/helpers.js.map +1 -0
  15. package/dist/__integration__/setup.d.ts +79 -0
  16. package/dist/__integration__/setup.d.ts.map +1 -0
  17. package/dist/__integration__/setup.js +230 -0
  18. package/dist/__integration__/setup.js.map +1 -0
  19. package/dist/adapters/factory.d.ts +40 -0
  20. package/dist/adapters/factory.d.ts.map +1 -0
  21. package/dist/adapters/factory.js +114 -0
  22. package/dist/adapters/factory.js.map +1 -0
  23. package/dist/adapters/index.d.ts +31 -0
  24. package/dist/adapters/index.d.ts.map +1 -0
  25. package/dist/adapters/index.js +34 -0
  26. package/dist/adapters/index.js.map +1 -0
  27. package/dist/adapters/mysql/adapter.d.ts +61 -0
  28. package/dist/adapters/mysql/adapter.d.ts.map +1 -0
  29. package/dist/adapters/mysql/adapter.js +567 -0
  30. package/dist/adapters/mysql/adapter.js.map +1 -0
  31. package/dist/adapters/postgresql/adapter.d.ts +52 -0
  32. package/dist/adapters/postgresql/adapter.d.ts.map +1 -0
  33. package/dist/adapters/postgresql/adapter.js +429 -0
  34. package/dist/adapters/postgresql/adapter.js.map +1 -0
  35. package/dist/adapters/sqlite/adapter.d.ts +56 -0
  36. package/dist/adapters/sqlite/adapter.d.ts.map +1 -0
  37. package/dist/adapters/sqlite/adapter.js +582 -0
  38. package/dist/adapters/sqlite/adapter.js.map +1 -0
  39. package/dist/adapters/types.d.ts +155 -0
  40. package/dist/adapters/types.d.ts.map +1 -0
  41. package/dist/adapters/types.js +7 -0
  42. package/dist/adapters/types.js.map +1 -0
  43. package/dist/config/loader.d.ts +11 -0
  44. package/dist/config/loader.d.ts.map +1 -0
  45. package/dist/config/loader.js +127 -0
  46. package/dist/config/loader.js.map +1 -0
  47. package/dist/index.d.ts +8 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +38 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/server.d.ts +21 -0
  52. package/dist/server.d.ts.map +1 -0
  53. package/dist/server.js +191 -0
  54. package/dist/server.js.map +1 -0
  55. package/dist/tools/describe-table.d.ts +11 -0
  56. package/dist/tools/describe-table.d.ts.map +1 -0
  57. package/dist/tools/describe-table.js +23 -0
  58. package/dist/tools/describe-table.js.map +1 -0
  59. package/dist/tools/execute.d.ts +22 -0
  60. package/dist/tools/execute.d.ts.map +1 -0
  61. package/dist/tools/execute.js +48 -0
  62. package/dist/tools/execute.js.map +1 -0
  63. package/dist/tools/explain.d.ts +25 -0
  64. package/dist/tools/explain.d.ts.map +1 -0
  65. package/dist/tools/explain.js +81 -0
  66. package/dist/tools/explain.js.map +1 -0
  67. package/dist/tools/list-databases.d.ts +18 -0
  68. package/dist/tools/list-databases.d.ts.map +1 -0
  69. package/dist/tools/list-databases.js +17 -0
  70. package/dist/tools/list-databases.js.map +1 -0
  71. package/dist/tools/list-tables.d.ts +22 -0
  72. package/dist/tools/list-tables.d.ts.map +1 -0
  73. package/dist/tools/list-tables.js +43 -0
  74. package/dist/tools/list-tables.js.map +1 -0
  75. package/dist/tools/query.d.ts +25 -0
  76. package/dist/tools/query.d.ts.map +1 -0
  77. package/dist/tools/query.js +109 -0
  78. package/dist/tools/query.js.map +1 -0
  79. package/dist/types.d.ts +93 -0
  80. package/dist/types.d.ts.map +1 -0
  81. package/dist/types.js +5 -0
  82. package/dist/types.js.map +1 -0
  83. package/dist/utils/errors.d.ts +22 -0
  84. package/dist/utils/errors.d.ts.map +1 -0
  85. package/dist/utils/errors.js +41 -0
  86. package/dist/utils/errors.js.map +1 -0
  87. package/dist/utils/formatter.d.ts +13 -0
  88. package/dist/utils/formatter.d.ts.map +1 -0
  89. package/dist/utils/formatter.js +56 -0
  90. package/dist/utils/formatter.js.map +1 -0
  91. package/dist/utils/truncate.d.ts +37 -0
  92. package/dist/utils/truncate.d.ts.map +1 -0
  93. package/dist/utils/truncate.js +91 -0
  94. package/dist/utils/truncate.js.map +1 -0
  95. package/package.json +65 -0
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Integration test setup utilities
3
+ *
4
+ * Manages PostgreSQL and MySQL Docker containers using Testcontainers, and SQLite file database for integration tests.
5
+ */
6
+ import pg from 'pg';
7
+ import * as mysql from 'mysql2/promise';
8
+ import Database from 'better-sqlite3';
9
+ import * as fs from 'fs';
10
+ import * as path from 'path';
11
+ import { PostgreSqlContainer } from '@testcontainers/postgresql';
12
+ import { MySqlContainer } from '@testcontainers/mysql';
13
+ const TEST_SQLITE_DB_PATH = './test-data/test.db';
14
+ // Global container instances (set during startContainers)
15
+ let postgresContainer = null;
16
+ let mysqlContainer = null;
17
+ // Connection strings (set dynamically after containers start)
18
+ let TEST_PG_URL;
19
+ let TEST_MYSQL_URL;
20
+ /**
21
+ * Start the test containers (PostgreSQL and MySQL) using Testcontainers
22
+ */
23
+ export async function startContainers() {
24
+ if (postgresContainer && mysqlContainer) {
25
+ console.log('Test containers already running');
26
+ return;
27
+ }
28
+ console.log('Starting PostgreSQL container...');
29
+ postgresContainer = await new PostgreSqlContainer('postgres:16-alpine')
30
+ .withDatabase('test_db')
31
+ .withUsername('test_user')
32
+ .withPassword('test_password')
33
+ .withTmpFs({ '/var/lib/postgresql/data': 'rw' })
34
+ .start();
35
+ TEST_PG_URL = postgresContainer.getConnectionUri();
36
+ // Store in environment variable so test files can access it
37
+ process.env.TEST_POSTGRES_URL = TEST_PG_URL;
38
+ console.log(`PostgreSQL ready on port ${postgresContainer.getPort()}`);
39
+ console.log('Starting MySQL container...');
40
+ mysqlContainer = await new MySqlContainer('mysql:8.0')
41
+ .withDatabase('test_db')
42
+ .withUsername('test_user')
43
+ .withUserPassword('test_password')
44
+ .withRootPassword('root_password')
45
+ .withTmpFs({ '/var/lib/mysql': 'rw' })
46
+ .start();
47
+ TEST_MYSQL_URL = mysqlContainer.getConnectionUri();
48
+ // Store in environment variable so test files can access it
49
+ process.env.TEST_MYSQL_URL = TEST_MYSQL_URL;
50
+ console.log(`MySQL ready on port ${mysqlContainer.getPort()}`);
51
+ }
52
+ /**
53
+ * Start the test PostgreSQL container (backward compatibility)
54
+ */
55
+ export async function startPostgres() {
56
+ await startContainers();
57
+ }
58
+ /**
59
+ * Stop the test containers
60
+ */
61
+ export async function stopContainers() {
62
+ console.log('Stopping test containers...');
63
+ if (postgresContainer) {
64
+ await postgresContainer.stop();
65
+ postgresContainer = null;
66
+ }
67
+ if (mysqlContainer) {
68
+ await mysqlContainer.stop();
69
+ mysqlContainer = null;
70
+ }
71
+ console.log('Test containers stopped');
72
+ }
73
+ /**
74
+ * Stop the test PostgreSQL container (backward compatibility)
75
+ */
76
+ export async function stopPostgres() {
77
+ await stopContainers();
78
+ }
79
+ /**
80
+ * Get the PostgreSQL connection URL (set after containers start)
81
+ */
82
+ export function getPostgresUrl() {
83
+ // Read from environment variable (set by global-setup)
84
+ const url = process.env.TEST_POSTGRES_URL || TEST_PG_URL;
85
+ if (!url) {
86
+ throw new Error('PostgreSQL container not started yet');
87
+ }
88
+ return url;
89
+ }
90
+ /**
91
+ * Get the MySQL connection URL (set after containers start)
92
+ */
93
+ export function getMySqlUrl() {
94
+ // Read from environment variable (set by global-setup)
95
+ const url = process.env.TEST_MYSQL_URL || TEST_MYSQL_URL;
96
+ if (!url) {
97
+ throw new Error('MySQL container not started yet');
98
+ }
99
+ return url;
100
+ }
101
+ /**
102
+ * Get a direct PostgreSQL database client for test verification
103
+ */
104
+ export async function getTestClient() {
105
+ const client = new pg.Client({ connectionString: getPostgresUrl() });
106
+ await client.connect();
107
+ return client;
108
+ }
109
+ /**
110
+ * Execute SQL directly for test setup/verification (PostgreSQL)
111
+ */
112
+ export async function execSql(sql, params) {
113
+ const client = await getTestClient();
114
+ try {
115
+ return await client.query(sql, params);
116
+ }
117
+ finally {
118
+ await client.end();
119
+ }
120
+ }
121
+ /**
122
+ * Get a direct MySQL database connection for test verification
123
+ */
124
+ export async function getMySqlTestConnection() {
125
+ return await mysql.createConnection(getMySqlUrl());
126
+ }
127
+ /**
128
+ * Execute SQL directly for test setup/verification (MySQL)
129
+ */
130
+ export async function execMySql(sql, params) {
131
+ const connection = await getMySqlTestConnection();
132
+ try {
133
+ const [result] = await connection.execute(sql, params);
134
+ return result;
135
+ }
136
+ finally {
137
+ await connection.end();
138
+ }
139
+ }
140
+ /**
141
+ * Execute multiple SQL statements in a single connection (MySQL)
142
+ * Useful when session state needs to persist (e.g., FOREIGN_KEY_CHECKS)
143
+ */
144
+ export async function execMySqlBatch(statements) {
145
+ const connection = await getMySqlTestConnection();
146
+ try {
147
+ for (const sql of statements) {
148
+ await connection.execute(sql);
149
+ }
150
+ }
151
+ finally {
152
+ await connection.end();
153
+ }
154
+ }
155
+ // ============================================================================
156
+ // SQLite Setup Utilities (No Docker needed)
157
+ // ============================================================================
158
+ /**
159
+ * Create the SQLite test database directory and file
160
+ */
161
+ export function createSqliteTestDb() {
162
+ const dbDir = path.dirname(TEST_SQLITE_DB_PATH);
163
+ // Create test-data directory if it doesn't exist
164
+ if (!fs.existsSync(dbDir)) {
165
+ fs.mkdirSync(dbDir, { recursive: true });
166
+ console.log(`Created directory: ${dbDir}`);
167
+ }
168
+ // Create empty database file (better-sqlite3 will create tables)
169
+ const db = new Database(TEST_SQLITE_DB_PATH);
170
+ // Enable foreign key support
171
+ db.pragma('foreign_keys = ON');
172
+ db.close();
173
+ console.log(`Created SQLite database: ${TEST_SQLITE_DB_PATH}`);
174
+ }
175
+ /**
176
+ * Delete the SQLite test database file
177
+ */
178
+ export function deleteSqliteTestDb() {
179
+ if (fs.existsSync(TEST_SQLITE_DB_PATH)) {
180
+ fs.unlinkSync(TEST_SQLITE_DB_PATH);
181
+ console.log(`Deleted SQLite database: ${TEST_SQLITE_DB_PATH}`);
182
+ }
183
+ // Also clean up the -wal and -shm files if they exist
184
+ const walPath = TEST_SQLITE_DB_PATH + '-wal';
185
+ const shmPath = TEST_SQLITE_DB_PATH + '-shm';
186
+ if (fs.existsSync(walPath)) {
187
+ fs.unlinkSync(walPath);
188
+ }
189
+ if (fs.existsSync(shmPath)) {
190
+ fs.unlinkSync(shmPath);
191
+ }
192
+ }
193
+ /**
194
+ * Get a SQLite database connection for test setup/verification
195
+ */
196
+ export function getSqliteTestDb() {
197
+ const db = new Database(TEST_SQLITE_DB_PATH);
198
+ // Enable foreign key support for each connection
199
+ db.pragma('foreign_keys = ON');
200
+ return db;
201
+ }
202
+ /**
203
+ * Execute SQL directly for test setup/verification (SQLite)
204
+ */
205
+ export async function execSqliteSql(sql) {
206
+ const db = getSqliteTestDb();
207
+ try {
208
+ db.exec(sql);
209
+ }
210
+ finally {
211
+ db.close();
212
+ }
213
+ }
214
+ /**
215
+ * Execute a query and return results (SQLite)
216
+ */
217
+ export async function querySqliteSql(sql) {
218
+ const db = getSqliteTestDb();
219
+ try {
220
+ return db.prepare(sql).all();
221
+ }
222
+ finally {
223
+ db.close();
224
+ }
225
+ }
226
+ /**
227
+ * Export SQLite path for use in helpers
228
+ */
229
+ export { TEST_SQLITE_DB_PATH };
230
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/__integration__/setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAA8B,MAAM,4BAA4B,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAyB,MAAM,uBAAuB,CAAC;AAE9E,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAElD,0DAA0D;AAC1D,IAAI,iBAAiB,GAAsC,IAAI,CAAC;AAChE,IAAI,cAAc,GAAiC,IAAI,CAAC;AAExD,8DAA8D;AAC9D,IAAI,WAAmB,CAAC;AACxB,IAAI,cAAsB,CAAC;AAE3B;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,iBAAiB,IAAI,cAAc,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;QAC/C,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,iBAAiB,GAAG,MAAM,IAAI,mBAAmB,CAAC,oBAAoB,CAAC;SACpE,YAAY,CAAC,SAAS,CAAC;SACvB,YAAY,CAAC,WAAW,CAAC;SACzB,YAAY,CAAC,eAAe,CAAC;SAC7B,SAAS,CAAC,EAAE,0BAA0B,EAAE,IAAI,EAAE,CAAC;SAC/C,KAAK,EAAE,CAAC;IAEX,WAAW,GAAG,iBAAiB,CAAC,gBAAgB,EAAE,CAAC;IACnD,4DAA4D;IAC5D,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,WAAW,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,4BAA4B,iBAAiB,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAEvE,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC3C,cAAc,GAAG,MAAM,IAAI,cAAc,CAAC,WAAW,CAAC;SACnD,YAAY,CAAC,SAAS,CAAC;SACvB,YAAY,CAAC,WAAW,CAAC;SACzB,gBAAgB,CAAC,eAAe,CAAC;SACjC,gBAAgB,CAAC,eAAe,CAAC;SACjC,SAAS,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC;SACrC,KAAK,EAAE,CAAC;IAEX,cAAc,GAAG,cAAc,CAAC,gBAAgB,EAAE,CAAC;IACnD,4DAA4D;IAC5D,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,cAAc,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,uBAAuB,cAAc,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AACjE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,eAAe,EAAE,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAE3C,IAAI,iBAAiB,EAAE,CAAC;QACtB,MAAM,iBAAiB,CAAC,IAAI,EAAE,CAAC;QAC/B,iBAAiB,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,cAAc,CAAC,IAAI,EAAE,CAAC;QAC5B,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,cAAc,EAAE,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,uDAAuD;IACvD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,WAAW,CAAC;IACzD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,uDAAuD;IACvD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,cAAc,CAAC;IACzD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC;IACrE,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACvB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAW,EAAE,MAAkB;IAC3D,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;IACrB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC1C,OAAO,MAAM,KAAK,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,MAAkB;IAC7D,MAAM,UAAU,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAClD,IAAI,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACvD,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,MAAM,UAAU,CAAC,GAAG,EAAE,CAAC;IACzB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAAoB;IACvD,MAAM,UAAU,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAClD,IAAI,CAAC;QACH,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,MAAM,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,UAAU,CAAC,GAAG,EAAE,CAAC;IACzB,CAAC;AACH,CAAC;AAGD,+EAA+E;AAC/E,4CAA4C;AAC5C,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAEhD,iDAAiD;IACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,iEAAiE;IACjE,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IAE7C,6BAA6B;IAC7B,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAE/B,EAAE,CAAC,KAAK,EAAE,CAAC;IACX,OAAO,CAAC,GAAG,CAAC,4BAA4B,mBAAmB,EAAE,CAAC,CAAC;AACjE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,IAAI,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACvC,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,4BAA4B,mBAAmB,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,sDAAsD;IACtD,MAAM,OAAO,GAAG,mBAAmB,GAAG,MAAM,CAAC;IAC7C,MAAM,OAAO,GAAG,mBAAmB,GAAG,MAAM,CAAC;IAE7C,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IAC7C,iDAAiD;IACjD,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC/B,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAW;IAC7C,MAAM,EAAE,GAAG,eAAe,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAW;IAC9C,MAAM,EAAE,GAAG,eAAe,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IAC/B,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED;;GAEG;AACH,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Database Adapter Factory
3
+ *
4
+ * Creates the appropriate database adapter based on connection URL scheme.
5
+ *
6
+ * Phase 1: PostgreSQL - DONE
7
+ * Phase 2: MySQL - DONE
8
+ * Phase 3: SQLite - DONE
9
+ */
10
+ import type { DatabaseAdapter } from './types.js';
11
+ import type { DatabaseConfig, DefaultsConfig } from '../types.js';
12
+ /**
13
+ * Create a database adapter based on configuration
14
+ *
15
+ * Auto-detects database type from URL scheme:
16
+ * - `postgresql://` or `postgres://` -> PostgreSQL adapter
17
+ * - `mysql://` -> MySQL adapter
18
+ * - `sqlite://` or `.db`/`.sqlite` file path -> SQLite adapter
19
+ *
20
+ * @param database - Database configuration (url, readonly, etc.)
21
+ * @param defaults - Default settings (timeout, limits)
22
+ * @returns Appropriate DatabaseAdapter instance
23
+ * @throws DbMcpError if database type is not supported
24
+ */
25
+ export declare function createAdapter(database: DatabaseConfig, defaults: DefaultsConfig): DatabaseAdapter;
26
+ /**
27
+ * Check if a URL is for a supported database type
28
+ *
29
+ * @param url - Database connection URL
30
+ * @returns true if the URL scheme is recognized
31
+ */
32
+ export declare function isSupportedUrl(url: string): boolean;
33
+ /**
34
+ * Check if a database type is currently implemented
35
+ *
36
+ * @param url - Database connection URL
37
+ * @returns true if the database type can be used now
38
+ */
39
+ export declare function isImplemented(url: string): boolean;
40
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/adapters/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA+ElE;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,cAAc,GACvB,eAAe,CASjB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQlD"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Database Adapter Factory
3
+ *
4
+ * Creates the appropriate database adapter based on connection URL scheme.
5
+ *
6
+ * Phase 1: PostgreSQL - DONE
7
+ * Phase 2: MySQL - DONE
8
+ * Phase 3: SQLite - DONE
9
+ */
10
+ import { PostgreSqlAdapter } from './postgresql/adapter.js';
11
+ import { MySqlAdapter } from './mysql/adapter.js';
12
+ import { SqliteAdapter } from './sqlite/adapter.js';
13
+ import { DbMcpError, ErrorCode } from '../utils/errors.js';
14
+ /**
15
+ * Detect database type from URL scheme
16
+ *
17
+ * @param url - Database connection URL
18
+ * @returns Database scheme type
19
+ * @throws DbMcpError if scheme is not recognized
20
+ */
21
+ function detectScheme(url) {
22
+ // PostgreSQL: postgresql:// or postgres://
23
+ if (url.startsWith('postgresql://') || url.startsWith('postgres://')) {
24
+ return 'postgresql';
25
+ }
26
+ // MySQL: mysql://
27
+ if (url.startsWith('mysql://')) {
28
+ return 'mysql';
29
+ }
30
+ // SQLite: sqlite:// or file path ending in .db/.sqlite/.sqlite3
31
+ if (url.startsWith('sqlite://') ||
32
+ url.endsWith('.db') ||
33
+ url.endsWith('.sqlite') ||
34
+ url.endsWith('.sqlite3')) {
35
+ return 'sqlite';
36
+ }
37
+ throw new DbMcpError(ErrorCode.CONFIG_INVALID, `Unknown database URL scheme: ${url}. ` +
38
+ 'Supported schemes: postgresql://, postgres://, mysql://, sqlite://', { url });
39
+ }
40
+ /**
41
+ * Create a base database adapter (without SSH wrapping)
42
+ *
43
+ * @param config - Adapter configuration
44
+ * @param scheme - Database scheme type
45
+ * @returns Appropriate DatabaseAdapter instance
46
+ */
47
+ function createBaseAdapter(config, scheme) {
48
+ switch (scheme) {
49
+ case 'postgresql':
50
+ return new PostgreSqlAdapter(config);
51
+ case 'mysql':
52
+ return new MySqlAdapter(config);
53
+ case 'sqlite':
54
+ return new SqliteAdapter(config);
55
+ default: {
56
+ // TypeScript exhaustive check
57
+ const _exhaustive = scheme;
58
+ throw new DbMcpError(ErrorCode.CONFIG_INVALID, `Unexpected database scheme: ${_exhaustive}`);
59
+ }
60
+ }
61
+ }
62
+ /**
63
+ * Create a database adapter based on configuration
64
+ *
65
+ * Auto-detects database type from URL scheme:
66
+ * - `postgresql://` or `postgres://` -> PostgreSQL adapter
67
+ * - `mysql://` -> MySQL adapter
68
+ * - `sqlite://` or `.db`/`.sqlite` file path -> SQLite adapter
69
+ *
70
+ * @param database - Database configuration (url, readonly, etc.)
71
+ * @param defaults - Default settings (timeout, limits)
72
+ * @returns Appropriate DatabaseAdapter instance
73
+ * @throws DbMcpError if database type is not supported
74
+ */
75
+ export function createAdapter(database, defaults) {
76
+ const scheme = detectScheme(database.url);
77
+ const config = {
78
+ database,
79
+ defaults,
80
+ };
81
+ return createBaseAdapter(config, scheme);
82
+ }
83
+ /**
84
+ * Check if a URL is for a supported database type
85
+ *
86
+ * @param url - Database connection URL
87
+ * @returns true if the URL scheme is recognized
88
+ */
89
+ export function isSupportedUrl(url) {
90
+ try {
91
+ detectScheme(url);
92
+ return true;
93
+ }
94
+ catch {
95
+ return false;
96
+ }
97
+ }
98
+ /**
99
+ * Check if a database type is currently implemented
100
+ *
101
+ * @param url - Database connection URL
102
+ * @returns true if the database type can be used now
103
+ */
104
+ export function isImplemented(url) {
105
+ try {
106
+ const scheme = detectScheme(url);
107
+ // All three database types are now implemented (Phase 1-3)
108
+ return scheme === 'postgresql' || scheme === 'mysql' || scheme === 'sqlite';
109
+ }
110
+ catch {
111
+ return false;
112
+ }
113
+ }
114
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/adapters/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAO3D;;;;;;GAMG;AACH,SAAS,YAAY,CAAC,GAAW;IAC/B,2CAA2C;IAC3C,IAAI,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACrE,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,kBAAkB;IAClB,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,gEAAgE;IAChE,IACE,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC;QAC3B,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnB,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;QACvB,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,EACxB,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,UAAU,CAClB,SAAS,CAAC,cAAc,EACxB,gCAAgC,GAAG,IAAI;QACrC,oEAAoE,EACtE,EAAE,GAAG,EAAE,CACR,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,iBAAiB,CACxB,MAAqB,EACrB,MAAsB;IAEtB,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,YAAY;YACf,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAEvC,KAAK,OAAO;YACV,OAAO,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;QAElC,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;QAEnC,OAAO,CAAC,CAAC,CAAC;YACR,8BAA8B;YAC9B,MAAM,WAAW,GAAU,MAAM,CAAC;YAClC,MAAM,IAAI,UAAU,CAClB,SAAS,CAAC,cAAc,EACxB,+BAA+B,WAAW,EAAE,CAC7C,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAC3B,QAAwB,EACxB,QAAwB;IAExB,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAE1C,MAAM,MAAM,GAAkB;QAC5B,QAAQ;QACR,QAAQ;KACT,CAAC;IAEF,OAAO,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,CAAC;QACH,YAAY,CAAC,GAAG,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QACjC,2DAA2D;QAC3D,OAAO,MAAM,KAAK,YAAY,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,QAAQ,CAAC;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Database Adapters Module
3
+ *
4
+ * Barrel file exporting all adapter-related types and implementations.
5
+ *
6
+ * Usage:
7
+ * ```typescript
8
+ * import {
9
+ * createAdapter,
10
+ * DatabaseAdapter,
11
+ * AdapterConnection,
12
+ * } from './adapters/index.js';
13
+ *
14
+ * const adapter = createAdapter(dbConfig, defaults);
15
+ *
16
+ * // SQL dialect methods are now part of the adapter
17
+ * adapter.validateQueryForTool(sql, 'query');
18
+ * const parsed = adapter.parseQuery(sql);
19
+ *
20
+ * await adapter.withConnection(async (conn) => {
21
+ * const result = await conn.query('SELECT * FROM users WHERE id = $1', [1]);
22
+ * return result;
23
+ * });
24
+ * ```
25
+ */
26
+ export type { DatabaseAdapter, AdapterConnection, RawQueryResult, AdapterConfig, ListTablesInternalResult, } from './types.js';
27
+ export { createAdapter, isSupportedUrl, isImplemented } from './factory.js';
28
+ export { PostgreSqlAdapter } from './postgresql/adapter.js';
29
+ export { MySqlAdapter } from './mysql/adapter.js';
30
+ export { SqliteAdapter } from './sqlite/adapter.js';
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Database Adapters Module
3
+ *
4
+ * Barrel file exporting all adapter-related types and implementations.
5
+ *
6
+ * Usage:
7
+ * ```typescript
8
+ * import {
9
+ * createAdapter,
10
+ * DatabaseAdapter,
11
+ * AdapterConnection,
12
+ * } from './adapters/index.js';
13
+ *
14
+ * const adapter = createAdapter(dbConfig, defaults);
15
+ *
16
+ * // SQL dialect methods are now part of the adapter
17
+ * adapter.validateQueryForTool(sql, 'query');
18
+ * const parsed = adapter.parseQuery(sql);
19
+ *
20
+ * await adapter.withConnection(async (conn) => {
21
+ * const result = await conn.query('SELECT * FROM users WHERE id = $1', [1]);
22
+ * return result;
23
+ * });
24
+ * ```
25
+ */
26
+ // Factory
27
+ export { createAdapter, isSupportedUrl, isImplemented } from './factory.js';
28
+ // PostgreSQL (explicit exports for testing/extension)
29
+ export { PostgreSqlAdapter } from './postgresql/adapter.js';
30
+ // MySQL (explicit exports for testing/extension)
31
+ export { MySqlAdapter } from './mysql/adapter.js';
32
+ // SQLite (explicit exports for testing/extension)
33
+ export { SqliteAdapter } from './sqlite/adapter.js';
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAWH,UAAU;AACV,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE5E,sDAAsD;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,iDAAiD;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,kDAAkD;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * MySQL Database Adapter
3
+ *
4
+ * Implements DatabaseAdapter interface for MySQL databases.
5
+ * Uses mysql2/promise driver with per-request connection recycling.
6
+ */
7
+ import type { DatabaseAdapter, AdapterConnection, AdapterConfig } from '../types.js';
8
+ import type { ParsedQuery } from '../../types.js';
9
+ /**
10
+ * Strip SQL comments from a query
11
+ */
12
+ declare function stripComments(sql: string): string;
13
+ /**
14
+ * String-aware statement splitting
15
+ */
16
+ declare function splitStatements(sql: string): string[];
17
+ /**
18
+ * MySQL database adapter
19
+ *
20
+ * Creates new connections for each request to prevent session state attacks.
21
+ */
22
+ export declare class MySqlAdapter implements DatabaseAdapter {
23
+ readonly type: "mysql";
24
+ private readonly connectionUrl;
25
+ private readonly timeout;
26
+ constructor(config: AdapterConfig);
27
+ /**
28
+ * Get the default schema name for MySQL (database name from URL)
29
+ */
30
+ getDefaultSchema(): string;
31
+ /**
32
+ * Parse and validate a SQL query
33
+ */
34
+ parseQuery(sql: string): ParsedQuery;
35
+ /**
36
+ * Inject a LIMIT clause into a SELECT query if it doesn't have one
37
+ */
38
+ injectLimit(sql: string, limit: number): string;
39
+ /**
40
+ * Validate that a SQL query is appropriate for a specific tool
41
+ */
42
+ validateQueryForTool(sql: string, tool: 'query' | 'execute'): void;
43
+ /**
44
+ * Get the EXPLAIN prefix for MySQL
45
+ */
46
+ getExplainPrefix(analyze: boolean): string;
47
+ /**
48
+ * Convert PostgreSQL-style placeholders ($1, $2) to MySQL-style (?)
49
+ */
50
+ convertPlaceholders(sql: string): string;
51
+ /**
52
+ * Execute a function with a managed MySQL connection
53
+ */
54
+ withConnection<T>(fn: (conn: AdapterConnection) => Promise<T>): Promise<T>;
55
+ /**
56
+ * Clean up resources (no persistent resources in this adapter)
57
+ */
58
+ dispose(): Promise<void>;
59
+ }
60
+ export { stripComments, splitStatements };
61
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/mysql/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EAEjB,aAAa,EAEd,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,WAAW,EAOZ,MAAM,gBAAgB,CAAC;AA6CxB;;GAEG;AACH,iBAAS,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA0E1C;AAED;;GAEG;AACH,iBAAS,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAwD9C;AAgED;;;;GAIG;AACH,qBAAa,YAAa,YAAW,eAAe;IAClD,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IAEjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,aAAa;IAKjC;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAa1B;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW;IAsDpC;;OAEG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAQ/C;;OAEG;IACH,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI;IAyClE;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAI1C;;OAEG;IACH,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIxC;;OAEG;IACG,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA0ChF;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAI/B;AAsND,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC"}