@tejasanik/postgres-mcp-server 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +186 -10
- package/dist/db-manager/index.d.ts +7 -0
- package/dist/db-manager/index.d.ts.map +1 -0
- package/dist/db-manager/index.js +7 -0
- package/dist/db-manager/index.js.map +1 -0
- package/dist/db-manager/validation.d.ts +35 -0
- package/dist/db-manager/validation.d.ts.map +1 -0
- package/dist/db-manager/validation.js +54 -0
- package/dist/db-manager/validation.js.map +1 -0
- package/dist/db-manager.d.ts +175 -5
- package/dist/db-manager.d.ts.map +1 -1
- package/dist/db-manager.js +589 -26
- package/dist/db-manager.js.map +1 -1
- package/dist/index.js +141 -11
- package/dist/index.js.map +1 -1
- package/dist/tools/analysis-tools.d.ts.map +1 -1
- package/dist/tools/analysis-tools.js +53 -49
- package/dist/tools/analysis-tools.js.map +1 -1
- package/dist/tools/schema-tools.d.ts +40 -1
- package/dist/tools/schema-tools.d.ts.map +1 -1
- package/dist/tools/schema-tools.js +174 -92
- package/dist/tools/schema-tools.js.map +1 -1
- package/dist/tools/server-tools.d.ts +1 -0
- package/dist/tools/server-tools.d.ts.map +1 -1
- package/dist/tools/server-tools.js +10 -6
- package/dist/tools/server-tools.js.map +1 -1
- package/dist/tools/sql/utils/connection-utils.d.ts +79 -0
- package/dist/tools/sql/utils/connection-utils.d.ts.map +1 -0
- package/dist/tools/sql/utils/connection-utils.js +129 -0
- package/dist/tools/sql/utils/connection-utils.js.map +1 -0
- package/dist/tools/sql/utils/constants.d.ts +55 -0
- package/dist/tools/sql/utils/constants.d.ts.map +1 -0
- package/dist/tools/sql/utils/constants.js +55 -0
- package/dist/tools/sql/utils/constants.js.map +1 -0
- package/dist/tools/sql/utils/dry-run-utils.d.ts +31 -0
- package/dist/tools/sql/utils/dry-run-utils.d.ts.map +1 -0
- package/dist/tools/sql/utils/dry-run-utils.js +173 -0
- package/dist/tools/sql/utils/dry-run-utils.js.map +1 -0
- package/dist/tools/sql/utils/file-handler.d.ts +57 -0
- package/dist/tools/sql/utils/file-handler.d.ts.map +1 -0
- package/dist/tools/sql/utils/file-handler.js +150 -0
- package/dist/tools/sql/utils/file-handler.js.map +1 -0
- package/dist/tools/sql/utils/index.d.ts +12 -0
- package/dist/tools/sql/utils/index.d.ts.map +1 -0
- package/dist/tools/sql/utils/index.js +12 -0
- package/dist/tools/sql/utils/index.js.map +1 -0
- package/dist/tools/sql/utils/result-formatter.d.ts +94 -0
- package/dist/tools/sql/utils/result-formatter.d.ts.map +1 -0
- package/dist/tools/sql/utils/result-formatter.js +154 -0
- package/dist/tools/sql/utils/result-formatter.js.map +1 -0
- package/dist/tools/sql/utils/sql-parser.d.ts +125 -0
- package/dist/tools/sql/utils/sql-parser.d.ts.map +1 -0
- package/dist/tools/sql/utils/sql-parser.js +468 -0
- package/dist/tools/sql/utils/sql-parser.js.map +1 -0
- package/dist/tools/sql-tools.d.ts +21 -0
- package/dist/tools/sql-tools.d.ts.map +1 -1
- package/dist/tools/sql-tools.js +383 -532
- package/dist/tools/sql-tools.js.map +1 -1
- package/dist/types.d.ts +38 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/retry.d.ts +1 -1
- package/dist/utils/retry.d.ts.map +1 -1
- package/dist/utils/retry.js.map +1 -1
- package/dist/utils/validation.d.ts +45 -9
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +335 -72
- package/dist/utils/validation.js.map +1 -1
- package/package.json +9 -2
- package/dist/__tests__/analysis-tools.test.d.ts +0 -2
- package/dist/__tests__/analysis-tools.test.d.ts.map +0 -1
- package/dist/__tests__/analysis-tools.test.js +0 -294
- package/dist/__tests__/analysis-tools.test.js.map +0 -1
- package/dist/__tests__/db-manager.test.d.ts +0 -2
- package/dist/__tests__/db-manager.test.d.ts.map +0 -1
- package/dist/__tests__/db-manager.test.js +0 -410
- package/dist/__tests__/db-manager.test.js.map +0 -1
- package/dist/__tests__/mcp-server.test.d.ts +0 -13
- package/dist/__tests__/mcp-server.test.d.ts.map +0 -1
- package/dist/__tests__/mcp-server.test.js +0 -146
- package/dist/__tests__/mcp-server.test.js.map +0 -1
- package/dist/__tests__/schema-tools.test.d.ts +0 -2
- package/dist/__tests__/schema-tools.test.d.ts.map +0 -1
- package/dist/__tests__/schema-tools.test.js +0 -171
- package/dist/__tests__/schema-tools.test.js.map +0 -1
- package/dist/__tests__/server-tools.test.d.ts +0 -2
- package/dist/__tests__/server-tools.test.d.ts.map +0 -1
- package/dist/__tests__/server-tools.test.js +0 -113
- package/dist/__tests__/server-tools.test.js.map +0 -1
- package/dist/__tests__/sql-tools.test.d.ts +0 -2
- package/dist/__tests__/sql-tools.test.d.ts.map +0 -1
- package/dist/__tests__/sql-tools.test.js +0 -1912
- package/dist/__tests__/sql-tools.test.js.map +0 -1
- package/dist/__tests__/validation.test.d.ts +0 -2
- package/dist/__tests__/validation.test.d.ts.map +0 -1
- package/dist/__tests__/validation.test.js +0 -203
- package/dist/__tests__/validation.test.js.map +0 -1
|
@@ -1,410 +0,0 @@
|
|
|
1
|
-
import { jest, describe, it, expect, beforeEach, afterEach } from '@jest/globals';
|
|
2
|
-
import { DatabaseManager, getDbManager, resetDbManager } from '../db-manager.js';
|
|
3
|
-
// Helper to clear all PG_* environment variables
|
|
4
|
-
function clearPgEnvVars() {
|
|
5
|
-
for (const key of Object.keys(process.env)) {
|
|
6
|
-
if (key.startsWith('PG_')) {
|
|
7
|
-
delete process.env[key];
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
describe('DatabaseManager', () => {
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
// Reset the singleton and environment
|
|
14
|
-
resetDbManager();
|
|
15
|
-
delete process.env.POSTGRES_SERVERS;
|
|
16
|
-
delete process.env.POSTGRES_ACCESS_MODE;
|
|
17
|
-
clearPgEnvVars();
|
|
18
|
-
});
|
|
19
|
-
afterEach(() => {
|
|
20
|
-
resetDbManager();
|
|
21
|
-
clearPgEnvVars();
|
|
22
|
-
});
|
|
23
|
-
describe('constructor and configuration', () => {
|
|
24
|
-
it('should handle missing POSTGRES_SERVERS env var', () => {
|
|
25
|
-
const manager = new DatabaseManager();
|
|
26
|
-
expect(manager.getServerNames()).toEqual([]);
|
|
27
|
-
expect(manager.getServersConfig()).toEqual({});
|
|
28
|
-
});
|
|
29
|
-
it('should parse valid POSTGRES_SERVERS config', () => {
|
|
30
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
31
|
-
dev: { host: 'localhost', port: '5432', username: 'user', password: 'pass' },
|
|
32
|
-
prod: { host: 'prod.example.com', port: '5433', username: 'admin', password: 'secret' }
|
|
33
|
-
});
|
|
34
|
-
const manager = new DatabaseManager();
|
|
35
|
-
expect(manager.getServerNames()).toEqual(['dev', 'prod']);
|
|
36
|
-
const devConfig = manager.getServerConfig('dev');
|
|
37
|
-
expect(devConfig).toEqual({ host: 'localhost', port: '5432', username: 'user', password: 'pass' });
|
|
38
|
-
});
|
|
39
|
-
it('should handle invalid JSON in POSTGRES_SERVERS', () => {
|
|
40
|
-
process.env.POSTGRES_SERVERS = 'invalid json';
|
|
41
|
-
const manager = new DatabaseManager();
|
|
42
|
-
expect(manager.getServerNames()).toEqual([]);
|
|
43
|
-
});
|
|
44
|
-
it('should validate server config structure', () => {
|
|
45
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
46
|
-
invalid: { port: '5432' } // missing host
|
|
47
|
-
});
|
|
48
|
-
const manager = new DatabaseManager();
|
|
49
|
-
expect(manager.getServerNames()).toEqual([]);
|
|
50
|
-
});
|
|
51
|
-
it('should return null for non-existent server', () => {
|
|
52
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
53
|
-
dev: { host: 'localhost', port: '5432', username: 'user', password: 'pass' }
|
|
54
|
-
});
|
|
55
|
-
const manager = new DatabaseManager();
|
|
56
|
-
expect(manager.getServerConfig('nonexistent')).toBeNull();
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
describe('PG_* environment variable configuration', () => {
|
|
60
|
-
it('should parse servers from PG_* env vars', () => {
|
|
61
|
-
process.env.PG_NAME_1 = 'dev';
|
|
62
|
-
process.env.PG_HOST_1 = 'localhost';
|
|
63
|
-
process.env.PG_PORT_1 = '5432';
|
|
64
|
-
process.env.PG_USERNAME_1 = 'user';
|
|
65
|
-
process.env.PG_PASSWORD_1 = 'pass';
|
|
66
|
-
process.env.PG_DATABASE_1 = 'mydb';
|
|
67
|
-
process.env.PG_SCHEMA_1 = 'public';
|
|
68
|
-
process.env.PG_SSL_1 = 'true';
|
|
69
|
-
process.env.PG_DEFAULT_1 = 'true';
|
|
70
|
-
const manager = new DatabaseManager();
|
|
71
|
-
expect(manager.getServerNames()).toContain('dev');
|
|
72
|
-
const config = manager.getServerConfig('dev');
|
|
73
|
-
expect(config).toEqual({
|
|
74
|
-
host: 'localhost',
|
|
75
|
-
port: '5432',
|
|
76
|
-
username: 'user',
|
|
77
|
-
password: 'pass',
|
|
78
|
-
defaultDatabase: 'mydb',
|
|
79
|
-
defaultSchema: 'public',
|
|
80
|
-
ssl: true,
|
|
81
|
-
isDefault: true
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
it('should parse multiple servers from PG_* env vars', () => {
|
|
85
|
-
process.env.PG_NAME_1 = 'dev';
|
|
86
|
-
process.env.PG_HOST_1 = 'localhost';
|
|
87
|
-
process.env.PG_USERNAME_1 = 'dev_user';
|
|
88
|
-
process.env.PG_PASSWORD_1 = 'dev_pass';
|
|
89
|
-
process.env.PG_NAME_2 = 'prod';
|
|
90
|
-
process.env.PG_HOST_2 = 'prod.example.com';
|
|
91
|
-
process.env.PG_USERNAME_2 = 'prod_user';
|
|
92
|
-
process.env.PG_PASSWORD_2 = 'prod_pass';
|
|
93
|
-
process.env.PG_SSL_2 = 'require';
|
|
94
|
-
const manager = new DatabaseManager();
|
|
95
|
-
expect(manager.getServerNames()).toContain('dev');
|
|
96
|
-
expect(manager.getServerNames()).toContain('prod');
|
|
97
|
-
expect(manager.getServerConfig('dev')?.host).toBe('localhost');
|
|
98
|
-
expect(manager.getServerConfig('prod')?.host).toBe('prod.example.com');
|
|
99
|
-
expect(manager.getServerConfig('prod')?.ssl).toBe('require');
|
|
100
|
-
});
|
|
101
|
-
it('should use default port when not specified', () => {
|
|
102
|
-
process.env.PG_NAME_1 = 'dev';
|
|
103
|
-
process.env.PG_HOST_1 = 'localhost';
|
|
104
|
-
process.env.PG_USERNAME_1 = 'user';
|
|
105
|
-
const manager = new DatabaseManager();
|
|
106
|
-
expect(manager.getServerConfig('dev')?.port).toBe('5432');
|
|
107
|
-
});
|
|
108
|
-
it('should skip servers missing required fields', () => {
|
|
109
|
-
// Missing PG_HOST_1
|
|
110
|
-
process.env.PG_NAME_1 = 'incomplete';
|
|
111
|
-
process.env.PG_USERNAME_1 = 'user';
|
|
112
|
-
const manager = new DatabaseManager();
|
|
113
|
-
expect(manager.getServerNames()).not.toContain('incomplete');
|
|
114
|
-
});
|
|
115
|
-
it('should skip servers missing username', () => {
|
|
116
|
-
process.env.PG_NAME_1 = 'nouser';
|
|
117
|
-
process.env.PG_HOST_1 = 'localhost';
|
|
118
|
-
// Missing PG_USERNAME_1
|
|
119
|
-
const manager = new DatabaseManager();
|
|
120
|
-
expect(manager.getServerNames()).not.toContain('nouser');
|
|
121
|
-
});
|
|
122
|
-
it('should parse SSL options correctly', () => {
|
|
123
|
-
process.env.PG_NAME_1 = 'ssl_true';
|
|
124
|
-
process.env.PG_HOST_1 = 'host1';
|
|
125
|
-
process.env.PG_USERNAME_1 = 'user';
|
|
126
|
-
process.env.PG_SSL_1 = 'true';
|
|
127
|
-
process.env.PG_NAME_2 = 'ssl_false';
|
|
128
|
-
process.env.PG_HOST_2 = 'host2';
|
|
129
|
-
process.env.PG_USERNAME_2 = 'user';
|
|
130
|
-
process.env.PG_SSL_2 = 'false';
|
|
131
|
-
process.env.PG_NAME_3 = 'ssl_require';
|
|
132
|
-
process.env.PG_HOST_3 = 'host3';
|
|
133
|
-
process.env.PG_USERNAME_3 = 'user';
|
|
134
|
-
process.env.PG_SSL_3 = 'require';
|
|
135
|
-
const manager = new DatabaseManager();
|
|
136
|
-
expect(manager.getServerConfig('ssl_true')?.ssl).toBe(true);
|
|
137
|
-
expect(manager.getServerConfig('ssl_false')?.ssl).toBe(false);
|
|
138
|
-
expect(manager.getServerConfig('ssl_require')?.ssl).toBe('require');
|
|
139
|
-
});
|
|
140
|
-
it('should allow named suffixes like _DEV, _PROD', () => {
|
|
141
|
-
process.env.PG_NAME_DEV = 'development';
|
|
142
|
-
process.env.PG_HOST_DEV = 'dev.example.com';
|
|
143
|
-
process.env.PG_USERNAME_DEV = 'dev_user';
|
|
144
|
-
process.env.PG_NAME_PROD = 'production';
|
|
145
|
-
process.env.PG_HOST_PROD = 'prod.example.com';
|
|
146
|
-
process.env.PG_USERNAME_PROD = 'prod_user';
|
|
147
|
-
const manager = new DatabaseManager();
|
|
148
|
-
expect(manager.getServerNames()).toContain('development');
|
|
149
|
-
expect(manager.getServerNames()).toContain('production');
|
|
150
|
-
});
|
|
151
|
-
it('should merge PG_* vars with POSTGRES_SERVERS (PG_* takes precedence)', () => {
|
|
152
|
-
// JSON config
|
|
153
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
154
|
-
dev: { host: 'json-host', port: '5432', username: 'json-user', password: 'json-pass' },
|
|
155
|
-
staging: { host: 'staging-host', port: '5432', username: 'staging-user', password: 'staging-pass' }
|
|
156
|
-
});
|
|
157
|
-
// PG_* config (should override 'dev')
|
|
158
|
-
process.env.PG_NAME_1 = 'dev';
|
|
159
|
-
process.env.PG_HOST_1 = 'env-host';
|
|
160
|
-
process.env.PG_USERNAME_1 = 'env-user';
|
|
161
|
-
process.env.PG_PASSWORD_1 = 'env-pass';
|
|
162
|
-
const manager = new DatabaseManager();
|
|
163
|
-
// dev should come from PG_* (takes precedence)
|
|
164
|
-
expect(manager.getServerConfig('dev')?.host).toBe('env-host');
|
|
165
|
-
expect(manager.getServerConfig('dev')?.username).toBe('env-user');
|
|
166
|
-
// staging should still come from JSON
|
|
167
|
-
expect(manager.getServerConfig('staging')?.host).toBe('staging-host');
|
|
168
|
-
});
|
|
169
|
-
it('should parse context from PG_CONTEXT_* env vars', () => {
|
|
170
|
-
process.env.PG_NAME_1 = 'dev';
|
|
171
|
-
process.env.PG_HOST_1 = 'localhost';
|
|
172
|
-
process.env.PG_USERNAME_1 = 'user';
|
|
173
|
-
process.env.PG_CONTEXT_1 = 'Development server. Safe for any queries.';
|
|
174
|
-
process.env.PG_NAME_PROD = 'production';
|
|
175
|
-
process.env.PG_HOST_PROD = 'prod.example.com';
|
|
176
|
-
process.env.PG_USERNAME_PROD = 'prod_user';
|
|
177
|
-
process.env.PG_CONTEXT_PROD = 'PRODUCTION - Read-only queries only. Always use LIMIT.';
|
|
178
|
-
const manager = new DatabaseManager();
|
|
179
|
-
expect(manager.getServerConfig('dev')?.context).toBe('Development server. Safe for any queries.');
|
|
180
|
-
expect(manager.getServerConfig('production')?.context).toBe('PRODUCTION - Read-only queries only. Always use LIMIT.');
|
|
181
|
-
});
|
|
182
|
-
it('should parse context from POSTGRES_SERVERS JSON', () => {
|
|
183
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
184
|
-
dev: {
|
|
185
|
-
host: 'localhost',
|
|
186
|
-
port: '5432',
|
|
187
|
-
username: 'user',
|
|
188
|
-
password: 'pass',
|
|
189
|
-
context: 'Test environment with sample data.'
|
|
190
|
-
},
|
|
191
|
-
prod: {
|
|
192
|
-
host: 'prod.example.com',
|
|
193
|
-
port: '5432',
|
|
194
|
-
username: 'prod_user',
|
|
195
|
-
password: 'prod_pass',
|
|
196
|
-
context: 'Production - be careful!'
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
const manager = new DatabaseManager();
|
|
200
|
-
expect(manager.getServerConfig('dev')?.context).toBe('Test environment with sample data.');
|
|
201
|
-
expect(manager.getServerConfig('prod')?.context).toBe('Production - be careful!');
|
|
202
|
-
});
|
|
203
|
-
it('should include context in getConnectionInfo', () => {
|
|
204
|
-
process.env.PG_NAME_1 = 'dev';
|
|
205
|
-
process.env.PG_HOST_1 = 'localhost';
|
|
206
|
-
process.env.PG_USERNAME_1 = 'user';
|
|
207
|
-
process.env.PG_CONTEXT_1 = 'Development context here';
|
|
208
|
-
const manager = new DatabaseManager();
|
|
209
|
-
// Note: Not connected yet, so context should be undefined
|
|
210
|
-
const infoBeforeConnect = manager.getConnectionInfo();
|
|
211
|
-
expect(infoBeforeConnect.context).toBeUndefined();
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
describe('access mode from environment', () => {
|
|
215
|
-
it('should default to full access mode', () => {
|
|
216
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
217
|
-
dev: { host: 'localhost', port: '5432', username: 'user', password: 'pass' }
|
|
218
|
-
});
|
|
219
|
-
const manager = getDbManager();
|
|
220
|
-
expect(manager.isReadOnly()).toBe(false);
|
|
221
|
-
});
|
|
222
|
-
it('should enable read-only mode with POSTGRES_ACCESS_MODE=readonly', () => {
|
|
223
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
224
|
-
dev: { host: 'localhost', port: '5432', username: 'user', password: 'pass' }
|
|
225
|
-
});
|
|
226
|
-
process.env.POSTGRES_ACCESS_MODE = 'readonly';
|
|
227
|
-
const manager = getDbManager();
|
|
228
|
-
expect(manager.isReadOnly()).toBe(true);
|
|
229
|
-
});
|
|
230
|
-
it('should enable read-only mode with POSTGRES_ACCESS_MODE=read-only', () => {
|
|
231
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
232
|
-
dev: { host: 'localhost', port: '5432', username: 'user', password: 'pass' }
|
|
233
|
-
});
|
|
234
|
-
process.env.POSTGRES_ACCESS_MODE = 'read-only';
|
|
235
|
-
const manager = getDbManager();
|
|
236
|
-
expect(manager.isReadOnly()).toBe(true);
|
|
237
|
-
});
|
|
238
|
-
it('should enable read-only mode with POSTGRES_ACCESS_MODE=ro', () => {
|
|
239
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
240
|
-
dev: { host: 'localhost', port: '5432', username: 'user', password: 'pass' }
|
|
241
|
-
});
|
|
242
|
-
process.env.POSTGRES_ACCESS_MODE = 'ro';
|
|
243
|
-
const manager = getDbManager();
|
|
244
|
-
expect(manager.isReadOnly()).toBe(true);
|
|
245
|
-
});
|
|
246
|
-
it('should handle case-insensitive access mode', () => {
|
|
247
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
248
|
-
dev: { host: 'localhost', port: '5432', username: 'user', password: 'pass' }
|
|
249
|
-
});
|
|
250
|
-
process.env.POSTGRES_ACCESS_MODE = 'READONLY';
|
|
251
|
-
const manager = getDbManager();
|
|
252
|
-
expect(manager.isReadOnly()).toBe(true);
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
describe('connection state', () => {
|
|
256
|
-
it('should start with no connection', () => {
|
|
257
|
-
const manager = new DatabaseManager();
|
|
258
|
-
expect(manager.isConnected()).toBe(false);
|
|
259
|
-
expect(manager.getCurrentState()).toEqual({
|
|
260
|
-
currentServer: null,
|
|
261
|
-
currentDatabase: null,
|
|
262
|
-
currentSchema: null
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
it('should throw when server not found', async () => {
|
|
266
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
267
|
-
dev: { host: 'localhost', port: '5432', username: 'user', password: 'pass' }
|
|
268
|
-
});
|
|
269
|
-
const manager = new DatabaseManager();
|
|
270
|
-
await expect(manager.switchServer('nonexistent')).rejects.toThrow("Server 'nonexistent' not found");
|
|
271
|
-
});
|
|
272
|
-
it('should validate database name', async () => {
|
|
273
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
274
|
-
dev: { host: 'localhost', port: '5432', username: 'user', password: 'pass' }
|
|
275
|
-
});
|
|
276
|
-
const manager = new DatabaseManager();
|
|
277
|
-
await expect(manager.switchServer('dev', 'invalid;db')).rejects.toThrow('Invalid database name');
|
|
278
|
-
await expect(manager.switchServer('dev', 'db--name')).rejects.toThrow('Invalid database name'); // SQL comment
|
|
279
|
-
await expect(manager.switchServer('dev', '123db')).rejects.toThrow('Invalid database name'); // starts with digit
|
|
280
|
-
await expect(manager.switchServer('dev', "db'name")).rejects.toThrow('Invalid database name'); // quote
|
|
281
|
-
// Note: 'GraphQL-Intro-DB' with single hyphens is valid and allowed
|
|
282
|
-
});
|
|
283
|
-
it('should throw when querying without connection', async () => {
|
|
284
|
-
const manager = new DatabaseManager();
|
|
285
|
-
await expect(manager.query('SELECT 1')).rejects.toThrow('No database connection');
|
|
286
|
-
});
|
|
287
|
-
it('should throw when getting client without connection', async () => {
|
|
288
|
-
const manager = new DatabaseManager();
|
|
289
|
-
await expect(manager.getClient()).rejects.toThrow('No database connection');
|
|
290
|
-
});
|
|
291
|
-
it('should throw when switching database without server', async () => {
|
|
292
|
-
const manager = new DatabaseManager();
|
|
293
|
-
await expect(manager.switchDatabase('mydb')).rejects.toThrow('No server selected');
|
|
294
|
-
});
|
|
295
|
-
});
|
|
296
|
-
describe('read-only mode enforcement', () => {
|
|
297
|
-
let manager;
|
|
298
|
-
beforeEach(() => {
|
|
299
|
-
manager = new DatabaseManager(true); // read-only mode
|
|
300
|
-
});
|
|
301
|
-
it('should block INSERT queries in read-only mode', async () => {
|
|
302
|
-
// Mock the pool to test the validation
|
|
303
|
-
manager.currentPool = { query: jest.fn() };
|
|
304
|
-
await expect(manager.query("INSERT INTO users VALUES (1)")).rejects.toThrow('Read-only mode violation');
|
|
305
|
-
});
|
|
306
|
-
it('should block UPDATE queries in read-only mode', async () => {
|
|
307
|
-
manager.currentPool = { query: jest.fn() };
|
|
308
|
-
await expect(manager.query("UPDATE users SET name = 'test'")).rejects.toThrow('Read-only mode violation');
|
|
309
|
-
});
|
|
310
|
-
it('should block DELETE queries in read-only mode', async () => {
|
|
311
|
-
manager.currentPool = { query: jest.fn() };
|
|
312
|
-
await expect(manager.query("DELETE FROM users")).rejects.toThrow('Read-only mode violation');
|
|
313
|
-
});
|
|
314
|
-
it('should block DROP queries in read-only mode', async () => {
|
|
315
|
-
manager.currentPool = { query: jest.fn() };
|
|
316
|
-
await expect(manager.query("DROP TABLE users")).rejects.toThrow('Read-only mode violation');
|
|
317
|
-
});
|
|
318
|
-
it('should block CREATE queries in read-only mode', async () => {
|
|
319
|
-
manager.currentPool = { query: jest.fn() };
|
|
320
|
-
await expect(manager.query("CREATE TABLE test (id INT)")).rejects.toThrow('Read-only mode violation');
|
|
321
|
-
});
|
|
322
|
-
it('should block CTE with write operations', async () => {
|
|
323
|
-
manager.currentPool = { query: jest.fn() };
|
|
324
|
-
await expect(manager.query("WITH x AS (DELETE FROM users RETURNING *) SELECT * FROM x"))
|
|
325
|
-
.rejects.toThrow('Read-only mode violation');
|
|
326
|
-
});
|
|
327
|
-
it('should allow SELECT queries in read-only mode', async () => {
|
|
328
|
-
const mockQuery = jest.fn()
|
|
329
|
-
.mockResolvedValue({ rows: [], fields: [] });
|
|
330
|
-
manager.currentPool = { query: mockQuery };
|
|
331
|
-
await manager.query("SELECT * FROM users");
|
|
332
|
-
expect(mockQuery).toHaveBeenCalled();
|
|
333
|
-
});
|
|
334
|
-
});
|
|
335
|
-
describe('full access mode', () => {
|
|
336
|
-
let manager;
|
|
337
|
-
beforeEach(() => {
|
|
338
|
-
manager = new DatabaseManager(false); // full access mode
|
|
339
|
-
});
|
|
340
|
-
it('should allow INSERT queries in full access mode', async () => {
|
|
341
|
-
const mockQuery = jest.fn()
|
|
342
|
-
.mockResolvedValue({ rows: [], fields: [] });
|
|
343
|
-
manager.currentPool = { query: mockQuery };
|
|
344
|
-
await manager.query("INSERT INTO users VALUES (1)");
|
|
345
|
-
expect(mockQuery).toHaveBeenCalled();
|
|
346
|
-
});
|
|
347
|
-
it('should allow UPDATE queries in full access mode', async () => {
|
|
348
|
-
const mockQuery = jest.fn()
|
|
349
|
-
.mockResolvedValue({ rows: [], fields: [] });
|
|
350
|
-
manager.currentPool = { query: mockQuery };
|
|
351
|
-
await manager.query("UPDATE users SET name = 'test'");
|
|
352
|
-
expect(mockQuery).toHaveBeenCalled();
|
|
353
|
-
});
|
|
354
|
-
});
|
|
355
|
-
describe('singleton behavior', () => {
|
|
356
|
-
it('should return same instance on multiple calls', () => {
|
|
357
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
358
|
-
dev: { host: 'localhost', port: '5432', username: 'user', password: 'pass' }
|
|
359
|
-
});
|
|
360
|
-
const manager1 = getDbManager();
|
|
361
|
-
const manager2 = getDbManager();
|
|
362
|
-
expect(manager1).toBe(manager2);
|
|
363
|
-
});
|
|
364
|
-
it('should create new instance after reset', () => {
|
|
365
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
366
|
-
dev: { host: 'localhost', port: '5432', username: 'user', password: 'pass' }
|
|
367
|
-
});
|
|
368
|
-
const manager1 = getDbManager();
|
|
369
|
-
resetDbManager();
|
|
370
|
-
const manager2 = getDbManager();
|
|
371
|
-
expect(manager1).not.toBe(manager2);
|
|
372
|
-
});
|
|
373
|
-
});
|
|
374
|
-
describe('query validation', () => {
|
|
375
|
-
it('should reject empty SQL', async () => {
|
|
376
|
-
const manager = new DatabaseManager(false);
|
|
377
|
-
manager.currentPool = { query: jest.fn() };
|
|
378
|
-
await expect(manager.query('')).rejects.toThrow('SQL query is required');
|
|
379
|
-
await expect(manager.query(null)).rejects.toThrow('SQL query is required');
|
|
380
|
-
});
|
|
381
|
-
});
|
|
382
|
-
describe('setReadOnlyMode', () => {
|
|
383
|
-
it('should allow changing read-only mode', () => {
|
|
384
|
-
const manager = new DatabaseManager(true);
|
|
385
|
-
expect(manager.isReadOnly()).toBe(true);
|
|
386
|
-
manager.setReadOnlyMode(false);
|
|
387
|
-
expect(manager.isReadOnly()).toBe(false);
|
|
388
|
-
manager.setReadOnlyMode(true);
|
|
389
|
-
expect(manager.isReadOnly()).toBe(true);
|
|
390
|
-
});
|
|
391
|
-
});
|
|
392
|
-
describe('setQueryTimeout', () => {
|
|
393
|
-
it('should set query timeout within limits', () => {
|
|
394
|
-
const manager = new DatabaseManager();
|
|
395
|
-
manager.setQueryTimeout(60000);
|
|
396
|
-
expect(manager.queryTimeoutMs).toBe(60000);
|
|
397
|
-
});
|
|
398
|
-
it('should enforce minimum timeout', () => {
|
|
399
|
-
const manager = new DatabaseManager();
|
|
400
|
-
manager.setQueryTimeout(100);
|
|
401
|
-
expect(manager.queryTimeoutMs).toBe(1000);
|
|
402
|
-
});
|
|
403
|
-
it('should enforce maximum timeout', () => {
|
|
404
|
-
const manager = new DatabaseManager();
|
|
405
|
-
manager.setQueryTimeout(1000000);
|
|
406
|
-
expect(manager.queryTimeoutMs).toBe(300000);
|
|
407
|
-
});
|
|
408
|
-
});
|
|
409
|
-
});
|
|
410
|
-
//# sourceMappingURL=db-manager.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"db-manager.test.js","sourceRoot":"","sources":["../../src/__tests__/db-manager.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP Server Integration Tests
|
|
3
|
-
*
|
|
4
|
-
* These tests verify that the MCP server correctly:
|
|
5
|
-
* - Has proper tool definitions
|
|
6
|
-
* - Environment configuration works
|
|
7
|
-
*
|
|
8
|
-
* Note: Since ESM modules can't be easily mocked with Jest,
|
|
9
|
-
* we focus on testing tool definitions and basic behavior.
|
|
10
|
-
* Full integration tests would require a real database.
|
|
11
|
-
*/
|
|
12
|
-
export {};
|
|
13
|
-
//# sourceMappingURL=mcp-server.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/mcp-server.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP Server Integration Tests
|
|
3
|
-
*
|
|
4
|
-
* These tests verify that the MCP server correctly:
|
|
5
|
-
* - Has proper tool definitions
|
|
6
|
-
* - Environment configuration works
|
|
7
|
-
*
|
|
8
|
-
* Note: Since ESM modules can't be easily mocked with Jest,
|
|
9
|
-
* we focus on testing tool definitions and basic behavior.
|
|
10
|
-
* Full integration tests would require a real database.
|
|
11
|
-
*/
|
|
12
|
-
import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
|
|
13
|
-
describe('MCP Server Tool Definitions', () => {
|
|
14
|
-
describe('Tool Definitions', () => {
|
|
15
|
-
const expectedTools = [
|
|
16
|
-
'list_servers',
|
|
17
|
-
'list_databases',
|
|
18
|
-
'switch_server_db',
|
|
19
|
-
'get_current_connection',
|
|
20
|
-
'list_schemas',
|
|
21
|
-
'list_objects',
|
|
22
|
-
'get_object_details',
|
|
23
|
-
'execute_sql',
|
|
24
|
-
'explain_query',
|
|
25
|
-
'get_top_queries',
|
|
26
|
-
'analyze_workload_indexes',
|
|
27
|
-
'analyze_query_indexes',
|
|
28
|
-
'analyze_db_health'
|
|
29
|
-
];
|
|
30
|
-
it('should define all expected tools', () => {
|
|
31
|
-
expect(expectedTools).toHaveLength(13);
|
|
32
|
-
});
|
|
33
|
-
it('should have proper input schemas for required parameters', () => {
|
|
34
|
-
// Verify key tools have required parameters defined
|
|
35
|
-
const toolsWithRequired = [
|
|
36
|
-
{ name: 'switch_server_db', required: ['server'] },
|
|
37
|
-
{ name: 'list_objects', required: ['schema'] },
|
|
38
|
-
{ name: 'get_object_details', required: ['schema', 'objectName'] },
|
|
39
|
-
{ name: 'execute_sql', required: ['sql'] },
|
|
40
|
-
{ name: 'explain_query', required: ['sql'] },
|
|
41
|
-
{ name: 'analyze_query_indexes', required: ['queries'] },
|
|
42
|
-
];
|
|
43
|
-
expect(toolsWithRequired).toHaveLength(6);
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
describe('Environment Configuration', () => {
|
|
48
|
-
const originalEnv = process.env;
|
|
49
|
-
beforeEach(() => {
|
|
50
|
-
process.env = { ...originalEnv };
|
|
51
|
-
});
|
|
52
|
-
afterEach(() => {
|
|
53
|
-
process.env = originalEnv;
|
|
54
|
-
});
|
|
55
|
-
it('should support POSTGRES_SERVERS environment variable', () => {
|
|
56
|
-
process.env.POSTGRES_SERVERS = JSON.stringify({
|
|
57
|
-
dev: { host: 'localhost', port: '5432', username: 'user', password: 'pass' }
|
|
58
|
-
});
|
|
59
|
-
expect(JSON.parse(process.env.POSTGRES_SERVERS)).toHaveProperty('dev');
|
|
60
|
-
});
|
|
61
|
-
it('should support POSTGRES_ACCESS_MODE environment variable', () => {
|
|
62
|
-
process.env.POSTGRES_ACCESS_MODE = 'readonly';
|
|
63
|
-
expect(process.env.POSTGRES_ACCESS_MODE).toBe('readonly');
|
|
64
|
-
});
|
|
65
|
-
it('should parse server config correctly', () => {
|
|
66
|
-
const config = {
|
|
67
|
-
production: {
|
|
68
|
-
host: 'prod.example.com',
|
|
69
|
-
port: '5432',
|
|
70
|
-
username: 'admin',
|
|
71
|
-
password: 'secret'
|
|
72
|
-
},
|
|
73
|
-
development: {
|
|
74
|
-
host: 'localhost',
|
|
75
|
-
port: '5433',
|
|
76
|
-
username: 'dev',
|
|
77
|
-
password: 'devpass'
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
process.env.POSTGRES_SERVERS = JSON.stringify(config);
|
|
81
|
-
const parsed = JSON.parse(process.env.POSTGRES_SERVERS);
|
|
82
|
-
expect(Object.keys(parsed)).toEqual(['production', 'development']);
|
|
83
|
-
expect(parsed.production.host).toBe('prod.example.com');
|
|
84
|
-
expect(parsed.development.port).toBe('5433');
|
|
85
|
-
});
|
|
86
|
-
it('should handle invalid JSON in POSTGRES_SERVERS gracefully', () => {
|
|
87
|
-
process.env.POSTGRES_SERVERS = 'not valid json';
|
|
88
|
-
expect(() => JSON.parse(process.env.POSTGRES_SERVERS)).toThrow();
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
describe('Response Format Expectations', () => {
|
|
92
|
-
it('should expect list_servers response format', () => {
|
|
93
|
-
const expectedFormat = {
|
|
94
|
-
servers: [
|
|
95
|
-
{ name: 'string', host: 'string', port: 'string', isConnected: 'boolean', isDefault: 'boolean' }
|
|
96
|
-
],
|
|
97
|
-
currentServer: 'string|null',
|
|
98
|
-
currentDatabase: 'string|null',
|
|
99
|
-
currentSchema: 'string|null'
|
|
100
|
-
};
|
|
101
|
-
expect(expectedFormat).toHaveProperty('servers');
|
|
102
|
-
expect(expectedFormat).toHaveProperty('currentServer');
|
|
103
|
-
expect(expectedFormat).toHaveProperty('currentDatabase');
|
|
104
|
-
});
|
|
105
|
-
it('should expect list_databases response format', () => {
|
|
106
|
-
const expectedFormat = {
|
|
107
|
-
serverName: 'string',
|
|
108
|
-
databases: [
|
|
109
|
-
{ name: 'string', owner: 'string', encoding: 'string', size: 'string' }
|
|
110
|
-
],
|
|
111
|
-
currentDatabase: 'string|null'
|
|
112
|
-
};
|
|
113
|
-
expect(expectedFormat).toHaveProperty('serverName');
|
|
114
|
-
expect(expectedFormat).toHaveProperty('databases');
|
|
115
|
-
expect(expectedFormat).toHaveProperty('currentDatabase');
|
|
116
|
-
});
|
|
117
|
-
it('should expect execute_sql response format', () => {
|
|
118
|
-
const smallResultFormat = {
|
|
119
|
-
rows: [],
|
|
120
|
-
rowCount: 0,
|
|
121
|
-
fields: []
|
|
122
|
-
};
|
|
123
|
-
const largeResultFormat = {
|
|
124
|
-
rows: [],
|
|
125
|
-
rowCount: 1000,
|
|
126
|
-
fields: [],
|
|
127
|
-
outputFile: '/tmp/results.json',
|
|
128
|
-
truncated: true
|
|
129
|
-
};
|
|
130
|
-
expect(smallResultFormat).toHaveProperty('rows');
|
|
131
|
-
expect(smallResultFormat).toHaveProperty('rowCount');
|
|
132
|
-
expect(largeResultFormat).toHaveProperty('outputFile');
|
|
133
|
-
expect(largeResultFormat).toHaveProperty('truncated');
|
|
134
|
-
});
|
|
135
|
-
it('should expect analyze_db_health response format', () => {
|
|
136
|
-
const healthCheckFormat = [
|
|
137
|
-
{ category: 'Buffer Cache Hit Rate', status: 'healthy', message: 'string' },
|
|
138
|
-
{ category: 'Connection Health', status: 'warning', message: 'string' }
|
|
139
|
-
];
|
|
140
|
-
expect(Array.isArray(healthCheckFormat)).toBe(true);
|
|
141
|
-
expect(healthCheckFormat[0]).toHaveProperty('category');
|
|
142
|
-
expect(healthCheckFormat[0]).toHaveProperty('status');
|
|
143
|
-
expect(healthCheckFormat[0]).toHaveProperty('message');
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
//# sourceMappingURL=mcp-server.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.test.js","sourceRoot":"","sources":["../../src/__tests__/mcp-server.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema-tools.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/schema-tools.test.ts"],"names":[],"mappings":""}
|