@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.
Files changed (96) hide show
  1. package/README.md +186 -10
  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 +1 -0
  24. package/dist/tools/server-tools.d.ts.map +1 -1
  25. package/dist/tools/server-tools.js +10 -6
  26. package/dist/tools/server-tools.js.map +1 -1
  27. package/dist/tools/sql/utils/connection-utils.d.ts +79 -0
  28. package/dist/tools/sql/utils/connection-utils.d.ts.map +1 -0
  29. package/dist/tools/sql/utils/connection-utils.js +129 -0
  30. package/dist/tools/sql/utils/connection-utils.js.map +1 -0
  31. package/dist/tools/sql/utils/constants.d.ts +55 -0
  32. package/dist/tools/sql/utils/constants.d.ts.map +1 -0
  33. package/dist/tools/sql/utils/constants.js +55 -0
  34. package/dist/tools/sql/utils/constants.js.map +1 -0
  35. package/dist/tools/sql/utils/dry-run-utils.d.ts +31 -0
  36. package/dist/tools/sql/utils/dry-run-utils.d.ts.map +1 -0
  37. package/dist/tools/sql/utils/dry-run-utils.js +173 -0
  38. package/dist/tools/sql/utils/dry-run-utils.js.map +1 -0
  39. package/dist/tools/sql/utils/file-handler.d.ts +57 -0
  40. package/dist/tools/sql/utils/file-handler.d.ts.map +1 -0
  41. package/dist/tools/sql/utils/file-handler.js +150 -0
  42. package/dist/tools/sql/utils/file-handler.js.map +1 -0
  43. package/dist/tools/sql/utils/index.d.ts +12 -0
  44. package/dist/tools/sql/utils/index.d.ts.map +1 -0
  45. package/dist/tools/sql/utils/index.js +12 -0
  46. package/dist/tools/sql/utils/index.js.map +1 -0
  47. package/dist/tools/sql/utils/result-formatter.d.ts +94 -0
  48. package/dist/tools/sql/utils/result-formatter.d.ts.map +1 -0
  49. package/dist/tools/sql/utils/result-formatter.js +154 -0
  50. package/dist/tools/sql/utils/result-formatter.js.map +1 -0
  51. package/dist/tools/sql/utils/sql-parser.d.ts +125 -0
  52. package/dist/tools/sql/utils/sql-parser.d.ts.map +1 -0
  53. package/dist/tools/sql/utils/sql-parser.js +468 -0
  54. package/dist/tools/sql/utils/sql-parser.js.map +1 -0
  55. package/dist/tools/sql-tools.d.ts +21 -0
  56. package/dist/tools/sql-tools.d.ts.map +1 -1
  57. package/dist/tools/sql-tools.js +383 -532
  58. package/dist/tools/sql-tools.js.map +1 -1
  59. package/dist/types.d.ts +38 -0
  60. package/dist/types.d.ts.map +1 -1
  61. package/dist/utils/retry.d.ts +1 -1
  62. package/dist/utils/retry.d.ts.map +1 -1
  63. package/dist/utils/retry.js.map +1 -1
  64. package/dist/utils/validation.d.ts +45 -9
  65. package/dist/utils/validation.d.ts.map +1 -1
  66. package/dist/utils/validation.js +335 -72
  67. package/dist/utils/validation.js.map +1 -1
  68. package/package.json +9 -2
  69. package/dist/__tests__/analysis-tools.test.d.ts +0 -2
  70. package/dist/__tests__/analysis-tools.test.d.ts.map +0 -1
  71. package/dist/__tests__/analysis-tools.test.js +0 -294
  72. package/dist/__tests__/analysis-tools.test.js.map +0 -1
  73. package/dist/__tests__/db-manager.test.d.ts +0 -2
  74. package/dist/__tests__/db-manager.test.d.ts.map +0 -1
  75. package/dist/__tests__/db-manager.test.js +0 -410
  76. package/dist/__tests__/db-manager.test.js.map +0 -1
  77. package/dist/__tests__/mcp-server.test.d.ts +0 -13
  78. package/dist/__tests__/mcp-server.test.d.ts.map +0 -1
  79. package/dist/__tests__/mcp-server.test.js +0 -146
  80. package/dist/__tests__/mcp-server.test.js.map +0 -1
  81. package/dist/__tests__/schema-tools.test.d.ts +0 -2
  82. package/dist/__tests__/schema-tools.test.d.ts.map +0 -1
  83. package/dist/__tests__/schema-tools.test.js +0 -171
  84. package/dist/__tests__/schema-tools.test.js.map +0 -1
  85. package/dist/__tests__/server-tools.test.d.ts +0 -2
  86. package/dist/__tests__/server-tools.test.d.ts.map +0 -1
  87. package/dist/__tests__/server-tools.test.js +0 -113
  88. package/dist/__tests__/server-tools.test.js.map +0 -1
  89. package/dist/__tests__/sql-tools.test.d.ts +0 -2
  90. package/dist/__tests__/sql-tools.test.d.ts.map +0 -1
  91. package/dist/__tests__/sql-tools.test.js +0 -1912
  92. package/dist/__tests__/sql-tools.test.js.map +0 -1
  93. package/dist/__tests__/validation.test.d.ts +0 -2
  94. package/dist/__tests__/validation.test.d.ts.map +0 -1
  95. package/dist/__tests__/validation.test.js +0 -203
  96. package/dist/__tests__/validation.test.js.map +0 -1
@@ -1,24 +1,168 @@
1
+ import { MAX_SQL_LENGTH_FOR_REGEX } from '../tools/sql/utils/constants.js';
2
+ /** Maximum identifier length in PostgreSQL */
3
+ const MAX_IDENTIFIER_LENGTH = 63;
4
+ /** Pattern for valid unquoted PostgreSQL identifier part */
5
+ const UNQUOTED_IDENTIFIER_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_$]*$/;
6
+ /** Pattern for quoted identifier content (allows Unicode and most characters) */
7
+ // Using [^"]|"" instead of [^"]+|"" to avoid potential ReDoS from nested quantifiers
8
+ const QUOTED_IDENTIFIER_PATTERN = /^"(?:[^"]|"")*"$/;
9
+ /** SQL injection patterns that should never appear in identifiers */
10
+ const SQL_INJECTION_PATTERNS = [
11
+ /;/, // Statement terminator
12
+ /--/, // Line comment start
13
+ /\/\*/, // Block comment start
14
+ /\*\//, // Block comment end
15
+ ];
16
+ /**
17
+ * Validates a single PostgreSQL identifier part (without schema).
18
+ * Supports both unquoted and quoted identifiers.
19
+ *
20
+ * @param part - The identifier part to validate
21
+ * @param fieldName - Field name for error messages
22
+ * @returns The validated identifier part
23
+ * @throws Error if the identifier is invalid
24
+ */
25
+ function validateIdentifierPart(part, fieldName) {
26
+ if (!part || typeof part !== 'string') {
27
+ throw new Error(`${fieldName} is required and must be a string`);
28
+ }
29
+ // Check for SQL injection patterns
30
+ for (const pattern of SQL_INJECTION_PATTERNS) {
31
+ if (pattern.test(part)) {
32
+ throw new Error(`${fieldName} contains potentially dangerous SQL characters`);
33
+ }
34
+ }
35
+ // Handle quoted identifiers (allow Unicode)
36
+ if (part.startsWith('"') && part.endsWith('"')) {
37
+ if (!QUOTED_IDENTIFIER_PATTERN.test(part)) {
38
+ throw new Error(`${fieldName} has invalid quoted identifier syntax. Use "" to escape internal quotes.`);
39
+ }
40
+ // Extract content without quotes for length check
41
+ const content = part.slice(1, -1).replace(/""/g, '"');
42
+ if (content.length > MAX_IDENTIFIER_LENGTH) {
43
+ throw new Error(`${fieldName} must be ${MAX_IDENTIFIER_LENGTH} characters or less (excluding quotes)`);
44
+ }
45
+ return part;
46
+ }
47
+ // Unquoted identifier validation
48
+ if (part.length > MAX_IDENTIFIER_LENGTH) {
49
+ throw new Error(`${fieldName} must be ${MAX_IDENTIFIER_LENGTH} characters or less`);
50
+ }
51
+ if (!UNQUOTED_IDENTIFIER_PATTERN.test(part)) {
52
+ throw new Error(`${fieldName} contains invalid characters. Only letters, numbers, underscores, and dollar signs are allowed, ` +
53
+ `and it must start with a letter or underscore. Use double quotes for special characters or Unicode.`);
54
+ }
55
+ return part;
56
+ }
57
+ /**
58
+ * Gets the appropriate field name for a part in a qualified identifier.
59
+ * Extracted to avoid nested ternary operators.
60
+ *
61
+ * @param totalParts - Total number of parts in the identifier
62
+ * @param partIndex - Index of the current part (0-based)
63
+ * @param fieldName - Base field name for error messages
64
+ * @returns The appropriate part name for error messages
65
+ */
66
+ function getPartName(totalParts, partIndex, fieldName) {
67
+ if (totalParts !== 2) {
68
+ return fieldName;
69
+ }
70
+ return partIndex === 0 ? `${fieldName} schema` : `${fieldName} name`;
71
+ }
1
72
  /**
2
73
  * Validates and sanitizes PostgreSQL identifiers (table names, column names, etc.)
3
- * Prevents SQL injection by only allowing valid identifier characters.
74
+ * Supports schema-qualified names (schema.table) and quoted identifiers.
75
+ * Prevents SQL injection by validating identifier characters.
76
+ *
77
+ * @param identifier - The identifier to validate (e.g., "users", "public.users", '"My Table"')
78
+ * @param fieldName - Field name for error messages
79
+ * @param allowQualified - Whether to allow schema-qualified names (default: true)
80
+ * @returns The validated identifier
81
+ * @throws Error if the identifier is invalid
82
+ *
83
+ * @example
84
+ * validateIdentifier('users', 'table') // 'users'
85
+ * validateIdentifier('public.users', 'table') // 'public.users'
86
+ * validateIdentifier('"My Table"', 'table') // '"My Table"'
87
+ * validateIdentifier('my_schema."Table"', 'table') // 'my_schema."Table"'
4
88
  */
5
- export function validateIdentifier(identifier, fieldName) {
89
+ export function validateIdentifier(identifier, fieldName, allowQualified = true) {
6
90
  if (!identifier || typeof identifier !== 'string') {
7
91
  throw new Error(`${fieldName} is required and must be a string`);
8
92
  }
9
- // PostgreSQL identifier rules:
10
- // - Must start with a letter (a-z) or underscore
11
- // - Can contain letters, digits, underscores, and dollar signs
12
- // - Maximum 63 characters
13
- // We're being more restrictive for security
14
- const validIdentifierRegex = /^[a-zA-Z_][a-zA-Z0-9_$]*$/;
15
- if (identifier.length > 63) {
16
- throw new Error(`${fieldName} must be 63 characters or less`);
93
+ const trimmed = identifier.trim();
94
+ // Split by unquoted dots (respecting quoted identifiers)
95
+ const parts = splitQualifiedIdentifier(trimmed);
96
+ if (parts.length === 0) {
97
+ throw new Error(`${fieldName} is required and must be a string`);
98
+ }
99
+ if (parts.length > 2) {
100
+ throw new Error(`${fieldName} has too many parts. Maximum format: schema.object`);
101
+ }
102
+ if (parts.length === 2 && !allowQualified) {
103
+ throw new Error(`${fieldName} cannot be schema-qualified. Provide just the object name.`);
104
+ }
105
+ // Validate each part
106
+ for (let i = 0; i < parts.length; i++) {
107
+ const partName = getPartName(parts.length, i, fieldName);
108
+ validateIdentifierPart(parts[i], partName);
109
+ }
110
+ return trimmed;
111
+ }
112
+ /**
113
+ * Splits a qualified identifier (e.g., "schema.table" or "schema"."table")
114
+ * into its parts, respecting quoted identifiers.
115
+ *
116
+ * @param identifier - The qualified identifier to split
117
+ * @returns Array of identifier parts
118
+ */
119
+ function splitQualifiedIdentifier(identifier) {
120
+ const parts = [];
121
+ let current = '';
122
+ let inQuotes = false;
123
+ let i = 0;
124
+ while (i < identifier.length) {
125
+ const char = identifier[i];
126
+ if (char === '"') {
127
+ if (inQuotes && identifier[i + 1] === '"') {
128
+ // Escaped quote inside quoted identifier
129
+ current += '""';
130
+ i += 2;
131
+ continue;
132
+ }
133
+ inQuotes = !inQuotes;
134
+ current += char;
135
+ }
136
+ else if (char === '.' && !inQuotes) {
137
+ // Separator found
138
+ if (current.trim()) {
139
+ parts.push(current.trim());
140
+ }
141
+ current = '';
142
+ }
143
+ else {
144
+ current += char;
145
+ }
146
+ i++;
17
147
  }
18
- if (!validIdentifierRegex.test(identifier)) {
19
- throw new Error(`${fieldName} contains invalid characters. Only letters, numbers, underscores, and dollar signs are allowed, and it must start with a letter or underscore.`);
148
+ // Add the last part
149
+ if (current.trim()) {
150
+ parts.push(current.trim());
20
151
  }
21
- return identifier;
152
+ return parts;
153
+ }
154
+ /**
155
+ * Parses a qualified identifier into schema and object name.
156
+ *
157
+ * @param identifier - The identifier to parse (must be pre-validated)
158
+ * @returns Object with schema (optional) and name
159
+ */
160
+ export function parseQualifiedIdentifier(identifier) {
161
+ const parts = splitQualifiedIdentifier(identifier);
162
+ if (parts.length === 2) {
163
+ return { schema: parts[0], name: parts[1] };
164
+ }
165
+ return { name: parts[0] || identifier };
22
166
  }
23
167
  /**
24
168
  * Escapes a PostgreSQL identifier by doubling any internal double quotes
@@ -33,54 +177,126 @@ export function escapeIdentifier(identifier) {
33
177
  return `"${identifier.replace(/"/g, '""')}"`;
34
178
  }
35
179
  /**
36
- * Validates SQL for read-only operations more thoroughly.
37
- * Returns true if the SQL appears to be read-only, false otherwise.
180
+ * Write operations that should be blocked in read-only mode.
181
+ * Organized by category for maintainability.
38
182
  */
39
- export function isReadOnlySql(sql) {
40
- if (!sql || typeof sql !== 'string') {
41
- return { isReadOnly: false, reason: 'SQL is required' };
42
- }
43
- // Normalize: remove comments, extra whitespace
44
- let normalizedSql = sql
45
- // Remove single-line comments
46
- .replace(/--[^\n]*/g, '')
47
- // Remove multi-line comments
48
- .replace(/\/\*[\s\S]*?\*\//g, '')
49
- // Normalize whitespace
50
- .replace(/\s+/g, ' ')
183
+ const WRITE_OPERATIONS = [
184
+ // DML Operations
185
+ 'INSERT',
186
+ 'UPDATE',
187
+ 'DELETE',
188
+ 'MERGE', // SQL:2008 standard MERGE statement
189
+ 'UPSERT', // PostgreSQL UPSERT pattern
190
+ // DDL Operations
191
+ 'DROP',
192
+ 'CREATE',
193
+ 'ALTER',
194
+ 'TRUNCATE',
195
+ 'COMMENT ON', // Modifies metadata
196
+ // Security Operations
197
+ 'GRANT',
198
+ 'REVOKE',
199
+ 'REASSIGN OWNED', // Ownership transfer
200
+ 'SECURITY LABEL', // Security labels
201
+ // Maintenance Operations (with side effects)
202
+ 'COPY', // Can write to files
203
+ 'VACUUM',
204
+ 'REINDEX',
205
+ 'CLUSTER',
206
+ 'ANALYZE', // Modifies statistics (can affect query plans)
207
+ 'REFRESH MATERIALIZED VIEW',
208
+ // Lock Operations
209
+ 'LOCK',
210
+ // Session State Operations
211
+ 'DISCARD',
212
+ 'RESET',
213
+ 'SET ', // Note: space to avoid matching in column names
214
+ 'SET LOCAL',
215
+ 'SET SESSION',
216
+ // Code Execution
217
+ 'DO', // Anonymous code blocks (no trailing space, \b handles boundary)
218
+ 'CALL', // Stored procedures
219
+ 'EXECUTE', // Dynamic SQL execution
220
+ // Transaction Control (shouldn't be in read-only queries)
221
+ 'BEGIN',
222
+ 'COMMIT',
223
+ 'ROLLBACK',
224
+ 'SAVEPOINT',
225
+ 'RELEASE SAVEPOINT',
226
+ // PostgreSQL Extensions
227
+ 'LOAD', // Load shared library
228
+ 'IMPORT FOREIGN SCHEMA',
229
+ 'CREATE SERVER',
230
+ 'CREATE FOREIGN',
231
+ 'NOTIFY', // Send notification
232
+ 'LISTEN', // Subscribe to notifications
233
+ 'UNLISTEN', // Unsubscribe from notifications
234
+ ];
235
+ /**
236
+ * Functions that could have side effects or security implications.
237
+ */
238
+ const DANGEROUS_FUNCTIONS = [
239
+ // Large Object Functions
240
+ 'LO_IMPORT',
241
+ 'LO_EXPORT',
242
+ 'LO_UNLINK',
243
+ 'LO_CREATE',
244
+ 'LO_OPEN',
245
+ 'LO_WRITE',
246
+ 'LO_PUT',
247
+ // File System Functions
248
+ 'PG_READ_FILE',
249
+ 'PG_READ_BINARY_FILE',
250
+ 'PG_WRITE_FILE',
251
+ 'PG_FILE_WRITE',
252
+ 'PG_FILE_UNLINK',
253
+ 'PG_FILE_RENAME',
254
+ // Remote Connection Functions
255
+ 'DBLINK_EXEC',
256
+ 'DBLINK',
257
+ 'DBLINK_CONNECT',
258
+ 'DBLINK_SEND_QUERY',
259
+ // Copy Functions
260
+ 'COPY_TO',
261
+ 'COPY_FROM',
262
+ // System Administration
263
+ 'PG_TERMINATE_BACKEND',
264
+ 'PG_CANCEL_BACKEND',
265
+ 'PG_RELOAD_CONF',
266
+ 'PG_ROTATE_LOGFILE',
267
+ 'PG_SWITCH_WAL',
268
+ 'PG_SWITCH_XLOG',
269
+ // Sequence Functions (modify state even in rollback)
270
+ 'NEXTVAL',
271
+ 'SETVAL',
272
+ 'CURRVAL', // Only dangerous if called after NEXTVAL
273
+ // Advisory Lock Functions (can affect other sessions)
274
+ 'PG_ADVISORY_LOCK',
275
+ 'PG_ADVISORY_UNLOCK',
276
+ 'PG_TRY_ADVISORY_LOCK',
277
+ ];
278
+ /**
279
+ * Normalizes SQL for analysis by removing comments and extra whitespace.
280
+ */
281
+ function normalizeSqlForAnalysis(sql) {
282
+ return sql
283
+ .replace(/--[^\n]*/g, '') // Remove single-line comments
284
+ .replace(/\/\*[\s\S]*?\*\//g, '') // Remove multi-line comments (non-greedy, safe pattern)
285
+ .replace(/\s+/g, ' ') // Normalize whitespace
51
286
  .trim()
52
287
  .toUpperCase();
53
- // Check for write operations at any position (not just start)
54
- const writeOperations = [
55
- 'INSERT',
56
- 'UPDATE',
57
- 'DELETE',
58
- 'DROP',
59
- 'CREATE',
60
- 'ALTER',
61
- 'TRUNCATE',
62
- 'GRANT',
63
- 'REVOKE',
64
- 'COPY',
65
- 'VACUUM',
66
- 'REINDEX',
67
- 'CLUSTER',
68
- 'REFRESH MATERIALIZED VIEW',
69
- 'LOCK',
70
- 'DISCARD',
71
- 'RESET',
72
- 'SET ', // Note: space to avoid matching in column names
73
- 'DO ', // Anonymous code blocks
74
- 'CALL', // Stored procedures
75
- ];
76
- // Check if any write operation appears as a keyword (word boundary check)
77
- for (const op of writeOperations) {
78
- // Check at start or after common statement separators
288
+ }
289
+ /**
290
+ * Checks if SQL contains any write operations.
291
+ * Uses ReDoS-safe patterns with bounded whitespace.
292
+ */
293
+ function checkWriteOperations(normalizedSql) {
294
+ for (const op of WRITE_OPERATIONS) {
295
+ const escapedOp = op.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
79
296
  const patterns = [
80
- new RegExp(`^${op}\\b`), // At start
81
- new RegExp(`\\(\\s*${op}\\b`), // After opening paren (subquery)
82
- new RegExp(`;\\s*${op}\\b`), // After semicolon
83
- new RegExp(`\\bWITH\\b.*\\bAS\\s*\\(\\s*${op}\\b`, 's'), // In CTE
297
+ new RegExp(`^${escapedOp}\\b`), // At start
298
+ new RegExp(`\\(\\s{0,10}${escapedOp}\\b`), // After opening paren
299
+ new RegExp(`;\\s{0,10}${escapedOp}\\b`), // After semicolon
84
300
  ];
85
301
  for (const pattern of patterns) {
86
302
  if (pattern.test(normalizedSql)) {
@@ -88,32 +304,79 @@ export function isReadOnlySql(sql) {
88
304
  }
89
305
  }
90
306
  }
91
- // Check for function calls that could have side effects
92
- const dangerousFunctions = [
93
- 'LO_IMPORT',
94
- 'LO_EXPORT',
95
- 'LO_UNLINK',
96
- 'PG_READ_FILE',
97
- 'PG_READ_BINARY_FILE',
98
- 'PG_WRITE_FILE',
99
- 'DBLINK_EXEC',
100
- 'DBLINK',
101
- ];
102
- for (const func of dangerousFunctions) {
103
- if (new RegExp(`\\b${func}\\s*\\(`).test(normalizedSql)) {
307
+ return null;
308
+ }
309
+ /**
310
+ * Checks for data-modifying CTEs (WITH ... AS (INSERT/UPDATE/DELETE)).
311
+ */
312
+ function checkCteWriteOperations(normalizedSql) {
313
+ if (!/\bWITH\b/.test(normalizedSql)) {
314
+ return null;
315
+ }
316
+ for (const op of ['INSERT', 'UPDATE', 'DELETE', 'MERGE']) {
317
+ if (new RegExp(`\\bAS\\s{0,10}\\(\\s{0,10}${op}\\b`).test(normalizedSql)) {
318
+ return { isReadOnly: false, reason: `Write operation '${op}' in CTE detected` };
319
+ }
320
+ }
321
+ return null;
322
+ }
323
+ /**
324
+ * Checks for dangerous function calls that could have side effects.
325
+ */
326
+ function checkDangerousFunctions(normalizedSql) {
327
+ for (const func of DANGEROUS_FUNCTIONS) {
328
+ const escapedFunc = func.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
329
+ if (new RegExp(`\\b${escapedFunc}\\s{0,10}\\(`).test(normalizedSql)) {
104
330
  return { isReadOnly: false, reason: `Dangerous function '${func}' detected` };
105
331
  }
106
332
  }
333
+ return null;
334
+ }
335
+ /**
336
+ * Validates SQL for read-only operations more thoroughly.
337
+ * Uses ReDoS-safe patterns and comprehensive operation detection.
338
+ *
339
+ * @param sql - The SQL string to validate
340
+ * @returns Object with isReadOnly flag and optional reason
341
+ */
342
+ export function isReadOnlySql(sql) {
343
+ if (!sql || typeof sql !== 'string') {
344
+ return { isReadOnly: false, reason: 'SQL is required' };
345
+ }
346
+ if (sql.length > MAX_SQL_LENGTH_FOR_REGEX) {
347
+ return {
348
+ isReadOnly: false,
349
+ reason: `SQL too large for safe validation (${sql.length} chars, max ${MAX_SQL_LENGTH_FOR_REGEX}). Review manually.`,
350
+ };
351
+ }
352
+ const normalizedSql = normalizeSqlForAnalysis(sql);
353
+ // Check each category of dangerous operations
354
+ const writeCheck = checkWriteOperations(normalizedSql);
355
+ if (writeCheck)
356
+ return writeCheck;
357
+ const cteCheck = checkCteWriteOperations(normalizedSql);
358
+ if (cteCheck)
359
+ return cteCheck;
360
+ const funcCheck = checkDangerousFunctions(normalizedSql);
361
+ if (funcCheck)
362
+ return funcCheck;
107
363
  return { isReadOnly: true };
108
364
  }
109
365
  /**
110
- * Validates that a number is within acceptable bounds.
366
+ * Validates that a value is a positive integer within acceptable bounds.
367
+ *
368
+ * @param value - The value to validate (can be number, string, or undefined/null)
369
+ * @param fieldName - Name of the field for error messages
370
+ * @param min - Minimum allowed value (default: 1)
371
+ * @param max - Maximum allowed value (default: 10000)
372
+ * @returns The validated integer value
373
+ * @throws Error if value is not a valid integer within bounds
111
374
  */
112
375
  export function validatePositiveInteger(value, fieldName, min = 1, max = 10000) {
113
376
  if (value === undefined || value === null) {
114
377
  return min;
115
378
  }
116
- const num = parseInt(value, 10);
379
+ const num = typeof value === 'number' ? value : parseInt(String(value), 10);
117
380
  if (isNaN(num) || num < min || num > max) {
118
381
  throw new Error(`${fieldName} must be an integer between ${min} and ${max}`);
119
382
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAE3E,8CAA8C;AAC9C,MAAM,qBAAqB,GAAG,EAAE,CAAC;AAEjC,4DAA4D;AAC5D,MAAM,2BAA2B,GAAG,2BAA2B,CAAC;AAEhE,iFAAiF;AACjF,qFAAqF;AACrF,MAAM,yBAAyB,GAAG,kBAAkB,CAAC;AAErD,qEAAqE;AACrE,MAAM,sBAAsB,GAAG;IAC7B,GAAG,EAAY,uBAAuB;IACtC,IAAI,EAAW,qBAAqB;IACpC,MAAM,EAAS,sBAAsB;IACrC,MAAM,EAAS,oBAAoB;CACpC,CAAC;AAEF;;;;;;;;GAQG;AACH,SAAS,sBAAsB,CAAC,IAAY,EAAE,SAAiB;IAC7D,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,mCAAmC,CAAC,CAAC;IACnE,CAAC;IAED,mCAAmC;IACnC,KAAK,MAAM,OAAO,IAAI,sBAAsB,EAAE,CAAC;QAC7C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,gDAAgD,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IAED,4CAA4C;IAC5C,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,0EAA0E,CAAC,CAAC;QAC1G,CAAC;QACD,kDAAkD;QAClD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACtD,IAAI,OAAO,CAAC,MAAM,GAAG,qBAAqB,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,YAAY,qBAAqB,wCAAwC,CAAC,CAAC;QACzG,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iCAAiC;IACjC,IAAI,IAAI,CAAC,MAAM,GAAG,qBAAqB,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,YAAY,qBAAqB,qBAAqB,CAAC,CAAC;IACtF,CAAC;IAED,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CACb,GAAG,SAAS,kGAAkG;YAC9G,qGAAqG,CACtG,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAC,UAAkB,EAAE,SAAiB,EAAE,SAAiB;IAC3E,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,OAAO,CAAC;AACvE,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAkB,EAClB,SAAiB,EACjB,iBAA0B,IAAI;IAE9B,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,mCAAmC,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IAElC,yDAAyD;IACzD,MAAM,KAAK,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAEhD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,mCAAmC,CAAC,CAAC;IACnE,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,oDAAoD,CAAC,CAAC;IACpF,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,4DAA4D,CAAC,CAAC;IAC5F,CAAC;IAED,qBAAqB;IACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QACzD,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,wBAAwB,CAAC,UAAkB;IAClD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAE3B,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjB,IAAI,QAAQ,IAAI,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC1C,yCAAyC;gBACzC,OAAO,IAAI,IAAI,CAAC;gBAChB,CAAC,IAAI,CAAC,CAAC;gBACP,SAAS;YACX,CAAC;YACD,QAAQ,GAAG,CAAC,QAAQ,CAAC;YACrB,OAAO,IAAI,IAAI,CAAC;QAClB,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACrC,kBAAkB;YAClB,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBACnB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7B,CAAC;YACD,OAAO,GAAG,EAAE,CAAC;QACf,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,IAAI,CAAC;QAClB,CAAC;QACD,CAAC,EAAE,CAAC;IACN,CAAC;IAED,oBAAoB;IACpB,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,UAAkB;IACzD,MAAM,KAAK,GAAG,wBAAwB,CAAC,UAAU,CAAC,CAAC;IAEnD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9C,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU,EAAE,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,iBAAiB;IACjB,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IAED,uDAAuD;IACvD,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,gBAAgB,GAAsB;IAC1C,iBAAiB;IACjB,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,OAAO,EAAe,oCAAoC;IAC1D,QAAQ,EAAc,4BAA4B;IAClD,iBAAiB;IACjB,MAAM;IACN,QAAQ;IACR,OAAO;IACP,UAAU;IACV,YAAY,EAAU,oBAAoB;IAC1C,sBAAsB;IACtB,OAAO;IACP,QAAQ;IACR,gBAAgB,EAAM,qBAAqB;IAC3C,gBAAgB,EAAM,kBAAkB;IACxC,6CAA6C;IAC7C,MAAM,EAAgB,qBAAqB;IAC3C,QAAQ;IACR,SAAS;IACT,SAAS;IACT,SAAS,EAAa,+CAA+C;IACrE,2BAA2B;IAC3B,kBAAkB;IAClB,MAAM;IACN,2BAA2B;IAC3B,SAAS;IACT,OAAO;IACP,MAAM,EAAgB,gDAAgD;IACtE,WAAW;IACX,aAAa;IACb,iBAAiB;IACjB,IAAI,EAAkB,iEAAiE;IACvF,MAAM,EAAgB,oBAAoB;IAC1C,SAAS,EAAa,wBAAwB;IAC9C,0DAA0D;IAC1D,OAAO;IACP,QAAQ;IACR,UAAU;IACV,WAAW;IACX,mBAAmB;IACnB,wBAAwB;IACxB,MAAM,EAAgB,sBAAsB;IAC5C,uBAAuB;IACvB,eAAe;IACf,gBAAgB;IAChB,QAAQ,EAAc,oBAAoB;IAC1C,QAAQ,EAAc,6BAA6B;IACnD,UAAU,EAAY,iCAAiC;CAC/C,CAAC;AAEX;;GAEG;AACH,MAAM,mBAAmB,GAAsB;IAC7C,yBAAyB;IACzB,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,SAAS;IACT,UAAU;IACV,QAAQ;IACR,wBAAwB;IACxB,cAAc;IACd,qBAAqB;IACrB,eAAe;IACf,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,8BAA8B;IAC9B,aAAa;IACb,QAAQ;IACR,gBAAgB;IAChB,mBAAmB;IACnB,iBAAiB;IACjB,SAAS;IACT,WAAW;IACX,wBAAwB;IACxB,sBAAsB;IACtB,mBAAmB;IACnB,gBAAgB;IAChB,mBAAmB;IACnB,eAAe;IACf,gBAAgB;IAChB,qDAAqD;IACrD,SAAS;IACT,QAAQ;IACR,SAAS,EAAa,yCAAyC;IAC/D,sDAAsD;IACtD,kBAAkB;IAClB,oBAAoB;IACpB,sBAAsB;CACd,CAAC;AAKX;;GAEG;AACH,SAAS,uBAAuB,CAAC,GAAW;IAC1C,OAAO,GAAG;SACP,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAW,8BAA8B;SACjE,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAG,wDAAwD;SAC3F,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAe,uBAAuB;SAC1D,IAAI,EAAE;SACN,WAAW,EAAE,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,SAAS,oBAAoB,CAAC,aAAqB;IACjD,KAAK,MAAM,EAAE,IAAI,gBAAgB,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG;YACf,IAAI,MAAM,CAAC,IAAI,SAAS,KAAK,CAAC,EAAa,WAAW;YACtD,IAAI,MAAM,CAAC,eAAe,SAAS,KAAK,CAAC,EAAE,sBAAsB;YACjE,IAAI,MAAM,CAAC,aAAa,SAAS,KAAK,CAAC,EAAI,kBAAkB;SAC9D,CAAC;QACF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;gBAChC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;YAClF,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAAC,aAAqB;IACpD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,KAAK,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;QACzD,IAAI,IAAI,MAAM,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YACzE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;QAClF,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAAC,aAAqB;IACpD,KAAK,MAAM,IAAI,IAAI,mBAAmB,EAAE,CAAC;QACvC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QAChE,IAAI,IAAI,MAAM,CAAC,MAAM,WAAW,cAAc,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YACpE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,IAAI,YAAY,EAAE,CAAC;QAChF,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC1D,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,GAAG,wBAAwB,EAAE,CAAC;QAC1C,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,MAAM,EAAE,sCAAsC,GAAG,CAAC,MAAM,eAAe,wBAAwB,qBAAqB;SACrH,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAEnD,8CAA8C;IAC9C,MAAM,UAAU,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAAC;IACvD,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAElC,MAAM,QAAQ,GAAG,uBAAuB,CAAC,aAAa,CAAC,CAAC;IACxD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,SAAS,GAAG,uBAAuB,CAAC,aAAa,CAAC,CAAC;IACzD,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAEhC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CACrC,KAAc,EACd,SAAiB,EACjB,MAAc,CAAC,EACf,MAAc,KAAK;IAEnB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,GAAG,CAAC;IACb,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5E,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,+BAA+B,GAAG,QAAQ,GAAG,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACtE,MAAM,UAAU,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IAExD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,uBAAuB,SAAS,sBAAsB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjG,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tejasanik/postgres-mcp-server",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "A Model Context Protocol (MCP) server for PostgreSQL database management and analysis",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,6 +14,8 @@
14
14
  "dev": "ts-node src/index.ts",
15
15
  "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
16
16
  "test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch",
17
+ "lint": "eslint src --ignore-pattern '__tests__'",
18
+ "lint:fix": "eslint src --ignore-pattern '__tests__' --fix",
17
19
  "prepare": "npm run build",
18
20
  "prepublishOnly": "npm run build && npm test"
19
21
  },
@@ -39,9 +41,14 @@
39
41
  "@types/node": "^22.10.2",
40
42
  "@types/pg": "^8.11.10",
41
43
  "@types/uuid": "^10.0.0",
44
+ "@typescript-eslint/eslint-plugin": "^8.51.0",
45
+ "@typescript-eslint/parser": "^8.51.0",
46
+ "eslint": "^9.39.2",
47
+ "eslint-plugin-sonarjs": "^3.0.5",
42
48
  "jest": "^29.7.0",
43
49
  "ts-jest": "^29.2.5",
44
- "typescript": "^5.7.2"
50
+ "typescript": "^5.7.2",
51
+ "typescript-eslint": "^8.51.0"
45
52
  },
46
53
  "engines": {
47
54
  "node": ">=18.0.0"
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=analysis-tools.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"analysis-tools.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/analysis-tools.test.ts"],"names":[],"mappings":""}