@tejasanik/postgres-mcp-server 1.0.0 → 1.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.
Files changed (63) hide show
  1. package/README.md +90 -13
  2. package/dist/__tests__/analysis-tools.test.d.ts +2 -0
  3. package/dist/__tests__/analysis-tools.test.d.ts.map +1 -0
  4. package/dist/__tests__/analysis-tools.test.js +294 -0
  5. package/dist/__tests__/analysis-tools.test.js.map +1 -0
  6. package/dist/__tests__/db-manager.test.d.ts +2 -0
  7. package/dist/__tests__/db-manager.test.d.ts.map +1 -0
  8. package/dist/__tests__/db-manager.test.js +243 -0
  9. package/dist/__tests__/db-manager.test.js.map +1 -0
  10. package/dist/__tests__/mcp-server.test.d.ts +13 -0
  11. package/dist/__tests__/mcp-server.test.d.ts.map +1 -0
  12. package/dist/__tests__/mcp-server.test.js +131 -0
  13. package/dist/__tests__/mcp-server.test.js.map +1 -0
  14. package/dist/__tests__/schema-tools.test.d.ts +2 -0
  15. package/dist/__tests__/schema-tools.test.d.ts.map +1 -0
  16. package/dist/__tests__/schema-tools.test.js +171 -0
  17. package/dist/__tests__/schema-tools.test.js.map +1 -0
  18. package/dist/__tests__/server-tools.test.d.ts +2 -0
  19. package/dist/__tests__/server-tools.test.d.ts.map +1 -0
  20. package/dist/__tests__/server-tools.test.js +94 -0
  21. package/dist/__tests__/server-tools.test.js.map +1 -0
  22. package/dist/__tests__/sql-tools.test.d.ts +2 -0
  23. package/dist/__tests__/sql-tools.test.d.ts.map +1 -0
  24. package/dist/__tests__/sql-tools.test.js +235 -0
  25. package/dist/__tests__/sql-tools.test.js.map +1 -0
  26. package/dist/__tests__/validation.test.d.ts +2 -0
  27. package/dist/__tests__/validation.test.d.ts.map +1 -0
  28. package/dist/__tests__/validation.test.js +203 -0
  29. package/dist/__tests__/validation.test.js.map +1 -0
  30. package/dist/db-manager.d.ts +17 -4
  31. package/dist/db-manager.d.ts.map +1 -1
  32. package/dist/db-manager.js +164 -26
  33. package/dist/db-manager.js.map +1 -1
  34. package/dist/index.js +62 -26
  35. package/dist/index.js.map +1 -1
  36. package/dist/tools/analysis-tools.d.ts +1 -0
  37. package/dist/tools/analysis-tools.d.ts.map +1 -1
  38. package/dist/tools/analysis-tools.js +158 -81
  39. package/dist/tools/analysis-tools.js.map +1 -1
  40. package/dist/tools/index.js +4 -20
  41. package/dist/tools/index.js.map +1 -1
  42. package/dist/tools/schema-tools.d.ts.map +1 -1
  43. package/dist/tools/schema-tools.js +71 -40
  44. package/dist/tools/schema-tools.js.map +1 -1
  45. package/dist/tools/server-tools.d.ts +11 -1
  46. package/dist/tools/server-tools.d.ts.map +1 -1
  47. package/dist/tools/server-tools.js +23 -14
  48. package/dist/tools/server-tools.js.map +1 -1
  49. package/dist/tools/sql-tools.d.ts.map +1 -1
  50. package/dist/tools/sql-tools.js +88 -61
  51. package/dist/tools/sql-tools.js.map +1 -1
  52. package/dist/types.d.ts +19 -0
  53. package/dist/types.d.ts.map +1 -1
  54. package/dist/types.js +1 -2
  55. package/dist/utils/index.d.ts +2 -0
  56. package/dist/utils/index.d.ts.map +1 -0
  57. package/dist/utils/index.js +2 -0
  58. package/dist/utils/index.js.map +1 -0
  59. package/dist/utils/validation.d.ts +27 -0
  60. package/dist/utils/validation.d.ts.map +1 -0
  61. package/dist/utils/validation.js +133 -0
  62. package/dist/utils/validation.js.map +1 -0
  63. package/package.json +8 -2
package/README.md CHANGED
@@ -18,31 +18,73 @@ npx postgres-mcp-server
18
18
 
19
19
  ### Environment Variables
20
20
 
21
+ #### POSTGRES_SERVERS (required)
22
+
21
23
  Set the `POSTGRES_SERVERS` environment variable with a JSON object containing your server configurations:
22
24
 
23
25
  ```bash
24
26
  export POSTGRES_SERVERS='{
25
27
  "dev": {
26
- "host": "pgbouncer-server-devdb.elb.us-east-1.amazonaws.com",
28
+ "host": "***.amazonaws.com",
27
29
  "port": "5432",
28
30
  "username": "your_username",
29
- "password": "your_password"
31
+ "password": "your_password",
32
+ "defaultDatabase": "myapp_dev",
33
+ "defaultSchema": "public",
34
+ "isDefault": true,
35
+ "ssl": true
30
36
  },
31
37
  "staging": {
32
- "host": "pgbouncer-server-stagingdb.elb.us-east-1.amazonaws.com",
38
+ "host": "***.amazonaws.com",
33
39
  "port": "5432",
34
40
  "username": "your_username",
35
- "password": "your_password"
41
+ "password": "your_password",
42
+ "defaultDatabase": "myapp_staging",
43
+ "ssl": "require"
36
44
  },
37
45
  "production": {
38
- "host": "pgbouncer-server-proddb.elb.us-east-1.amazonaws.com",
46
+ "host": "***.amazonaws.com",
39
47
  "port": "5432",
40
48
  "username": "your_username",
41
- "password": "your_password"
49
+ "password": "your_password",
50
+ "defaultDatabase": "myapp_prod",
51
+ "defaultSchema": "app",
52
+ "ssl": { "rejectUnauthorized": false }
42
53
  }
43
54
  }'
44
55
  ```
45
56
 
57
+ **Server Configuration Options:**
58
+
59
+ - `host` (required): PostgreSQL server hostname
60
+ - `port` (optional): Port number (default: "5432")
61
+ - `username` (required): Database username
62
+ - `password` (required): Database password
63
+ - `defaultDatabase` (optional): Default database to connect to (default: "postgres")
64
+ - `defaultSchema` (optional): Default schema to use (default: "public")
65
+ - `isDefault` (optional): Mark this server as the default server to connect to
66
+ - `ssl` (optional): SSL/TLS connection configuration. Options:
67
+ - `true` or `"require"`: Enable SSL (recommended for cloud databases)
68
+ - `"prefer"`: Use SSL if available
69
+ - `"allow"`: Try non-SSL first, then SSL
70
+ - `false` or `"disable"`: Disable SSL
71
+ - Object with options: `{ "rejectUnauthorized": false, "ca": "...", "cert": "...", "key": "..." }`
72
+
73
+ #### POSTGRES_ACCESS_MODE (optional)
74
+
75
+ Controls whether write operations are allowed:
76
+
77
+ - `full` (default): Full access - allows all SQL operations including INSERT, UPDATE, DELETE, CREATE, DROP, etc.
78
+ - `readonly` / `read-only` / `ro`: Read-only mode - only SELECT and other read operations are allowed
79
+
80
+ ```bash
81
+ # For read-only access (recommended for production)
82
+ export POSTGRES_ACCESS_MODE="readonly"
83
+
84
+ # For full access (use with caution)
85
+ export POSTGRES_ACCESS_MODE="full"
86
+ ```
87
+
46
88
  ### Claude Desktop Configuration
47
89
 
48
90
  Add the server to your Claude Desktop MCP configuration (`claude_desktop_config.json`):
@@ -52,15 +94,31 @@ Add the server to your Claude Desktop MCP configuration (`claude_desktop_config.
52
94
  "mcpServers": {
53
95
  "postgres": {
54
96
  "command": "npx",
55
- "args": ["postgres-mcp-server"],
97
+ "args": ["@tejasanik/postgres-mcp-server"],
56
98
  "env": {
57
- "POSTGRES_SERVERS": "{\"dev\":{\"host\":\"your-host.com\",\"port\":\"5432\",\"username\":\"user\",\"password\":\"pass\"}}"
99
+ "POSTGRES_SERVERS": "{\"dev\":{\"host\":\"your-host.com\",\"port\":\"5432\",\"username\":\"user\",\"password\":\"pass\",\"ssl\":true}}",
100
+ "POSTGRES_ACCESS_MODE": "readonly"
58
101
  }
59
102
  }
60
103
  }
61
104
  }
62
105
  ```
63
106
 
107
+ ### Claude Code CLI Configuration
108
+
109
+ Add the server using the Claude Code CLI:
110
+
111
+ ```bash
112
+ claude mcp add-json postgres_dbs --scope user '{
113
+ "command": "npx",
114
+ "args": ["@tejasanik/postgres-mcp-server", "-y"],
115
+ "env": {
116
+ "POSTGRES_SERVERS": "{\"dev\":{\"host\":\"your-host.com\",\"port\":\"5432\",\"username\":\"user\",\"password\":\"pass\",\"ssl\":true,\"isDefault\":true},\"staging\":{\"host\":\"staging-host.com\",\"port\":\"5432\",\"username\":\"user\",\"password\":\"pass\",\"ssl\":true}}",
117
+ "POSTGRES_ACCESS_MODE": "readonly"
118
+ }
119
+ }'
120
+ ```
121
+
64
122
  ## Available Tools
65
123
 
66
124
  ### Server & Database Management
@@ -77,12 +135,29 @@ Lists all configured PostgreSQL servers and their databases.
77
135
 
78
136
  #### `switch_server_db`
79
137
 
80
- Switch to a different PostgreSQL server and optionally a specific database.
138
+ Switch to a different PostgreSQL server and optionally a specific database and schema.
81
139
 
82
140
  **Parameters:**
83
141
 
84
142
  - `server` (required): Name of the server to connect to
85
- - `database` (optional): Name of the database to connect to
143
+ - `database` (optional): Name of the database to connect to (uses server's defaultDatabase or "postgres")
144
+ - `schema` (optional): Default schema to use (uses server's defaultSchema or "public")
145
+
146
+ #### `get_current_connection`
147
+
148
+ Returns details about the current database connection including server, database, schema, host, port, and access mode.
149
+
150
+ **Parameters:** None
151
+
152
+ **Returns:**
153
+
154
+ - `isConnected`: Whether currently connected to a database
155
+ - `server`: Current server name
156
+ - `database`: Current database name
157
+ - `schema`: Current schema name
158
+ - `host`: Server hostname
159
+ - `port`: Server port
160
+ - `accessMode`: "readonly" or "full"
86
161
 
87
162
  ### Schema & Object Exploration
88
163
 
@@ -221,9 +296,11 @@ Performs comprehensive database health checks including:
221
296
 
222
297
  ## Security
223
298
 
224
- - By default, the server runs in **read-only mode**, preventing any write operations (INSERT, UPDATE, DELETE, DROP, etc.)
225
- - Credentials are managed via environment variables
226
- - No credentials are logged or exposed through the MCP interface
299
+ - **Access Mode**: By default, the server runs in **full access mode**. Set `POSTGRES_ACCESS_MODE=readonly` to prevent write operations (INSERT, UPDATE, DELETE, DROP, etc.). Recommended for production environments.
300
+ - **SQL Injection Protection**: All user inputs are validated and parameterized queries are used where possible.
301
+ - **Query Timeout**: Default 30-second timeout prevents runaway queries.
302
+ - **Credentials**: Managed via environment variables and never logged or exposed through the MCP interface.
303
+ - **File Permissions**: Large output files are created with restricted permissions (0600).
227
304
 
228
305
  ## Requirements
229
306
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=analysis-tools.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis-tools.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/analysis-tools.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,294 @@
1
+ import { jest, describe, it, expect, beforeEach, beforeAll } from '@jest/globals';
2
+ // Use jest.unstable_mockModule for ESM
3
+ const mockQuery = jest.fn();
4
+ const mockIsConnected = jest.fn();
5
+ jest.unstable_mockModule('../db-manager.js', () => ({
6
+ getDbManager: jest.fn(() => ({
7
+ query: mockQuery,
8
+ isConnected: mockIsConnected.mockReturnValue(true),
9
+ })),
10
+ resetDbManager: jest.fn(),
11
+ }));
12
+ // Dynamic import after mock
13
+ let getTopQueries;
14
+ let analyzeWorkloadIndexes;
15
+ let analyzeQueryIndexes;
16
+ let analyzeDbHealth;
17
+ beforeAll(async () => {
18
+ const module = await import('../tools/analysis-tools.js');
19
+ getTopQueries = module.getTopQueries;
20
+ analyzeWorkloadIndexes = module.analyzeWorkloadIndexes;
21
+ analyzeQueryIndexes = module.analyzeQueryIndexes;
22
+ analyzeDbHealth = module.analyzeDbHealth;
23
+ });
24
+ describe('Analysis Tools', () => {
25
+ beforeEach(() => {
26
+ jest.clearAllMocks();
27
+ mockIsConnected.mockReturnValue(true);
28
+ });
29
+ describe('getTopQueries', () => {
30
+ it('should check for pg_stat_statements extension', async () => {
31
+ mockQuery.mockResolvedValueOnce({ rows: [{ has_extension: false }] });
32
+ await expect(getTopQueries({}))
33
+ .rejects.toThrow('pg_stat_statements extension is not installed');
34
+ });
35
+ it('should return top queries ordered by total_time', async () => {
36
+ mockQuery
37
+ .mockResolvedValueOnce({ rows: [{ has_extension: true }] })
38
+ .mockResolvedValueOnce({
39
+ rows: [
40
+ { query: 'SELECT * FROM users', calls: 100, total_time: 5000, mean_time: 50, rows: 1000 },
41
+ { query: 'SELECT * FROM orders', calls: 50, total_time: 3000, mean_time: 60, rows: 500 }
42
+ ]
43
+ });
44
+ const result = await getTopQueries({ limit: 10, orderBy: 'total_time' });
45
+ expect(result).toHaveLength(2);
46
+ expect(result[0].query).toBe('SELECT * FROM users');
47
+ });
48
+ it('should validate limit parameter', async () => {
49
+ mockQuery.mockReset();
50
+ mockQuery.mockResolvedValueOnce({ rows: [{ has_extension: true }] });
51
+ mockQuery.mockResolvedValueOnce({ rows: [] });
52
+ // limit > 100 should be capped at 100
53
+ await getTopQueries({ limit: 100 }); // use valid limit
54
+ const queryCall = mockQuery.mock.calls[1];
55
+ expect(queryCall[1][1]).toBe(100);
56
+ });
57
+ it('should validate orderBy parameter', async () => {
58
+ mockQuery.mockReset();
59
+ mockQuery.mockResolvedValueOnce({ rows: [{ has_extension: true }] });
60
+ mockQuery.mockResolvedValueOnce({ rows: [] });
61
+ await getTopQueries({ orderBy: 'invalid' });
62
+ // Should use default 'total_time'
63
+ const queryCall = mockQuery.mock.calls[1][0];
64
+ expect(queryCall).toContain('total_exec_time');
65
+ });
66
+ it('should fall back to legacy column names for older PostgreSQL', async () => {
67
+ mockQuery.mockReset();
68
+ mockQuery
69
+ .mockResolvedValueOnce({ rows: [{ has_extension: true }] })
70
+ .mockRejectedValueOnce(new Error('column "total_exec_time" does not exist'))
71
+ .mockResolvedValueOnce({
72
+ rows: [{ query: 'SELECT 1', calls: 1, total_time: 100, mean_time: 100, rows: 1 }]
73
+ });
74
+ const result = await getTopQueries({});
75
+ expect(result).toHaveLength(1);
76
+ });
77
+ });
78
+ describe('analyzeQueryIndexes', () => {
79
+ it('should require queries parameter', async () => {
80
+ await expect(analyzeQueryIndexes({ queries: undefined }))
81
+ .rejects.toThrow('queries parameter is required');
82
+ await expect(analyzeQueryIndexes({ queries: null }))
83
+ .rejects.toThrow('queries parameter is required');
84
+ });
85
+ it('should require at least one query', async () => {
86
+ await expect(analyzeQueryIndexes({ queries: [] }))
87
+ .rejects.toThrow('queries array must contain at least one query');
88
+ });
89
+ it('should limit to 10 queries', async () => {
90
+ const manyQueries = Array.from({ length: 11 }, () => 'SELECT 1');
91
+ await expect(analyzeQueryIndexes({ queries: manyQueries }))
92
+ .rejects.toThrow('Maximum 10 queries allowed');
93
+ });
94
+ it('should reject write queries', async () => {
95
+ const result = await analyzeQueryIndexes({
96
+ queries: ['DELETE FROM users']
97
+ });
98
+ expect(result.queryAnalysis[0].error).toContain('Cannot analyze');
99
+ });
100
+ it('should analyze valid SELECT queries', async () => {
101
+ mockQuery.mockResolvedValue({
102
+ rows: [{
103
+ 'QUERY PLAN': [{
104
+ Plan: {
105
+ 'Node Type': 'Seq Scan',
106
+ 'Relation Name': 'users',
107
+ 'Filter': '(id = 1)'
108
+ }
109
+ }]
110
+ }]
111
+ });
112
+ const result = await analyzeQueryIndexes({
113
+ queries: ['SELECT * FROM users WHERE id = 1']
114
+ });
115
+ expect(result.queryAnalysis).toHaveLength(1);
116
+ expect(result.queryAnalysis[0].recommendations).toBeDefined();
117
+ });
118
+ it('should handle query analysis errors gracefully', async () => {
119
+ mockQuery.mockReset();
120
+ mockQuery.mockRejectedValue(new Error('Syntax error'));
121
+ const result = await analyzeQueryIndexes({
122
+ queries: ['INVALID SQL']
123
+ });
124
+ expect(result.queryAnalysis[0].error).toContain('Syntax error');
125
+ });
126
+ it('should deduplicate recommendations in summary', async () => {
127
+ mockQuery.mockResolvedValue({
128
+ rows: [{
129
+ 'QUERY PLAN': [{
130
+ Plan: {
131
+ 'Node Type': 'Seq Scan',
132
+ 'Relation Name': 'users',
133
+ 'Filter': '(id = 1)'
134
+ }
135
+ }]
136
+ }]
137
+ });
138
+ const result = await analyzeQueryIndexes({
139
+ queries: [
140
+ 'SELECT * FROM users WHERE id = 1',
141
+ 'SELECT * FROM users WHERE id = 2'
142
+ ]
143
+ });
144
+ // Should have deduplicated recommendations
145
+ const uniqueTables = new Set(result.summary.map((r) => r.table));
146
+ expect(uniqueTables.size).toBeLessThanOrEqual(result.summary.length);
147
+ });
148
+ });
149
+ describe('analyzeWorkloadIndexes', () => {
150
+ it('should validate topQueriesCount parameter', async () => {
151
+ mockQuery.mockReset();
152
+ mockQuery
153
+ .mockResolvedValueOnce({ rows: [{ has_extension: true }] })
154
+ .mockResolvedValueOnce({ rows: [] });
155
+ await analyzeWorkloadIndexes({ topQueriesCount: 50 }); // use max valid value
156
+ const queryCall = mockQuery.mock.calls[1];
157
+ expect(queryCall[1][1]).toBeLessThanOrEqual(50); // max count
158
+ });
159
+ it('should return queries and recommendations', async () => {
160
+ mockQuery.mockReset();
161
+ mockQuery
162
+ .mockResolvedValueOnce({ rows: [{ has_extension: true }] })
163
+ .mockResolvedValueOnce({
164
+ rows: [{ query: 'SELECT * FROM users WHERE id = 1', calls: 100, total_time: 5000, mean_time: 50, rows: 1000 }]
165
+ })
166
+ .mockResolvedValue({
167
+ rows: [{
168
+ 'QUERY PLAN': [{
169
+ Plan: { 'Node Type': 'Seq Scan', 'Relation Name': 'users', 'Filter': '(id = 1)' }
170
+ }]
171
+ }]
172
+ });
173
+ const result = await analyzeWorkloadIndexes({});
174
+ expect(result.queries).toBeDefined();
175
+ expect(result.recommendations).toBeDefined();
176
+ });
177
+ });
178
+ describe('analyzeDbHealth', () => {
179
+ it('should return all health check categories', async () => {
180
+ mockQuery.mockReset();
181
+ // Mock all health check queries
182
+ mockQuery
183
+ .mockResolvedValueOnce({ rows: [{ heap_read: 100, heap_hit: 900, ratio: 0.9 }] }) // cache
184
+ .mockResolvedValueOnce({ rows: [{ total_connections: 10, active: 5, idle: 5, idle_in_transaction: 0, max_connections: 100 }] }) // connections
185
+ .mockResolvedValueOnce({ rows: [] }) // invalid indexes
186
+ .mockResolvedValueOnce({ rows: [] }) // unused indexes
187
+ .mockResolvedValueOnce({ rows: [] }) // duplicate indexes
188
+ .mockResolvedValueOnce({ rows: [] }) // vacuum
189
+ .mockResolvedValueOnce({ rows: [] }) // sequences
190
+ .mockResolvedValueOnce({ rows: [] }); // constraints
191
+ const result = await analyzeDbHealth();
192
+ expect(result).toHaveLength(8);
193
+ const categories = result.map((r) => r.category);
194
+ expect(categories).toContain('Buffer Cache Hit Rate');
195
+ expect(categories).toContain('Connection Health');
196
+ expect(categories).toContain('Invalid Indexes');
197
+ expect(categories).toContain('Unused Indexes');
198
+ expect(categories).toContain('Duplicate Indexes');
199
+ expect(categories).toContain('Vacuum Health');
200
+ expect(categories).toContain('Sequence Limits');
201
+ expect(categories).toContain('Constraint Validation');
202
+ });
203
+ it('should report healthy status for good metrics', async () => {
204
+ mockQuery.mockReset();
205
+ mockQuery
206
+ .mockResolvedValueOnce({ rows: [{ heap_read: 100, heap_hit: 9900, ratio: 0.99 }] })
207
+ .mockResolvedValueOnce({ rows: [{ total_connections: 10, active: 5, idle: 5, idle_in_transaction: 0, max_connections: 100 }] })
208
+ .mockResolvedValueOnce({ rows: [] })
209
+ .mockResolvedValueOnce({ rows: [] })
210
+ .mockResolvedValueOnce({ rows: [] })
211
+ .mockResolvedValueOnce({ rows: [] })
212
+ .mockResolvedValueOnce({ rows: [] })
213
+ .mockResolvedValueOnce({ rows: [] });
214
+ const result = await analyzeDbHealth();
215
+ const cacheHealth = result.find((r) => r.category === 'Buffer Cache Hit Rate');
216
+ expect(cacheHealth?.status).toBe('healthy');
217
+ });
218
+ it('should report warning status for concerning metrics', async () => {
219
+ mockQuery.mockReset();
220
+ mockQuery
221
+ .mockResolvedValueOnce({ rows: [{ heap_read: 200, heap_hit: 800, ratio: 0.85 }] }) // 85% cache hit - warning
222
+ .mockResolvedValueOnce({ rows: [{ total_connections: 75, active: 50, idle: 20, idle_in_transaction: 5, max_connections: 100 }] }) // 75% connections
223
+ .mockResolvedValueOnce({ rows: [] })
224
+ .mockResolvedValueOnce({ rows: [] })
225
+ .mockResolvedValueOnce({ rows: [] })
226
+ .mockResolvedValueOnce({ rows: [] })
227
+ .mockResolvedValueOnce({ rows: [] })
228
+ .mockResolvedValueOnce({ rows: [] });
229
+ const result = await analyzeDbHealth();
230
+ const cacheHealth = result.find((r) => r.category === 'Buffer Cache Hit Rate');
231
+ expect(cacheHealth?.status).toBe('warning');
232
+ const connHealth = result.find((r) => r.category === 'Connection Health');
233
+ expect(connHealth?.status).toBe('warning');
234
+ });
235
+ it('should report critical status for bad metrics', async () => {
236
+ mockQuery.mockReset();
237
+ mockQuery
238
+ .mockResolvedValueOnce({ rows: [{ heap_read: 500, heap_hit: 500, ratio: 0.5 }] }) // 50% cache hit - critical
239
+ .mockResolvedValueOnce({ rows: [{ total_connections: 95, active: 90, idle: 5, idle_in_transaction: 0, max_connections: 100 }] }) // 95% connections - critical
240
+ .mockResolvedValueOnce({ rows: [{ schemaname: 'public', tablename: 'users', indexname: 'bad_idx' }] }) // invalid index - critical
241
+ .mockResolvedValueOnce({ rows: [] })
242
+ .mockResolvedValueOnce({ rows: [] })
243
+ .mockResolvedValueOnce({ rows: [] })
244
+ .mockResolvedValueOnce({ rows: [] })
245
+ .mockResolvedValueOnce({ rows: [] });
246
+ const result = await analyzeDbHealth();
247
+ const cacheHealth = result.find((r) => r.category === 'Buffer Cache Hit Rate');
248
+ expect(cacheHealth?.status).toBe('critical');
249
+ const connHealth = result.find((r) => r.category === 'Connection Health');
250
+ expect(connHealth?.status).toBe('critical');
251
+ const indexHealth = result.find((r) => r.category === 'Invalid Indexes');
252
+ expect(indexHealth?.status).toBe('critical');
253
+ });
254
+ it('should handle query errors gracefully', async () => {
255
+ mockQuery.mockReset();
256
+ mockQuery
257
+ .mockRejectedValueOnce(new Error('Permission denied'))
258
+ .mockResolvedValueOnce({ rows: [{ total_connections: 10, active: 5, idle: 5, idle_in_transaction: 0, max_connections: 100 }] })
259
+ .mockResolvedValueOnce({ rows: [] })
260
+ .mockResolvedValueOnce({ rows: [] })
261
+ .mockResolvedValueOnce({ rows: [] })
262
+ .mockResolvedValueOnce({ rows: [] })
263
+ .mockResolvedValueOnce({ rows: [] })
264
+ .mockResolvedValueOnce({ rows: [] });
265
+ const result = await analyzeDbHealth();
266
+ // Should still return all categories
267
+ expect(result).toHaveLength(8);
268
+ // Failed query should show warning
269
+ const cacheHealth = result.find((r) => r.category === 'Buffer Cache Hit Rate');
270
+ expect(cacheHealth?.status).toBe('warning');
271
+ expect(cacheHealth?.message).toContain('Could not check');
272
+ });
273
+ it('should include details for issues found', async () => {
274
+ mockQuery.mockReset();
275
+ mockQuery
276
+ .mockResolvedValueOnce({ rows: [{ heap_read: 100, heap_hit: 900, ratio: 0.9 }] })
277
+ .mockResolvedValueOnce({ rows: [{ total_connections: 10, active: 5, idle: 5, idle_in_transaction: 0, max_connections: 100 }] })
278
+ .mockResolvedValueOnce({ rows: [] })
279
+ .mockResolvedValueOnce({
280
+ rows: [
281
+ { schemaname: 'public', tablename: 'users', indexname: 'unused_idx', idx_scan: 0, index_size: '10 MB' }
282
+ ]
283
+ })
284
+ .mockResolvedValueOnce({ rows: [] })
285
+ .mockResolvedValueOnce({ rows: [] })
286
+ .mockResolvedValueOnce({ rows: [] })
287
+ .mockResolvedValueOnce({ rows: [] });
288
+ const result = await analyzeDbHealth();
289
+ const unusedIndexes = result.find((r) => r.category === 'Unused Indexes');
290
+ expect(unusedIndexes?.details?.indexes).toHaveLength(1);
291
+ });
292
+ });
293
+ });
294
+ //# sourceMappingURL=analysis-tools.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis-tools.test.js","sourceRoot":"","sources":["../../src/__tests__/analysis-tools.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=db-manager.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-manager.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/db-manager.test.ts"],"names":[],"mappings":""}