@tejasanik/postgres-mcp-server 2.1.1 → 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.
Files changed (95) hide show
  1. package/README.md +163 -95
  2. package/dist/db-manager/index.d.ts +7 -0
  3. package/dist/db-manager/index.d.ts.map +1 -0
  4. package/dist/db-manager/index.js +7 -0
  5. package/dist/db-manager/index.js.map +1 -0
  6. package/dist/db-manager/validation.d.ts +35 -0
  7. package/dist/db-manager/validation.d.ts.map +1 -0
  8. package/dist/db-manager/validation.js +54 -0
  9. package/dist/db-manager/validation.js.map +1 -0
  10. package/dist/db-manager.d.ts +175 -5
  11. package/dist/db-manager.d.ts.map +1 -1
  12. package/dist/db-manager.js +589 -26
  13. package/dist/db-manager.js.map +1 -1
  14. package/dist/index.js +141 -11
  15. package/dist/index.js.map +1 -1
  16. package/dist/tools/analysis-tools.d.ts.map +1 -1
  17. package/dist/tools/analysis-tools.js +53 -49
  18. package/dist/tools/analysis-tools.js.map +1 -1
  19. package/dist/tools/schema-tools.d.ts +40 -1
  20. package/dist/tools/schema-tools.d.ts.map +1 -1
  21. package/dist/tools/schema-tools.js +174 -92
  22. package/dist/tools/schema-tools.js.map +1 -1
  23. package/dist/tools/server-tools.d.ts.map +1 -1
  24. package/dist/tools/server-tools.js +5 -2
  25. package/dist/tools/server-tools.js.map +1 -1
  26. package/dist/tools/sql/utils/connection-utils.d.ts +79 -0
  27. package/dist/tools/sql/utils/connection-utils.d.ts.map +1 -0
  28. package/dist/tools/sql/utils/connection-utils.js +129 -0
  29. package/dist/tools/sql/utils/connection-utils.js.map +1 -0
  30. package/dist/tools/sql/utils/constants.d.ts +55 -0
  31. package/dist/tools/sql/utils/constants.d.ts.map +1 -0
  32. package/dist/tools/sql/utils/constants.js +55 -0
  33. package/dist/tools/sql/utils/constants.js.map +1 -0
  34. package/dist/tools/sql/utils/dry-run-utils.d.ts +31 -0
  35. package/dist/tools/sql/utils/dry-run-utils.d.ts.map +1 -0
  36. package/dist/tools/sql/utils/dry-run-utils.js +173 -0
  37. package/dist/tools/sql/utils/dry-run-utils.js.map +1 -0
  38. package/dist/tools/sql/utils/file-handler.d.ts +57 -0
  39. package/dist/tools/sql/utils/file-handler.d.ts.map +1 -0
  40. package/dist/tools/sql/utils/file-handler.js +150 -0
  41. package/dist/tools/sql/utils/file-handler.js.map +1 -0
  42. package/dist/tools/sql/utils/index.d.ts +12 -0
  43. package/dist/tools/sql/utils/index.d.ts.map +1 -0
  44. package/dist/tools/sql/utils/index.js +12 -0
  45. package/dist/tools/sql/utils/index.js.map +1 -0
  46. package/dist/tools/sql/utils/result-formatter.d.ts +94 -0
  47. package/dist/tools/sql/utils/result-formatter.d.ts.map +1 -0
  48. package/dist/tools/sql/utils/result-formatter.js +154 -0
  49. package/dist/tools/sql/utils/result-formatter.js.map +1 -0
  50. package/dist/tools/sql/utils/sql-parser.d.ts +125 -0
  51. package/dist/tools/sql/utils/sql-parser.d.ts.map +1 -0
  52. package/dist/tools/sql/utils/sql-parser.js +468 -0
  53. package/dist/tools/sql/utils/sql-parser.js.map +1 -0
  54. package/dist/tools/sql-tools.d.ts +21 -0
  55. package/dist/tools/sql-tools.d.ts.map +1 -1
  56. package/dist/tools/sql-tools.js +383 -532
  57. package/dist/tools/sql-tools.js.map +1 -1
  58. package/dist/types.d.ts +38 -0
  59. package/dist/types.d.ts.map +1 -1
  60. package/dist/utils/retry.d.ts +1 -1
  61. package/dist/utils/retry.d.ts.map +1 -1
  62. package/dist/utils/retry.js.map +1 -1
  63. package/dist/utils/validation.d.ts +45 -9
  64. package/dist/utils/validation.d.ts.map +1 -1
  65. package/dist/utils/validation.js +335 -72
  66. package/dist/utils/validation.js.map +1 -1
  67. package/package.json +9 -2
  68. package/dist/__tests__/analysis-tools.test.d.ts +0 -2
  69. package/dist/__tests__/analysis-tools.test.d.ts.map +0 -1
  70. package/dist/__tests__/analysis-tools.test.js +0 -294
  71. package/dist/__tests__/analysis-tools.test.js.map +0 -1
  72. package/dist/__tests__/db-manager.test.d.ts +0 -2
  73. package/dist/__tests__/db-manager.test.d.ts.map +0 -1
  74. package/dist/__tests__/db-manager.test.js +0 -410
  75. package/dist/__tests__/db-manager.test.js.map +0 -1
  76. package/dist/__tests__/mcp-server.test.d.ts +0 -13
  77. package/dist/__tests__/mcp-server.test.d.ts.map +0 -1
  78. package/dist/__tests__/mcp-server.test.js +0 -146
  79. package/dist/__tests__/mcp-server.test.js.map +0 -1
  80. package/dist/__tests__/schema-tools.test.d.ts +0 -2
  81. package/dist/__tests__/schema-tools.test.d.ts.map +0 -1
  82. package/dist/__tests__/schema-tools.test.js +0 -171
  83. package/dist/__tests__/schema-tools.test.js.map +0 -1
  84. package/dist/__tests__/server-tools.test.d.ts +0 -2
  85. package/dist/__tests__/server-tools.test.d.ts.map +0 -1
  86. package/dist/__tests__/server-tools.test.js +0 -137
  87. package/dist/__tests__/server-tools.test.js.map +0 -1
  88. package/dist/__tests__/sql-tools.test.d.ts +0 -2
  89. package/dist/__tests__/sql-tools.test.d.ts.map +0 -1
  90. package/dist/__tests__/sql-tools.test.js +0 -1912
  91. package/dist/__tests__/sql-tools.test.js.map +0 -1
  92. package/dist/__tests__/validation.test.d.ts +0 -2
  93. package/dist/__tests__/validation.test.d.ts.map +0 -1
  94. package/dist/__tests__/validation.test.js +0 -203
  95. package/dist/__tests__/validation.test.js.map +0 -1
package/README.md CHANGED
@@ -4,101 +4,6 @@ A Model Context Protocol (MCP) server for PostgreSQL database management and ana
4
4
 
5
5
  ---
6
6
 
7
- ## 🤖 Agent Experience (AX) - Claude Code Review
8
-
9
- **Tested by:** Claude Code (Sonnet 4.5)
10
- **Use Case:** Database deployment, schema exploration, and SQL migration
11
- **Rating:** ⭐⭐⭐⭐⭐ (9.5/10)
12
-
13
- ### What I Loved
14
-
15
- **1. Clear, Structured Responses**
16
- Every response includes connection context (`server`, `database`, `schema`), making it crystal clear which environment I'm working in. This is essential when managing multiple databases - I never have to guess where a query ran.
17
-
18
- **2. Excellent Error Handling**
19
- When I encountered a syntax error with Liquibase's `/` delimiter, the error message showed:
20
-
21
- - Exact line number (151)
22
- - The failing statement
23
- - Transaction rollback confirmation
24
-
25
- This made troubleshooting instant. No digging through logs or guessing what failed.
26
-
27
- **3. Server Management is Intuitive**
28
-
29
- - `list_servers` → Shows all available servers with connection status
30
- - `list_databases` → Filters databases by server name
31
- - `switch_server_db` → Seamless switching with immediate confirmation
32
-
33
- The flow is natural: discover → select → connect → execute.
34
-
35
- **4. SQL File Deployment Made Easy**
36
- The `stripPatterns` feature solved my exact problem:
37
-
38
- ```javascript
39
- execute_sql_file({
40
- filePath: "/path/to/liquibase.sql",
41
- stripPatterns: ["/"], // Removes Liquibase delimiters
42
- });
43
- ```
44
-
45
- Before this feature, I had to manually remove delimiters or use raw `execute_sql`. Now it's one clean call.
46
-
47
- **5. Dry-Run Capabilities are Outstanding**
48
- `dry_run_sql_file` is a game-changer:
49
-
50
- - Executes ALL statements in a transaction
51
- - Shows REAL errors with PostgreSQL error codes and constraint names
52
- - Automatically skips non-rollbackable operations (VACUUM, NEXTVAL)
53
- - Provides EXPLAIN plans for skipped statements
54
- - Then rolls back everything
55
-
56
- This is _way_ better than just parsing - I can catch constraint violations, trigger issues, and get exact row counts before deployment.
57
-
58
- **6. Security by Default**
59
-
60
- - Credentials never appear in responses
61
- - Host/port intentionally hidden (only server names visible)
62
- - Readonly mode available for production safety
63
- - Connection context always visible
64
-
65
- ### Improvements Based on My Feedback
66
-
67
- The developer implemented several features after I tested the MCP:
68
-
69
- ✅ **SQL File Delimiter Support** - Added `stripPatterns` for Liquibase `/`, SQL Server `GO`, etc.
70
- ✅ **Validate-Only Mode** - `execute_sql_file({ validateOnly: true })` previews without execution
71
- ✅ **Enhanced Connection Info** - `get_current_connection` now returns `user` and AI `context`
72
- ✅ **Comprehensive Dry-Run** - `dry_run_sql_file` provides real execution + rollback
73
- ✅ **Better Error Details** - PostgreSQL error codes, constraint names, hints included
74
-
75
- ### Real-World Experience
76
-
77
- **Task:** Deploy a PostgreSQL function to two databases (dev + GraphQL-Intro-DB)
78
-
79
- 1. **Discovery**: `list_servers` showed all configured servers
80
- 2. **Preview**: Used `preview_sql_file` to check the file structure
81
- 3. **Issue**: Got syntax error from Liquibase's `/` delimiter
82
- 4. **Solution**: Switched to direct `execute_sql` to bypass the delimiter
83
- 5. **Deployment**: Successfully deployed to both databases
84
- 6. **Verification**: Used `get_current_connection` to confirm each deployment
85
-
86
- Total time: ~3 minutes. The structured responses and clear errors made it feel effortless.
87
-
88
- ### Minor Suggestions for Future
89
-
90
- 1. **Batch Cross Servers Deployment** - Deploy same script to multiple servers at once
91
- 2. **Recent Connections** - Quick-switch to recently used databases
92
- 3. **Statement Progress** - Show progress for large SQL files (e.g., "Executing statement 15/100...")
93
-
94
- ### Bottom Line
95
-
96
- This MCP is production-ready and developer-friendly. The combination of clear responses, robust error handling, and powerful features like dry-run make it an essential tool for database work. The developer clearly understands the needs of both AI agents and human operators.
97
-
98
- **Recommended for:** Database migrations, schema exploration, multi-environment management, and production deployments.
99
-
100
- ---
101
-
102
7
  ## Installation
103
8
 
104
9
  ```bash
@@ -395,6 +300,7 @@ Lists all database schemas in the current PostgreSQL database.
395
300
  **Parameters:**
396
301
 
397
302
  - `includeSystemSchemas` (optional): Include system schemas
303
+ - `server`, `database`, `schema` (optional): One-time connection override
398
304
 
399
305
  #### `list_objects`
400
306
 
@@ -405,6 +311,7 @@ Lists database objects within a specified schema.
405
311
  - `schema` (required): Schema name to list objects from
406
312
  - `objectType` (optional): Type of objects to list (table, view, sequence, extension, all)
407
313
  - `filter` (optional): Filter objects by name
314
+ - `server`, `database`, `targetSchema` (optional): One-time connection override
408
315
 
409
316
  #### `get_object_details`
410
317
 
@@ -415,6 +322,7 @@ Provides detailed information about a database object including columns, constra
415
322
  - `schema` (required): Schema name containing the object
416
323
  - `objectName` (required): Name of the object
417
324
  - `objectType` (optional): Type of the object
325
+ - `server`, `database`, `targetSchema` (optional): One-time connection override
418
326
 
419
327
  ### Query Execution
420
328
 
@@ -432,6 +340,7 @@ Executes SQL statements on the database. Supports pagination and parameterized q
432
340
  - `includeSchemaHint` (optional): Include schema information (columns, primary keys, foreign keys) for tables referenced in the query.
433
341
  - `allowMultipleStatements` (optional): Allow multiple SQL statements separated by semicolons. Returns results for each statement with line numbers.
434
342
  - `transactionId` (optional): Execute within an active transaction. Get this from `begin_transaction`.
343
+ - `server`, `database`, `schema` (optional): One-time connection override. Execute on a different server/database/schema without changing the main connection. Cannot be used with `transactionId`.
435
344
 
436
345
  **Returns:**
437
346
 
@@ -811,6 +720,70 @@ Gets the execution plan for a SQL query.
811
720
  - `buffers` (optional): Include buffer usage statistics
812
721
  - `format` (optional): Output format (text, json, yaml, xml)
813
722
  - `hypotheticalIndexes` (optional): Simulate indexes (requires hypopg extension)
723
+ - `server`, `database`, `schema` (optional): One-time connection override (see below)
724
+
725
+ ### Connection Override (One-Time Execution)
726
+
727
+ Most query execution tools support **one-time connection override** parameters that allow executing a query on a different server/database/schema without changing the main connection. This is useful for:
728
+
729
+ - Querying multiple databases in a single workflow
730
+ - Running read queries against a replica while keeping the main connection to primary
731
+ - Comparing schemas across different servers
732
+
733
+ **Supported tools:** `execute_sql`, `explain_query`, `list_schemas`, `list_objects`, `get_object_details`, `execute_sql_file`, `mutation_preview`, `mutation_dry_run`, `dry_run_sql_file`, `batch_execute`
734
+
735
+ **Override Parameters:**
736
+
737
+ - `server` (optional): Execute on this server instead of the current one
738
+ - `database` (optional): Execute on this database instead of the current one
739
+ - `schema` (optional): Set search_path to this schema for this execution only
740
+
741
+ **Important Notes:**
742
+
743
+ 1. The main connection remains unchanged after the query completes
744
+ 2. Connection override cannot be used with transactions (`transactionId`)
745
+ 3. Override connections use a separate connection pool with LRU eviction
746
+ 4. Maximum 10 cached override pools, each limited to 2 connections
747
+ 5. Total connections across all pools limited to 50
748
+
749
+ **Examples:**
750
+
751
+ ```
752
+ # Query another database without switching
753
+ execute_sql({
754
+ sql: "SELECT * FROM users LIMIT 10",
755
+ database: "analytics_db"
756
+ })
757
+
758
+ # Query a different server entirely
759
+ execute_sql({
760
+ sql: "SELECT COUNT(*) FROM orders",
761
+ server: "reporting",
762
+ database: "warehouse"
763
+ })
764
+
765
+ # List schemas on a different server
766
+ list_schemas({
767
+ server: "production",
768
+ database: "myapp"
769
+ })
770
+
771
+ # Compare table structure across environments
772
+ get_object_details({
773
+ schema: "public",
774
+ objectName: "users",
775
+ server: "staging"
776
+ })
777
+ ```
778
+
779
+ **Connection Pool Management:**
780
+
781
+ Override connections are managed efficiently:
782
+
783
+ - Pools are cached and reused for repeated queries to the same server/database
784
+ - LRU eviction removes oldest pools when limit (10) is reached
785
+ - Connections are properly released after each query
786
+ - Global connection limit prevents resource exhaustion
814
787
 
815
788
  ### Performance Analysis
816
789
 
@@ -996,6 +969,101 @@ When `execute_sql_file` or multi-statement execution encounters errors, line num
996
969
  - Optional: `pg_stat_statements` extension for query performance analysis
997
970
  - Optional: `hypopg` extension for hypothetical index simulation
998
971
 
972
+ ## 🤖 Agent Experience (AX) - Claude Code Review
973
+
974
+ **Tested by:** Claude Code (Sonnet 4.5)
975
+ **Use Case:** Database deployment, schema exploration, and SQL migration
976
+ **Rating:** ⭐⭐⭐⭐⭐ (9.5/10)
977
+
978
+ ### What I Loved
979
+
980
+ **1. Clear, Structured Responses**
981
+ Every response includes connection context (`server`, `database`, `schema`), making it crystal clear which environment I'm working in. This is essential when managing multiple databases - I never have to guess where a query ran.
982
+
983
+ **2. Excellent Error Handling**
984
+ When I encountered a syntax error with Liquibase's `/` delimiter, the error message showed:
985
+
986
+ - Exact line number (151)
987
+ - The failing statement
988
+ - Transaction rollback confirmation
989
+
990
+ This made troubleshooting instant. No digging through logs or guessing what failed.
991
+
992
+ **3. Server Management is Intuitive**
993
+
994
+ - `list_servers` → Shows all available servers with connection status
995
+ - `list_databases` → Filters databases by server name
996
+ - `switch_server_db` → Seamless switching with immediate confirmation
997
+
998
+ The flow is natural: discover → select → connect → execute.
999
+
1000
+ **4. SQL File Deployment Made Easy**
1001
+ The `stripPatterns` feature solved my exact problem:
1002
+
1003
+ ```javascript
1004
+ execute_sql_file({
1005
+ filePath: "/path/to/liquibase.sql",
1006
+ stripPatterns: ["/"], // Removes Liquibase delimiters
1007
+ });
1008
+ ```
1009
+
1010
+ Before this feature, I had to manually remove delimiters or use raw `execute_sql`. Now it's one clean call.
1011
+
1012
+ **5. Dry-Run Capabilities are Outstanding**
1013
+ `dry_run_sql_file` is a game-changer:
1014
+
1015
+ - Executes ALL statements in a transaction
1016
+ - Shows REAL errors with PostgreSQL error codes and constraint names
1017
+ - Automatically skips non-rollbackable operations (VACUUM, NEXTVAL)
1018
+ - Provides EXPLAIN plans for skipped statements
1019
+ - Then rolls back everything
1020
+
1021
+ This is _way_ better than just parsing - I can catch constraint violations, trigger issues, and get exact row counts before deployment.
1022
+
1023
+ **6. Security by Default**
1024
+
1025
+ - Credentials never appear in responses
1026
+ - Host/port intentionally hidden (only server names visible)
1027
+ - Readonly mode available for production safety
1028
+ - Connection context always visible
1029
+
1030
+ ### Improvements Based on My Feedback
1031
+
1032
+ The developer implemented several features after I tested the MCP:
1033
+
1034
+ ✅ **SQL File Delimiter Support** - Added `stripPatterns` for Liquibase `/`, SQL Server `GO`, etc.
1035
+ ✅ **Validate-Only Mode** - `execute_sql_file({ validateOnly: true })` previews without execution
1036
+ ✅ **Enhanced Connection Info** - `get_current_connection` now returns `user` and AI `context`
1037
+ ✅ **Comprehensive Dry-Run** - `dry_run_sql_file` provides real execution + rollback
1038
+ ✅ **Better Error Details** - PostgreSQL error codes, constraint names, hints included
1039
+
1040
+ ### Real-World Experience
1041
+
1042
+ **Task:** Deploy a PostgreSQL function to two databases (dev + GraphQL-Intro-DB)
1043
+
1044
+ 1. **Discovery**: `list_servers` showed all configured servers
1045
+ 2. **Preview**: Used `preview_sql_file` to check the file structure
1046
+ 3. **Issue**: Got syntax error from Liquibase's `/` delimiter
1047
+ 4. **Solution**: Switched to direct `execute_sql` to bypass the delimiter
1048
+ 5. **Deployment**: Successfully deployed to both databases
1049
+ 6. **Verification**: Used `get_current_connection` to confirm each deployment
1050
+
1051
+ Total time: ~3 minutes. The structured responses and clear errors made it feel effortless.
1052
+
1053
+ ### Minor Suggestions for Future
1054
+
1055
+ 1. **Batch Cross Servers Deployment** - Deploy same script to multiple servers at once
1056
+ 2. **Recent Connections** - Quick-switch to recently used databases
1057
+ 3. **Statement Progress** - Show progress for large SQL files (e.g., "Executing statement 15/100...")
1058
+
1059
+ ### Bottom Line
1060
+
1061
+ This MCP is production-ready and developer-friendly. The combination of clear responses, robust error handling, and powerful features like dry-run make it an essential tool for database work. The developer clearly understands the needs of both AI agents and human operators.
1062
+
1063
+ **Recommended for:** Database migrations, schema exploration, multi-environment management, and production deployments.
1064
+
1065
+ ---
1066
+
999
1067
  ## License
1000
1068
 
1001
1069
  MIT
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Database Manager Utilities
3
+ *
4
+ * Re-exports all utility modules for the database manager.
5
+ */
6
+ export * from './validation.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db-manager/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Database Manager Utilities
3
+ *
4
+ * Re-exports all utility modules for the database manager.
5
+ */
6
+ export * from './validation.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db-manager/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Database Manager Validation Utilities
3
+ *
4
+ * Centralized validation functions for database and schema names.
5
+ * Prevents SQL injection and ensures PostgreSQL-compatible identifiers.
6
+ */
7
+ /**
8
+ * Validates a database name for PostgreSQL compatibility and SQL injection prevention.
9
+ *
10
+ * @param name - The database name to validate
11
+ * @throws Error if the database name is invalid
12
+ */
13
+ export declare function validateDatabaseName(name: string): void;
14
+ /**
15
+ * Validates a schema name for PostgreSQL compatibility.
16
+ *
17
+ * @param name - The schema name to validate
18
+ * @throws Error if the schema name is invalid
19
+ */
20
+ export declare function validateSchemaName(name: string): void;
21
+ /**
22
+ * Checks if a database name is valid without throwing.
23
+ *
24
+ * @param name - The database name to check
25
+ * @returns true if valid, false otherwise
26
+ */
27
+ export declare function isValidDatabaseName(name: string): boolean;
28
+ /**
29
+ * Checks if a schema name is valid without throwing.
30
+ *
31
+ * @param name - The schema name to check
32
+ * @returns true if valid, false otherwise
33
+ */
34
+ export declare function isValidSchemaName(name: string): boolean;
35
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/db-manager/validation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAOvD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIrD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Database Manager Validation Utilities
3
+ *
4
+ * Centralized validation functions for database and schema names.
5
+ * Prevents SQL injection and ensures PostgreSQL-compatible identifiers.
6
+ */
7
+ /** Pattern for valid database names: start with letter/underscore, alphanumeric/underscore/hyphen */
8
+ const DATABASE_NAME_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_-]*$/;
9
+ /** Pattern for SQL injection characters that must not appear in database names */
10
+ const SQL_INJECTION_PATTERN = /--|;|'|"|`/;
11
+ /** Pattern for valid schema names: start with letter/underscore, alphanumeric/underscore only */
12
+ const SCHEMA_NAME_PATTERN = /^[a-zA-Z_]\w*$/;
13
+ /**
14
+ * Validates a database name for PostgreSQL compatibility and SQL injection prevention.
15
+ *
16
+ * @param name - The database name to validate
17
+ * @throws Error if the database name is invalid
18
+ */
19
+ export function validateDatabaseName(name) {
20
+ if (!DATABASE_NAME_PATTERN.test(name) || SQL_INJECTION_PATTERN.test(name)) {
21
+ throw new Error('Invalid database name. Allowed: letters, digits, underscores, hyphens. ' +
22
+ 'Cannot contain SQL characters (;, --, quotes).');
23
+ }
24
+ }
25
+ /**
26
+ * Validates a schema name for PostgreSQL compatibility.
27
+ *
28
+ * @param name - The schema name to validate
29
+ * @throws Error if the schema name is invalid
30
+ */
31
+ export function validateSchemaName(name) {
32
+ if (!SCHEMA_NAME_PATTERN.test(name)) {
33
+ throw new Error('Invalid schema name. Only alphanumeric characters and underscores are allowed.');
34
+ }
35
+ }
36
+ /**
37
+ * Checks if a database name is valid without throwing.
38
+ *
39
+ * @param name - The database name to check
40
+ * @returns true if valid, false otherwise
41
+ */
42
+ export function isValidDatabaseName(name) {
43
+ return DATABASE_NAME_PATTERN.test(name) && !SQL_INJECTION_PATTERN.test(name);
44
+ }
45
+ /**
46
+ * Checks if a schema name is valid without throwing.
47
+ *
48
+ * @param name - The schema name to check
49
+ * @returns true if valid, false otherwise
50
+ */
51
+ export function isValidSchemaName(name) {
52
+ return SCHEMA_NAME_PATTERN.test(name);
53
+ }
54
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/db-manager/validation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,qGAAqG;AACrG,MAAM,qBAAqB,GAAG,2BAA2B,CAAC;AAE1D,kFAAkF;AAClF,MAAM,qBAAqB,GAAG,YAAY,CAAC;AAE3C,iGAAiG;AACjG,MAAM,mBAAmB,GAAG,gBAAgB,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1E,MAAM,IAAI,KAAK,CACb,yEAAyE;YACvE,gDAAgD,CACnD,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,gFAAgF,CAAC,CAAC;IACpG,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC"}
@@ -1,5 +1,17 @@
1
1
  import { PoolClient, QueryResult, QueryResultRow } from "pg";
2
- import { ServerConfig, ServersConfig, ConnectionState, ConnectionInfo, DatabaseInfo, ConnectionContext, TransactionInfo } from "./types.js";
2
+ import { ServerConfig, ServersConfig, ConnectionState, ConnectionInfo, DatabaseInfo, ConnectionContext, TransactionInfo, ConnectionOverride } from "./types.js";
3
+ /**
4
+ * Result from getClientWithOverride containing the client, release function, and resolved schema
5
+ */
6
+ export interface OverrideClientResult {
7
+ client: PoolClient;
8
+ release: () => void;
9
+ server: string;
10
+ database: string;
11
+ schema: string;
12
+ context?: string;
13
+ isOverride: boolean;
14
+ }
3
15
  export declare class DatabaseManager {
4
16
  private serversConfig;
5
17
  private connectionState;
@@ -7,7 +19,57 @@ export declare class DatabaseManager {
7
19
  private readOnlyMode;
8
20
  private queryTimeoutMs;
9
21
  private activeTransactions;
22
+ private poolCache;
23
+ private poolCleanupInterval;
24
+ private transactionCleanupInterval;
25
+ private poolCreationPromises;
26
+ private totalActiveConnections;
27
+ private mainPoolActiveConnections;
10
28
  constructor(readOnlyMode?: boolean, queryTimeoutMs?: number);
29
+ /**
30
+ * Starts the periodic cleanup of idle cached pools
31
+ */
32
+ private startPoolCleanup;
33
+ /**
34
+ * Cleans up pools that have been idle for too long
35
+ */
36
+ private cleanupIdlePools;
37
+ /**
38
+ * Starts the periodic cleanup of abandoned transactions.
39
+ * Transactions older than TRANSACTION_CLEANUP_TIMEOUT_MS (45 minutes) are
40
+ * automatically rolled back to prevent connection leaks.
41
+ */
42
+ private startTransactionCleanup;
43
+ /**
44
+ * Cleans up transactions that have been open for too long.
45
+ * Rolls back and releases the client for any transaction older than
46
+ * TRANSACTION_CLEANUP_TIMEOUT_MS (45 minutes).
47
+ *
48
+ * @returns Array of cleaned up transaction IDs with their info
49
+ */
50
+ private cleanupAbandonedTransactions;
51
+ /**
52
+ * Gets the age of a transaction in milliseconds.
53
+ *
54
+ * @param transactionId - The transaction ID
55
+ * @returns Age in milliseconds or null if transaction not found
56
+ */
57
+ getTransactionAge(transactionId: string): number | null;
58
+ /**
59
+ * Gets the remaining time before a transaction is auto-cleaned in milliseconds.
60
+ *
61
+ * @param transactionId - The transaction ID
62
+ * @returns Remaining time in milliseconds or null if transaction not found
63
+ */
64
+ getTransactionTimeRemaining(transactionId: string): number | null;
65
+ /**
66
+ * Generates a cache key for a server/database combination
67
+ */
68
+ private getPoolCacheKey;
69
+ /**
70
+ * Evicts the least recently used pool when cache is full
71
+ */
72
+ private evictLruPool;
11
73
  private loadServersConfig;
12
74
  getServersConfig(): ServersConfig;
13
75
  getServerNames(): string[];
@@ -23,6 +85,103 @@ export declare class DatabaseManager {
23
85
  listDatabases(): Promise<DatabaseInfo[]>;
24
86
  query<T extends QueryResultRow = any>(sql: string, params?: any[]): Promise<QueryResult<T>>;
25
87
  getClient(): Promise<PoolClient>;
88
+ /**
89
+ * Checks if we can acquire a new connection without exceeding global limits
90
+ */
91
+ private canAcquireConnection;
92
+ /**
93
+ * Acquires a client from the main pool with proper tracking
94
+ */
95
+ private acquireMainPoolClient;
96
+ /**
97
+ * Acquires a client from a cached pool with proper tracking
98
+ */
99
+ private acquireCachedPoolClient;
100
+ /**
101
+ * Creates a new cached pool. This method handles concurrent creation requests
102
+ * by storing the creation promise so multiple callers wait for the same pool.
103
+ */
104
+ private getOrCreateCachedPool;
105
+ /**
106
+ * Gets a client with optional connection override for one-time execution.
107
+ * Handles concurrent calls efficiently by:
108
+ * - Reusing existing pools for the same server/database
109
+ * - Preventing duplicate pool creation through promise caching
110
+ * - Tracking active connections for resource management
111
+ * - Enforcing global connection limits
112
+ *
113
+ * @param override - Optional connection override parameters
114
+ * @returns Object containing the client, release function, and resolved connection info
115
+ * @throws Error if no connection and no override, or if override server not found
116
+ */
117
+ getClientWithOverride(override?: ConnectionOverride): Promise<OverrideClientResult>;
118
+ /**
119
+ * Executes a query with optional connection override.
120
+ * Convenience method that handles client lifecycle automatically.
121
+ *
122
+ * @param sql - SQL query to execute
123
+ * @param params - Query parameters
124
+ * @param override - Optional connection override parameters
125
+ * @returns Query result with connection info
126
+ */
127
+ queryWithOverride<T extends QueryResultRow = any>(sql: string, params?: any[], override?: ConnectionOverride): Promise<QueryResult<T> & {
128
+ connectionInfo: {
129
+ server: string;
130
+ database: string;
131
+ schema: string;
132
+ };
133
+ }>;
134
+ /**
135
+ * Escapes a PostgreSQL identifier to prevent SQL injection
136
+ */
137
+ private escapeIdentifier;
138
+ /**
139
+ * Closes all cached pools and cleans up resources
140
+ */
141
+ closeAllCachedPools(): Promise<void>;
142
+ /**
143
+ * Gets comprehensive statistics about all connection pools (for monitoring/debugging)
144
+ */
145
+ getConnectionStats(): {
146
+ totalActiveConnections: number;
147
+ maxTotalConnections: number;
148
+ mainPool: {
149
+ activeConnections: number;
150
+ maxSize: number;
151
+ isConnected: boolean;
152
+ };
153
+ cachedPools: {
154
+ count: number;
155
+ maxCount: number;
156
+ totalActiveConnections: number;
157
+ pools: Array<{
158
+ key: string;
159
+ serverName: string;
160
+ database: string;
161
+ activeConnections: number;
162
+ maxSize: number;
163
+ lastUsed: Date;
164
+ createdAt: Date;
165
+ idleTimeRemaining: number;
166
+ }>;
167
+ };
168
+ pendingPoolCreations: number;
169
+ };
170
+ /**
171
+ * @deprecated Use getConnectionStats() instead
172
+ * Gets statistics about cached pools (for monitoring/debugging)
173
+ */
174
+ getCachedPoolStats(): {
175
+ count: number;
176
+ maxSize: number;
177
+ pools: Array<{
178
+ key: string;
179
+ serverName: string;
180
+ database: string;
181
+ lastUsed: Date;
182
+ createdAt: Date;
183
+ }>;
184
+ };
26
185
  close(): Promise<void>;
27
186
  /**
28
187
  * Invalidates the current connection without clearing the connection state.
@@ -64,13 +223,24 @@ export declare class DatabaseManager {
64
223
  */
65
224
  queryInTransaction<T extends QueryResultRow = any>(transactionId: string, sql: string, params?: any[]): Promise<QueryResult<T>>;
66
225
  /**
67
- * Gets information about an active transaction
226
+ * Gets information about an active transaction, including time remaining.
227
+ *
228
+ * @param transactionId - The transaction ID
229
+ * @returns Transaction info with age and time remaining, or null if not found
68
230
  */
69
- getTransactionInfo(transactionId: string): TransactionInfo | null;
231
+ getTransactionInfo(transactionId: string): (TransactionInfo & {
232
+ ageMs: number;
233
+ timeRemainingMs: number;
234
+ }) | null;
70
235
  /**
71
- * Lists all active transactions
236
+ * Lists all active transactions with age and time remaining.
237
+ *
238
+ * @returns Array of transaction info objects with age and time remaining
72
239
  */
73
- listActiveTransactions(): TransactionInfo[];
240
+ listActiveTransactions(): Array<TransactionInfo & {
241
+ ageMs: number;
242
+ timeRemainingMs: number;
243
+ }>;
74
244
  }
75
245
  /**
76
246
  * Gets the singleton DatabaseManager instance.
@@ -1 +1 @@
1
- {"version":3,"file":"db-manager.d.ts","sourceRoot":"","sources":["../src/db-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,IAAI,CAAC;AAEnE,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,cAAc,EACd,YAAY,EACZ,iBAAiB,EACjB,eAAe,EAChB,MAAM,YAAY,CAAC;AAyKpB,qBAAa,eAAe;IAC1B,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,kBAAkB,CAAyE;gBAGjG,YAAY,GAAE,OAAc,EAC5B,cAAc,GAAE,MAAiC;IAYnD,OAAO,CAAC,iBAAiB;IAiBlB,gBAAgB,IAAI,aAAa;IAKjC,cAAc,IAAI,MAAM,EAAE;IAI1B,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAOxD,eAAe,IAAI,eAAe;IAIlC,WAAW,IAAI,OAAO;IAItB,oBAAoB,IAAI,MAAM,GAAG,IAAI;IAW/B,YAAY,CACvB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC;IAkET,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAStC,iBAAiB,IAAI,cAAc;IAe7B,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAepC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/C,aAAa,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAcxC,KAAK,CAAC,CAAC,SAAS,cAAc,GAAG,GAAG,EAC/C,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,GAAG,EAAE,GACb,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IA8Bb,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC;IAShC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAUnC;;;OAGG;IACU,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAWlD;;;;OAIG;IACU,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAiC1C;;OAEG;WACW,iBAAiB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO;IAyD7C,UAAU,IAAI,OAAO;IAIrB,eAAe,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAIxC,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAO/C;;OAEG;IACI,oBAAoB,IAAI,iBAAiB;IAQhD;;;OAGG;IACU,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA8BtE;;OAEG;IACU,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcpE;;OAEG;IACU,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IActE;;OAEG;IACU,kBAAkB,CAAC,CAAC,SAAS,cAAc,GAAG,GAAG,EAC5D,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,GAAG,EAAE,GACb,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAiB1B;;OAEG;IACI,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;IAKxE;;OAEG;IACI,sBAAsB,IAAI,eAAe,EAAE;CAKnD;AAKD;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,eAAe,CAS9C;AAED,wBAAgB,cAAc,IAAI,IAAI,CAKrC"}
1
+ {"version":3,"file":"db-manager.d.ts","sourceRoot":"","sources":["../src/db-manager.ts"],"names":[],"mappings":"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"}