@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,568 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration test helpers
|
|
3
|
+
*
|
|
4
|
+
* Provides test configuration factory and database utilities.
|
|
5
|
+
*/
|
|
6
|
+
import { execSql, execSqliteSql, getSqliteTestDb, execMySql, execMySqlBatch, getPostgresUrl, getMySqlUrl } from './setup.js';
|
|
7
|
+
const TEST_SQLITE_DB_PATH = './test-data/test.db';
|
|
8
|
+
/**
|
|
9
|
+
* Create a test configuration with optional overrides
|
|
10
|
+
*/
|
|
11
|
+
export function createTestConfig(overrides) {
|
|
12
|
+
const postgresUrl = getPostgresUrl();
|
|
13
|
+
const base = {
|
|
14
|
+
databases: {
|
|
15
|
+
testdb: {
|
|
16
|
+
url: postgresUrl,
|
|
17
|
+
readonly: false,
|
|
18
|
+
},
|
|
19
|
+
readonlydb: {
|
|
20
|
+
url: postgresUrl,
|
|
21
|
+
readonly: true,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
defaults: {
|
|
25
|
+
maxRows: 100,
|
|
26
|
+
maxCellLength: 500,
|
|
27
|
+
maxTotalSize: 65536,
|
|
28
|
+
maxColumns: 50,
|
|
29
|
+
maxTables: 200,
|
|
30
|
+
maxIndexes: 20,
|
|
31
|
+
timeout: 30000,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
if (!overrides) {
|
|
35
|
+
return base;
|
|
36
|
+
}
|
|
37
|
+
// Handle databases override - if explicitly provided, use it directly
|
|
38
|
+
const databases = 'databases' in overrides
|
|
39
|
+
? overrides.databases ?? base.databases
|
|
40
|
+
: base.databases;
|
|
41
|
+
// Handle defaults override - merge with base
|
|
42
|
+
const defaults = 'defaults' in overrides
|
|
43
|
+
? { ...base.defaults, ...overrides.defaults }
|
|
44
|
+
: base.defaults;
|
|
45
|
+
return { databases, defaults };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Initialize the test database schema
|
|
49
|
+
*/
|
|
50
|
+
export async function initializeSchema() {
|
|
51
|
+
const schema = `
|
|
52
|
+
-- Drop existing tables in reverse FK order
|
|
53
|
+
DROP TABLE IF EXISTS order_items CASCADE;
|
|
54
|
+
DROP TABLE IF EXISTS orders CASCADE;
|
|
55
|
+
DROP TABLE IF EXISTS products CASCADE;
|
|
56
|
+
DROP TABLE IF EXISTS users CASCADE;
|
|
57
|
+
DROP TABLE IF EXISTS wide_table CASCADE;
|
|
58
|
+
DROP VIEW IF EXISTS user_order_summary CASCADE;
|
|
59
|
+
DROP SCHEMA IF EXISTS test_schema CASCADE;
|
|
60
|
+
|
|
61
|
+
-- Users table with various column types
|
|
62
|
+
CREATE TABLE users (
|
|
63
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
64
|
+
email VARCHAR(255) NOT NULL UNIQUE,
|
|
65
|
+
name VARCHAR(100),
|
|
66
|
+
age INTEGER,
|
|
67
|
+
balance DECIMAL(10, 2) DEFAULT 0.00,
|
|
68
|
+
metadata JSONB,
|
|
69
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
70
|
+
updated_at TIMESTAMPTZ,
|
|
71
|
+
is_active BOOLEAN DEFAULT true
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
-- Indexes for testing
|
|
75
|
+
CREATE INDEX users_created_at_idx ON users(created_at);
|
|
76
|
+
CREATE INDEX users_name_email_idx ON users(name, email);
|
|
77
|
+
|
|
78
|
+
-- Products table
|
|
79
|
+
CREATE TABLE products (
|
|
80
|
+
id SERIAL PRIMARY KEY,
|
|
81
|
+
name VARCHAR(255) NOT NULL,
|
|
82
|
+
price DECIMAL(10, 2) NOT NULL,
|
|
83
|
+
stock INTEGER DEFAULT 0,
|
|
84
|
+
category VARCHAR(100)
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
-- Orders table with foreign key
|
|
88
|
+
CREATE TABLE orders (
|
|
89
|
+
id SERIAL PRIMARY KEY,
|
|
90
|
+
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
91
|
+
total DECIMAL(10, 2) NOT NULL,
|
|
92
|
+
status VARCHAR(50) DEFAULT 'pending',
|
|
93
|
+
items JSONB NOT NULL DEFAULT '[]',
|
|
94
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
CREATE INDEX orders_user_id_idx ON orders(user_id);
|
|
98
|
+
CREATE INDEX orders_status_idx ON orders(status);
|
|
99
|
+
|
|
100
|
+
-- Order items junction table
|
|
101
|
+
CREATE TABLE order_items (
|
|
102
|
+
order_id INTEGER NOT NULL REFERENCES orders(id),
|
|
103
|
+
product_id INTEGER NOT NULL REFERENCES products(id),
|
|
104
|
+
quantity INTEGER NOT NULL DEFAULT 1,
|
|
105
|
+
price_at_time DECIMAL(10, 2) NOT NULL,
|
|
106
|
+
PRIMARY KEY (order_id, product_id)
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
-- View for testing view detection
|
|
110
|
+
CREATE VIEW user_order_summary AS
|
|
111
|
+
SELECT
|
|
112
|
+
u.id as user_id,
|
|
113
|
+
u.email,
|
|
114
|
+
COUNT(o.id) as order_count,
|
|
115
|
+
COALESCE(SUM(o.total), 0) as total_spent
|
|
116
|
+
FROM users u
|
|
117
|
+
LEFT JOIN orders o ON u.id = o.user_id
|
|
118
|
+
GROUP BY u.id, u.email;
|
|
119
|
+
|
|
120
|
+
-- Wide table for truncation testing
|
|
121
|
+
CREATE TABLE wide_table (
|
|
122
|
+
id SERIAL PRIMARY KEY,
|
|
123
|
+
col_01 TEXT, col_02 TEXT, col_03 TEXT, col_04 TEXT, col_05 TEXT,
|
|
124
|
+
col_06 TEXT, col_07 TEXT, col_08 TEXT, col_09 TEXT, col_10 TEXT,
|
|
125
|
+
col_11 TEXT, col_12 TEXT, col_13 TEXT, col_14 TEXT, col_15 TEXT,
|
|
126
|
+
col_16 TEXT, col_17 TEXT, col_18 TEXT, col_19 TEXT, col_20 TEXT,
|
|
127
|
+
col_21 TEXT, col_22 TEXT, col_23 TEXT, col_24 TEXT, col_25 TEXT,
|
|
128
|
+
col_26 TEXT, col_27 TEXT, col_28 TEXT, col_29 TEXT, col_30 TEXT,
|
|
129
|
+
col_31 TEXT, col_32 TEXT, col_33 TEXT, col_34 TEXT, col_35 TEXT,
|
|
130
|
+
col_36 TEXT, col_37 TEXT, col_38 TEXT, col_39 TEXT, col_40 TEXT,
|
|
131
|
+
col_41 TEXT, col_42 TEXT, col_43 TEXT, col_44 TEXT, col_45 TEXT,
|
|
132
|
+
col_46 TEXT, col_47 TEXT, col_48 TEXT, col_49 TEXT, col_50 TEXT,
|
|
133
|
+
col_51 TEXT, col_52 TEXT, col_53 TEXT, col_54 TEXT, col_55 TEXT
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
-- Test schema for non-public schema testing
|
|
137
|
+
CREATE SCHEMA test_schema;
|
|
138
|
+
|
|
139
|
+
CREATE TABLE test_schema.special_table (
|
|
140
|
+
id SERIAL PRIMARY KEY,
|
|
141
|
+
data TEXT
|
|
142
|
+
);
|
|
143
|
+
`;
|
|
144
|
+
await execSql(schema);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Seed the test database with sample data
|
|
148
|
+
* Uses TRUNCATE CASCADE for fast, atomic cleanup then re-insert
|
|
149
|
+
*/
|
|
150
|
+
export async function seedTestData() {
|
|
151
|
+
// Use TRUNCATE CASCADE for fast, atomic cleanup
|
|
152
|
+
await execSql('TRUNCATE users, products, orders, order_items RESTART IDENTITY CASCADE');
|
|
153
|
+
const seed = `
|
|
154
|
+
-- Seed users
|
|
155
|
+
INSERT INTO users (id, email, name, age, balance, metadata, is_active) VALUES
|
|
156
|
+
('11111111-1111-1111-1111-111111111111', 'alice@example.com', 'Alice Smith', 30, 1000.50, '{"role": "admin"}', true),
|
|
157
|
+
('22222222-2222-2222-2222-222222222222', 'bob@example.com', 'Bob Jones', 25, 500.00, '{"role": "user"}', true),
|
|
158
|
+
('33333333-3333-3333-3333-333333333333', 'charlie@example.com', 'Charlie Brown', 35, 0.00, null, false);
|
|
159
|
+
|
|
160
|
+
-- Seed products
|
|
161
|
+
INSERT INTO products (id, name, price, stock, category) VALUES
|
|
162
|
+
(1, 'Widget', 9.99, 100, 'gadgets'),
|
|
163
|
+
(2, 'Gadget', 19.99, 50, 'gadgets'),
|
|
164
|
+
(3, 'Thingamajig', 29.99, 25, 'misc');
|
|
165
|
+
|
|
166
|
+
-- Reset sequence after explicit ID inserts
|
|
167
|
+
SELECT setval('products_id_seq', 3);
|
|
168
|
+
|
|
169
|
+
-- Seed orders
|
|
170
|
+
INSERT INTO orders (id, user_id, total, status, items) VALUES
|
|
171
|
+
(1, '11111111-1111-1111-1111-111111111111', 29.98, 'completed', '[{"product_id": 1, "qty": 2}]'),
|
|
172
|
+
(2, '11111111-1111-1111-1111-111111111111', 19.99, 'pending', '[{"product_id": 2, "qty": 1}]'),
|
|
173
|
+
(3, '22222222-2222-2222-2222-222222222222', 9.99, 'completed', '[{"product_id": 1, "qty": 1}]');
|
|
174
|
+
|
|
175
|
+
SELECT setval('orders_id_seq', 3);
|
|
176
|
+
|
|
177
|
+
-- Seed order items
|
|
178
|
+
INSERT INTO order_items (order_id, product_id, quantity, price_at_time) VALUES
|
|
179
|
+
(1, 1, 2, 9.99),
|
|
180
|
+
(2, 2, 1, 19.99),
|
|
181
|
+
(3, 1, 1, 9.99);
|
|
182
|
+
|
|
183
|
+
-- Seed test_schema
|
|
184
|
+
DELETE FROM test_schema.special_table;
|
|
185
|
+
INSERT INTO test_schema.special_table (id, data) VALUES (1, 'test data');
|
|
186
|
+
|
|
187
|
+
-- Force stats update for row estimates
|
|
188
|
+
ANALYZE;
|
|
189
|
+
`;
|
|
190
|
+
await execSql(seed);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Clean up test data between tests
|
|
194
|
+
*/
|
|
195
|
+
export async function cleanupTestData() {
|
|
196
|
+
await execSql(`
|
|
197
|
+
TRUNCATE order_items, orders, products, users RESTART IDENTITY CASCADE;
|
|
198
|
+
TRUNCATE test_schema.special_table RESTART IDENTITY CASCADE;
|
|
199
|
+
`);
|
|
200
|
+
}
|
|
201
|
+
// ============================================================================
|
|
202
|
+
// SQLite Test Configuration and Helpers
|
|
203
|
+
// ============================================================================
|
|
204
|
+
/**
|
|
205
|
+
* Create a SQLite test configuration with optional overrides
|
|
206
|
+
*/
|
|
207
|
+
export function createSqliteTestConfig(overrides) {
|
|
208
|
+
const base = {
|
|
209
|
+
databases: {
|
|
210
|
+
sqlitedb: {
|
|
211
|
+
url: `sqlite://${TEST_SQLITE_DB_PATH}`,
|
|
212
|
+
readonly: false,
|
|
213
|
+
},
|
|
214
|
+
sqlitedb_readonly: {
|
|
215
|
+
url: `sqlite://${TEST_SQLITE_DB_PATH}`,
|
|
216
|
+
readonly: true,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
defaults: {
|
|
220
|
+
maxRows: 100,
|
|
221
|
+
maxCellLength: 500,
|
|
222
|
+
maxTotalSize: 65536,
|
|
223
|
+
maxColumns: 50,
|
|
224
|
+
maxTables: 200,
|
|
225
|
+
maxIndexes: 20,
|
|
226
|
+
timeout: 30000,
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
if (!overrides) {
|
|
230
|
+
return base;
|
|
231
|
+
}
|
|
232
|
+
// Handle databases override - if explicitly provided, use it directly
|
|
233
|
+
const databases = 'databases' in overrides
|
|
234
|
+
? overrides.databases ?? base.databases
|
|
235
|
+
: base.databases;
|
|
236
|
+
// Handle defaults override - merge with base
|
|
237
|
+
const defaults = 'defaults' in overrides
|
|
238
|
+
? { ...base.defaults, ...overrides.defaults }
|
|
239
|
+
: base.defaults;
|
|
240
|
+
return { databases, defaults };
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Initialize the SQLite test database schema
|
|
244
|
+
*/
|
|
245
|
+
export async function initializeSqliteSchema() {
|
|
246
|
+
// Drop existing tables in reverse FK order
|
|
247
|
+
await execSqliteSql('DROP TABLE IF EXISTS order_items');
|
|
248
|
+
await execSqliteSql('DROP TABLE IF EXISTS orders');
|
|
249
|
+
await execSqliteSql('DROP TABLE IF EXISTS products');
|
|
250
|
+
await execSqliteSql('DROP TABLE IF EXISTS users');
|
|
251
|
+
await execSqliteSql('DROP TABLE IF EXISTS wide_table');
|
|
252
|
+
await execSqliteSql('DROP VIEW IF EXISTS user_order_summary');
|
|
253
|
+
// Users table with SQLite-compatible types
|
|
254
|
+
await execSqliteSql(`
|
|
255
|
+
CREATE TABLE users (
|
|
256
|
+
id TEXT PRIMARY KEY,
|
|
257
|
+
email TEXT NOT NULL UNIQUE,
|
|
258
|
+
name TEXT,
|
|
259
|
+
age INTEGER,
|
|
260
|
+
balance REAL DEFAULT 0.00,
|
|
261
|
+
metadata TEXT,
|
|
262
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
263
|
+
updated_at TEXT,
|
|
264
|
+
is_active INTEGER DEFAULT 1
|
|
265
|
+
)
|
|
266
|
+
`);
|
|
267
|
+
// Create indexes for testing
|
|
268
|
+
await execSqliteSql('CREATE INDEX users_created_at_idx ON users(created_at)');
|
|
269
|
+
await execSqliteSql('CREATE INDEX users_name_email_idx ON users(name, email)');
|
|
270
|
+
// Products table
|
|
271
|
+
await execSqliteSql(`
|
|
272
|
+
CREATE TABLE products (
|
|
273
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
274
|
+
name TEXT NOT NULL,
|
|
275
|
+
price REAL NOT NULL,
|
|
276
|
+
stock INTEGER DEFAULT 0,
|
|
277
|
+
category TEXT
|
|
278
|
+
)
|
|
279
|
+
`);
|
|
280
|
+
// Orders table with foreign key
|
|
281
|
+
await execSqliteSql(`
|
|
282
|
+
CREATE TABLE orders (
|
|
283
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
284
|
+
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
285
|
+
total REAL NOT NULL,
|
|
286
|
+
status TEXT DEFAULT 'pending',
|
|
287
|
+
items TEXT NOT NULL DEFAULT '[]',
|
|
288
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
289
|
+
)
|
|
290
|
+
`);
|
|
291
|
+
await execSqliteSql('CREATE INDEX orders_user_id_idx ON orders(user_id)');
|
|
292
|
+
await execSqliteSql('CREATE INDEX orders_status_idx ON orders(status)');
|
|
293
|
+
// Order items junction table
|
|
294
|
+
await execSqliteSql(`
|
|
295
|
+
CREATE TABLE order_items (
|
|
296
|
+
order_id INTEGER NOT NULL REFERENCES orders(id),
|
|
297
|
+
product_id INTEGER NOT NULL REFERENCES products(id),
|
|
298
|
+
quantity INTEGER NOT NULL DEFAULT 1,
|
|
299
|
+
price_at_time REAL NOT NULL,
|
|
300
|
+
PRIMARY KEY (order_id, product_id)
|
|
301
|
+
)
|
|
302
|
+
`);
|
|
303
|
+
// View for testing view detection
|
|
304
|
+
await execSqliteSql(`
|
|
305
|
+
CREATE VIEW user_order_summary AS
|
|
306
|
+
SELECT
|
|
307
|
+
u.id as user_id,
|
|
308
|
+
u.email,
|
|
309
|
+
COUNT(o.id) as order_count,
|
|
310
|
+
COALESCE(SUM(o.total), 0) as total_spent
|
|
311
|
+
FROM users u
|
|
312
|
+
LEFT JOIN orders o ON u.id = o.user_id
|
|
313
|
+
GROUP BY u.id, u.email
|
|
314
|
+
`);
|
|
315
|
+
// Wide table for truncation testing
|
|
316
|
+
const wideCols = Array.from({ length: 55 }, (_, i) => `col_${String(i + 1).padStart(2, '0')} TEXT`).join(', ');
|
|
317
|
+
await execSqliteSql(`
|
|
318
|
+
CREATE TABLE wide_table (
|
|
319
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
320
|
+
${wideCols}
|
|
321
|
+
)
|
|
322
|
+
`);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Seed the SQLite test database with sample data
|
|
326
|
+
* Uses full cleanup + re-insert to ensure consistent state
|
|
327
|
+
*/
|
|
328
|
+
export async function seedSqliteTestData() {
|
|
329
|
+
// Run cleanup in a single connection with FKs disabled
|
|
330
|
+
// getSqliteTestDb() auto-enables FKs, so we disable them first
|
|
331
|
+
const db = getSqliteTestDb();
|
|
332
|
+
try {
|
|
333
|
+
db.exec(`
|
|
334
|
+
PRAGMA foreign_keys = OFF;
|
|
335
|
+
DELETE FROM order_items;
|
|
336
|
+
DELETE FROM orders;
|
|
337
|
+
DELETE FROM products;
|
|
338
|
+
DELETE FROM users;
|
|
339
|
+
PRAGMA foreign_keys = ON;
|
|
340
|
+
`);
|
|
341
|
+
}
|
|
342
|
+
finally {
|
|
343
|
+
db.close();
|
|
344
|
+
}
|
|
345
|
+
// Seed users
|
|
346
|
+
await execSqliteSql(`
|
|
347
|
+
INSERT INTO users (id, email, name, age, balance, metadata, is_active) VALUES
|
|
348
|
+
('11111111-1111-1111-1111-111111111111', 'alice@example.com', 'Alice Smith', 30, 1000.50, '{"role": "admin"}', 1),
|
|
349
|
+
('22222222-2222-2222-2222-222222222222', 'bob@example.com', 'Bob Jones', 25, 500.00, '{"role": "user"}', 1),
|
|
350
|
+
('33333333-3333-3333-3333-333333333333', 'charlie@example.com', 'Charlie Brown', 35, 0.00, null, 0)
|
|
351
|
+
`);
|
|
352
|
+
// Seed products
|
|
353
|
+
await execSqliteSql(`
|
|
354
|
+
INSERT INTO products (id, name, price, stock, category) VALUES
|
|
355
|
+
(1, 'Widget', 9.99, 100, 'gadgets'),
|
|
356
|
+
(2, 'Gadget', 19.99, 50, 'gadgets'),
|
|
357
|
+
(3, 'Thingamajig', 29.99, 25, 'misc')
|
|
358
|
+
`);
|
|
359
|
+
// Seed orders
|
|
360
|
+
await execSqliteSql(`
|
|
361
|
+
INSERT INTO orders (id, user_id, total, status, items) VALUES
|
|
362
|
+
(1, '11111111-1111-1111-1111-111111111111', 29.98, 'completed', '[{"product_id": 1, "qty": 2}]'),
|
|
363
|
+
(2, '11111111-1111-1111-1111-111111111111', 19.99, 'pending', '[{"product_id": 2, "qty": 1}]'),
|
|
364
|
+
(3, '22222222-2222-2222-2222-222222222222', 9.99, 'completed', '[{"product_id": 1, "qty": 1}]')
|
|
365
|
+
`);
|
|
366
|
+
// Seed order items
|
|
367
|
+
await execSqliteSql(`
|
|
368
|
+
INSERT INTO order_items (order_id, product_id, quantity, price_at_time) VALUES
|
|
369
|
+
(1, 1, 2, 9.99),
|
|
370
|
+
(2, 2, 1, 19.99),
|
|
371
|
+
(3, 1, 1, 9.99)
|
|
372
|
+
`);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Clean up SQLite test data between tests
|
|
376
|
+
*/
|
|
377
|
+
export async function cleanupSqliteTestData() {
|
|
378
|
+
await execSqliteSql('DELETE FROM order_items');
|
|
379
|
+
await execSqliteSql('DELETE FROM orders');
|
|
380
|
+
await execSqliteSql('DELETE FROM products');
|
|
381
|
+
await execSqliteSql('DELETE FROM users');
|
|
382
|
+
}
|
|
383
|
+
// ============================================================================
|
|
384
|
+
// MySQL Test Configuration and Helpers
|
|
385
|
+
// ============================================================================
|
|
386
|
+
/**
|
|
387
|
+
* Create a MySQL test configuration with optional overrides
|
|
388
|
+
*/
|
|
389
|
+
export function createMySqlTestConfig(overrides) {
|
|
390
|
+
const mysqlUrl = getMySqlUrl();
|
|
391
|
+
const base = {
|
|
392
|
+
databases: {
|
|
393
|
+
mysqldb: {
|
|
394
|
+
url: mysqlUrl,
|
|
395
|
+
readonly: false,
|
|
396
|
+
},
|
|
397
|
+
mysqldb_readonly: {
|
|
398
|
+
url: mysqlUrl,
|
|
399
|
+
readonly: true,
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
defaults: {
|
|
403
|
+
maxRows: 100,
|
|
404
|
+
maxCellLength: 500,
|
|
405
|
+
maxTotalSize: 65536,
|
|
406
|
+
maxColumns: 50,
|
|
407
|
+
maxTables: 200,
|
|
408
|
+
maxIndexes: 20,
|
|
409
|
+
timeout: 30000,
|
|
410
|
+
},
|
|
411
|
+
};
|
|
412
|
+
if (!overrides) {
|
|
413
|
+
return base;
|
|
414
|
+
}
|
|
415
|
+
// Handle databases override - if explicitly provided, use it directly
|
|
416
|
+
const databases = 'databases' in overrides
|
|
417
|
+
? overrides.databases ?? base.databases
|
|
418
|
+
: base.databases;
|
|
419
|
+
// Handle defaults override - merge with base
|
|
420
|
+
const defaults = 'defaults' in overrides
|
|
421
|
+
? { ...base.defaults, ...overrides.defaults }
|
|
422
|
+
: base.defaults;
|
|
423
|
+
return { databases, defaults };
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Initialize the MySQL test database schema
|
|
427
|
+
*/
|
|
428
|
+
export async function initializeMySqlSchema() {
|
|
429
|
+
// Drop existing tables in reverse FK order
|
|
430
|
+
// MySQL requires disabling foreign key checks to drop tables with FK dependencies
|
|
431
|
+
await execMySql('SET FOREIGN_KEY_CHECKS = 0');
|
|
432
|
+
await execMySql('DROP TABLE IF EXISTS order_items');
|
|
433
|
+
await execMySql('DROP TABLE IF EXISTS orders');
|
|
434
|
+
await execMySql('DROP TABLE IF EXISTS products');
|
|
435
|
+
await execMySql('DROP TABLE IF EXISTS users');
|
|
436
|
+
await execMySql('DROP TABLE IF EXISTS wide_table');
|
|
437
|
+
await execMySql('DROP VIEW IF EXISTS user_order_summary');
|
|
438
|
+
await execMySql('SET FOREIGN_KEY_CHECKS = 1');
|
|
439
|
+
// Users table with MySQL-compatible types
|
|
440
|
+
await execMySql(`
|
|
441
|
+
CREATE TABLE users (
|
|
442
|
+
id CHAR(36) PRIMARY KEY,
|
|
443
|
+
email VARCHAR(255) NOT NULL UNIQUE,
|
|
444
|
+
name VARCHAR(100),
|
|
445
|
+
age INT,
|
|
446
|
+
balance DECIMAL(10, 2) DEFAULT 0.00,
|
|
447
|
+
metadata JSON,
|
|
448
|
+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
449
|
+
updated_at TIMESTAMP NULL,
|
|
450
|
+
is_active BOOLEAN DEFAULT TRUE
|
|
451
|
+
)
|
|
452
|
+
`);
|
|
453
|
+
// Create indexes for testing
|
|
454
|
+
await execMySql('CREATE INDEX users_created_at_idx ON users(created_at)');
|
|
455
|
+
await execMySql('CREATE INDEX users_name_email_idx ON users(name, email)');
|
|
456
|
+
// Products table
|
|
457
|
+
await execMySql(`
|
|
458
|
+
CREATE TABLE products (
|
|
459
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
460
|
+
name VARCHAR(255) NOT NULL,
|
|
461
|
+
price DECIMAL(10, 2) NOT NULL,
|
|
462
|
+
stock INT DEFAULT 0,
|
|
463
|
+
category VARCHAR(100)
|
|
464
|
+
)
|
|
465
|
+
`);
|
|
466
|
+
// Orders table with foreign key
|
|
467
|
+
await execMySql(`
|
|
468
|
+
CREATE TABLE orders (
|
|
469
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
470
|
+
user_id CHAR(36) NOT NULL,
|
|
471
|
+
total DECIMAL(10, 2) NOT NULL,
|
|
472
|
+
status VARCHAR(50) DEFAULT 'pending',
|
|
473
|
+
items JSON NOT NULL,
|
|
474
|
+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
475
|
+
CONSTRAINT fk_orders_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
476
|
+
)
|
|
477
|
+
`);
|
|
478
|
+
await execMySql('CREATE INDEX orders_user_id_idx ON orders(user_id)');
|
|
479
|
+
await execMySql('CREATE INDEX orders_status_idx ON orders(status)');
|
|
480
|
+
// Order items junction table
|
|
481
|
+
await execMySql(`
|
|
482
|
+
CREATE TABLE order_items (
|
|
483
|
+
order_id INT NOT NULL,
|
|
484
|
+
product_id INT NOT NULL,
|
|
485
|
+
quantity INT NOT NULL DEFAULT 1,
|
|
486
|
+
price_at_time DECIMAL(10, 2) NOT NULL,
|
|
487
|
+
PRIMARY KEY (order_id, product_id),
|
|
488
|
+
CONSTRAINT fk_order_items_order FOREIGN KEY (order_id) REFERENCES orders(id),
|
|
489
|
+
CONSTRAINT fk_order_items_product FOREIGN KEY (product_id) REFERENCES products(id)
|
|
490
|
+
)
|
|
491
|
+
`);
|
|
492
|
+
// View for testing view detection
|
|
493
|
+
await execMySql(`
|
|
494
|
+
CREATE VIEW user_order_summary AS
|
|
495
|
+
SELECT
|
|
496
|
+
u.id as user_id,
|
|
497
|
+
u.email,
|
|
498
|
+
COUNT(o.id) as order_count,
|
|
499
|
+
COALESCE(SUM(o.total), 0) as total_spent
|
|
500
|
+
FROM users u
|
|
501
|
+
LEFT JOIN orders o ON u.id = o.user_id
|
|
502
|
+
GROUP BY u.id, u.email
|
|
503
|
+
`);
|
|
504
|
+
// Wide table for truncation testing
|
|
505
|
+
const wideCols = Array.from({ length: 55 }, (_, i) => `col_${String(i + 1).padStart(2, '0')} TEXT`).join(', ');
|
|
506
|
+
await execMySql(`
|
|
507
|
+
CREATE TABLE wide_table (
|
|
508
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
509
|
+
${wideCols}
|
|
510
|
+
)
|
|
511
|
+
`);
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Seed the MySQL test database with sample data
|
|
515
|
+
* Uses TRUNCATE for fast cleanup then re-insert
|
|
516
|
+
*/
|
|
517
|
+
export async function seedMySqlTestData() {
|
|
518
|
+
// Use execMySqlBatch for atomic cleanup with FK checks disabled
|
|
519
|
+
await execMySqlBatch([
|
|
520
|
+
'SET FOREIGN_KEY_CHECKS = 0',
|
|
521
|
+
'TRUNCATE TABLE order_items',
|
|
522
|
+
'TRUNCATE TABLE orders',
|
|
523
|
+
'TRUNCATE TABLE products',
|
|
524
|
+
'TRUNCATE TABLE users',
|
|
525
|
+
'SET FOREIGN_KEY_CHECKS = 1',
|
|
526
|
+
]);
|
|
527
|
+
// Seed data in correct order (respecting FK constraints)
|
|
528
|
+
await execMySql(`
|
|
529
|
+
INSERT INTO users (id, email, name, age, balance, metadata, is_active) VALUES
|
|
530
|
+
('11111111-1111-1111-1111-111111111111', 'alice@example.com', 'Alice Smith', 30, 1000.50, '{"role": "admin"}', TRUE),
|
|
531
|
+
('22222222-2222-2222-2222-222222222222', 'bob@example.com', 'Bob Jones', 25, 500.00, '{"role": "user"}', TRUE),
|
|
532
|
+
('33333333-3333-3333-3333-333333333333', 'charlie@example.com', 'Charlie Brown', 35, 0.00, NULL, FALSE)
|
|
533
|
+
`);
|
|
534
|
+
await execMySql(`
|
|
535
|
+
INSERT INTO products (id, name, price, stock, category) VALUES
|
|
536
|
+
(1, 'Widget', 9.99, 100, 'gadgets'),
|
|
537
|
+
(2, 'Gadget', 19.99, 50, 'gadgets'),
|
|
538
|
+
(3, 'Thingamajig', 29.99, 25, 'misc')
|
|
539
|
+
`);
|
|
540
|
+
await execMySql(`
|
|
541
|
+
INSERT INTO orders (id, user_id, total, status, items) VALUES
|
|
542
|
+
(1, '11111111-1111-1111-1111-111111111111', 29.98, 'completed', '[{"product_id": 1, "qty": 2}]'),
|
|
543
|
+
(2, '11111111-1111-1111-1111-111111111111', 19.99, 'pending', '[{"product_id": 2, "qty": 1}]'),
|
|
544
|
+
(3, '22222222-2222-2222-2222-222222222222', 9.99, 'completed', '[{"product_id": 1, "qty": 1}]')
|
|
545
|
+
`);
|
|
546
|
+
await execMySql(`
|
|
547
|
+
INSERT INTO order_items (order_id, product_id, quantity, price_at_time) VALUES
|
|
548
|
+
(1, 1, 2, 9.99),
|
|
549
|
+
(2, 2, 1, 19.99),
|
|
550
|
+
(3, 1, 1, 9.99)
|
|
551
|
+
`);
|
|
552
|
+
// Update table statistics for row estimates
|
|
553
|
+
await execMySql('ANALYZE TABLE users, products, orders, order_items');
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Clean up MySQL test data between tests
|
|
557
|
+
*/
|
|
558
|
+
export async function cleanupMySqlTestData() {
|
|
559
|
+
await execMySqlBatch([
|
|
560
|
+
'SET FOREIGN_KEY_CHECKS = 0',
|
|
561
|
+
'TRUNCATE TABLE order_items',
|
|
562
|
+
'TRUNCATE TABLE orders',
|
|
563
|
+
'TRUNCATE TABLE products',
|
|
564
|
+
'TRUNCATE TABLE users',
|
|
565
|
+
'SET FOREIGN_KEY_CHECKS = 1',
|
|
566
|
+
]);
|
|
567
|
+
}
|
|
568
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/__integration__/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
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
|
+
declare const TEST_SQLITE_DB_PATH = "./test-data/test.db";
|
|
10
|
+
/**
|
|
11
|
+
* Start the test containers (PostgreSQL and MySQL) using Testcontainers
|
|
12
|
+
*/
|
|
13
|
+
export declare function startContainers(): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Start the test PostgreSQL container (backward compatibility)
|
|
16
|
+
*/
|
|
17
|
+
export declare function startPostgres(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Stop the test containers
|
|
20
|
+
*/
|
|
21
|
+
export declare function stopContainers(): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Stop the test PostgreSQL container (backward compatibility)
|
|
24
|
+
*/
|
|
25
|
+
export declare function stopPostgres(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Get the PostgreSQL connection URL (set after containers start)
|
|
28
|
+
*/
|
|
29
|
+
export declare function getPostgresUrl(): string;
|
|
30
|
+
/**
|
|
31
|
+
* Get the MySQL connection URL (set after containers start)
|
|
32
|
+
*/
|
|
33
|
+
export declare function getMySqlUrl(): string;
|
|
34
|
+
/**
|
|
35
|
+
* Get a direct PostgreSQL database client for test verification
|
|
36
|
+
*/
|
|
37
|
+
export declare function getTestClient(): Promise<pg.Client>;
|
|
38
|
+
/**
|
|
39
|
+
* Execute SQL directly for test setup/verification (PostgreSQL)
|
|
40
|
+
*/
|
|
41
|
+
export declare function execSql(sql: string, params?: unknown[]): Promise<pg.QueryResult>;
|
|
42
|
+
/**
|
|
43
|
+
* Get a direct MySQL database connection for test verification
|
|
44
|
+
*/
|
|
45
|
+
export declare function getMySqlTestConnection(): Promise<mysql.Connection>;
|
|
46
|
+
/**
|
|
47
|
+
* Execute SQL directly for test setup/verification (MySQL)
|
|
48
|
+
*/
|
|
49
|
+
export declare function execMySql(sql: string, params?: unknown[]): Promise<mysql.QueryResult>;
|
|
50
|
+
/**
|
|
51
|
+
* Execute multiple SQL statements in a single connection (MySQL)
|
|
52
|
+
* Useful when session state needs to persist (e.g., FOREIGN_KEY_CHECKS)
|
|
53
|
+
*/
|
|
54
|
+
export declare function execMySqlBatch(statements: string[]): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Create the SQLite test database directory and file
|
|
57
|
+
*/
|
|
58
|
+
export declare function createSqliteTestDb(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Delete the SQLite test database file
|
|
61
|
+
*/
|
|
62
|
+
export declare function deleteSqliteTestDb(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Get a SQLite database connection for test setup/verification
|
|
65
|
+
*/
|
|
66
|
+
export declare function getSqliteTestDb(): Database.Database;
|
|
67
|
+
/**
|
|
68
|
+
* Execute SQL directly for test setup/verification (SQLite)
|
|
69
|
+
*/
|
|
70
|
+
export declare function execSqliteSql(sql: string): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Execute a query and return results (SQLite)
|
|
73
|
+
*/
|
|
74
|
+
export declare function querySqliteSql(sql: string): Promise<unknown[]>;
|
|
75
|
+
/**
|
|
76
|
+
* Export SQLite path for use in helpers
|
|
77
|
+
*/
|
|
78
|
+
export { TEST_SQLITE_DB_PATH };
|
|
79
|
+
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","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;AAMtC,QAAA,MAAM,mBAAmB,wBAAwB,CAAC;AAUlD;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAgCrD;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAEnD;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAcpD;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAOvC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAOpC;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,CAIxD;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,CAOtF;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAExE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAQ3F;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CASxE;AAOD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAiBzC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAgBzC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,QAAQ,CAAC,QAAQ,CAKnD;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO9D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAOpE;AAED;;GAEG;AACH,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
|