@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.
- package/README.md +90 -13
- package/dist/__tests__/analysis-tools.test.d.ts +2 -0
- package/dist/__tests__/analysis-tools.test.d.ts.map +1 -0
- package/dist/__tests__/analysis-tools.test.js +294 -0
- package/dist/__tests__/analysis-tools.test.js.map +1 -0
- package/dist/__tests__/db-manager.test.d.ts +2 -0
- package/dist/__tests__/db-manager.test.d.ts.map +1 -0
- package/dist/__tests__/db-manager.test.js +243 -0
- package/dist/__tests__/db-manager.test.js.map +1 -0
- package/dist/__tests__/mcp-server.test.d.ts +13 -0
- package/dist/__tests__/mcp-server.test.d.ts.map +1 -0
- package/dist/__tests__/mcp-server.test.js +131 -0
- package/dist/__tests__/mcp-server.test.js.map +1 -0
- package/dist/__tests__/schema-tools.test.d.ts +2 -0
- package/dist/__tests__/schema-tools.test.d.ts.map +1 -0
- package/dist/__tests__/schema-tools.test.js +171 -0
- package/dist/__tests__/schema-tools.test.js.map +1 -0
- package/dist/__tests__/server-tools.test.d.ts +2 -0
- package/dist/__tests__/server-tools.test.d.ts.map +1 -0
- package/dist/__tests__/server-tools.test.js +94 -0
- package/dist/__tests__/server-tools.test.js.map +1 -0
- package/dist/__tests__/sql-tools.test.d.ts +2 -0
- package/dist/__tests__/sql-tools.test.d.ts.map +1 -0
- package/dist/__tests__/sql-tools.test.js +235 -0
- package/dist/__tests__/sql-tools.test.js.map +1 -0
- package/dist/__tests__/validation.test.d.ts +2 -0
- package/dist/__tests__/validation.test.d.ts.map +1 -0
- package/dist/__tests__/validation.test.js +203 -0
- package/dist/__tests__/validation.test.js.map +1 -0
- package/dist/db-manager.d.ts +17 -4
- package/dist/db-manager.d.ts.map +1 -1
- package/dist/db-manager.js +164 -26
- package/dist/db-manager.js.map +1 -1
- package/dist/index.js +62 -26
- package/dist/index.js.map +1 -1
- package/dist/tools/analysis-tools.d.ts +1 -0
- package/dist/tools/analysis-tools.d.ts.map +1 -1
- package/dist/tools/analysis-tools.js +158 -81
- package/dist/tools/analysis-tools.js.map +1 -1
- package/dist/tools/index.js +4 -20
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/schema-tools.d.ts.map +1 -1
- package/dist/tools/schema-tools.js +71 -40
- package/dist/tools/schema-tools.js.map +1 -1
- package/dist/tools/server-tools.d.ts +11 -1
- package/dist/tools/server-tools.d.ts.map +1 -1
- package/dist/tools/server-tools.js +23 -14
- package/dist/tools/server-tools.js.map +1 -1
- package/dist/tools/sql-tools.d.ts.map +1 -1
- package/dist/tools/sql-tools.js +88 -61
- package/dist/tools/sql-tools.js.map +1 -1
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -2
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/validation.d.ts +27 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +133 -0
- package/dist/utils/validation.js.map +1 -0
- 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": "
|
|
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": "
|
|
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": "
|
|
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 **
|
|
225
|
-
-
|
|
226
|
-
-
|
|
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 @@
|
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"db-manager.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/db-manager.test.ts"],"names":[],"mappings":""}
|