@berthojoris/mcp-mysql-server 1.4.15 → 1.5.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.
@@ -0,0 +1,337 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.QueryCache = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ /**
9
+ * Default cache configuration
10
+ */
11
+ const DEFAULT_CONFIG = {
12
+ enabled: true,
13
+ ttlMs: 60000, // 1 minute default TTL
14
+ maxSize: 100, // Maximum 100 cached queries
15
+ maxMemoryMB: 50, // Maximum 50MB memory usage
16
+ };
17
+ /**
18
+ * LRU Query Cache with TTL support
19
+ * Implements an in-memory cache for query results to improve performance
20
+ */
21
+ class QueryCache {
22
+ constructor() {
23
+ this.cache = new Map();
24
+ this.config = { ...DEFAULT_CONFIG };
25
+ this.stats = { totalHits: 0, totalMisses: 0 };
26
+ this.accessOrder = [];
27
+ // Load config from environment if available
28
+ this.loadConfigFromEnv();
29
+ }
30
+ /**
31
+ * Get singleton instance
32
+ */
33
+ static getInstance() {
34
+ if (!QueryCache.instance) {
35
+ QueryCache.instance = new QueryCache();
36
+ }
37
+ return QueryCache.instance;
38
+ }
39
+ /**
40
+ * Load cache configuration from environment variables
41
+ */
42
+ loadConfigFromEnv() {
43
+ if (process.env.CACHE_ENABLED !== undefined) {
44
+ this.config.enabled = process.env.CACHE_ENABLED === "true";
45
+ }
46
+ if (process.env.CACHE_TTL_MS) {
47
+ const ttl = parseInt(process.env.CACHE_TTL_MS, 10);
48
+ if (!isNaN(ttl) && ttl > 0) {
49
+ this.config.ttlMs = ttl;
50
+ }
51
+ }
52
+ if (process.env.CACHE_MAX_SIZE) {
53
+ const maxSize = parseInt(process.env.CACHE_MAX_SIZE, 10);
54
+ if (!isNaN(maxSize) && maxSize > 0) {
55
+ this.config.maxSize = maxSize;
56
+ }
57
+ }
58
+ if (process.env.CACHE_MAX_MEMORY_MB) {
59
+ const maxMemory = parseInt(process.env.CACHE_MAX_MEMORY_MB, 10);
60
+ if (!isNaN(maxMemory) && maxMemory > 0) {
61
+ this.config.maxMemoryMB = maxMemory;
62
+ }
63
+ }
64
+ }
65
+ /**
66
+ * Generate a unique hash for a query and its parameters
67
+ */
68
+ generateHash(sql, params) {
69
+ const normalized = sql.trim().toLowerCase();
70
+ let paramsStr = "";
71
+ if (params) {
72
+ try {
73
+ paramsStr = JSON.stringify(params);
74
+ }
75
+ catch {
76
+ // Handle circular references or non-serializable values
77
+ paramsStr = params
78
+ .map((p) => {
79
+ if (p === null)
80
+ return "null";
81
+ if (p === undefined)
82
+ return "undefined";
83
+ if (typeof p === "object") {
84
+ try {
85
+ return JSON.stringify(p);
86
+ }
87
+ catch {
88
+ return String(p);
89
+ }
90
+ }
91
+ return String(p);
92
+ })
93
+ .join(",");
94
+ }
95
+ }
96
+ const combined = `${normalized}:${paramsStr}`;
97
+ return crypto_1.default.createHash("md5").update(combined).digest("hex");
98
+ }
99
+ /**
100
+ * Check if a query result is cached and valid
101
+ */
102
+ get(sql, params) {
103
+ if (!this.config.enabled) {
104
+ return null;
105
+ }
106
+ const hash = this.generateHash(sql, params);
107
+ const entry = this.cache.get(hash);
108
+ if (!entry) {
109
+ this.stats.totalMisses++;
110
+ return null;
111
+ }
112
+ // Check if entry has expired
113
+ const now = Date.now();
114
+ if (now - entry.timestamp > this.config.ttlMs) {
115
+ this.cache.delete(hash);
116
+ this.removeFromAccessOrder(hash);
117
+ this.stats.totalMisses++;
118
+ return null;
119
+ }
120
+ // Update hit count and access order
121
+ entry.hitCount++;
122
+ this.updateAccessOrder(hash);
123
+ this.stats.totalHits++;
124
+ // Return a deep copy to prevent mutation of cached data
125
+ return {
126
+ ...entry,
127
+ data: JSON.parse(JSON.stringify(entry.data)),
128
+ };
129
+ }
130
+ /**
131
+ * Cache a query result
132
+ */
133
+ set(sql, params, data) {
134
+ if (!this.config.enabled) {
135
+ return;
136
+ }
137
+ // Only cache SELECT queries
138
+ const normalizedSql = sql.trim().toUpperCase();
139
+ if (!normalizedSql.startsWith("SELECT")) {
140
+ return;
141
+ }
142
+ const hash = this.generateHash(sql, params);
143
+ // Check if we need to evict entries
144
+ this.evictIfNeeded();
145
+ const entry = {
146
+ data,
147
+ timestamp: Date.now(),
148
+ hitCount: 0,
149
+ queryHash: hash,
150
+ sql,
151
+ params,
152
+ };
153
+ this.cache.set(hash, entry);
154
+ this.updateAccessOrder(hash);
155
+ }
156
+ /**
157
+ * Invalidate cache entries matching a pattern
158
+ * Used when data is modified (INSERT, UPDATE, DELETE)
159
+ */
160
+ invalidate(pattern) {
161
+ let invalidatedCount = 0;
162
+ if (!pattern) {
163
+ // Clear all cache
164
+ invalidatedCount = this.cache.size;
165
+ this.cache.clear();
166
+ this.accessOrder = [];
167
+ return invalidatedCount;
168
+ }
169
+ const regex = typeof pattern === "string" ? new RegExp(pattern, "i") : pattern;
170
+ for (const [hash, entry] of this.cache.entries()) {
171
+ if (regex.test(entry.sql)) {
172
+ this.cache.delete(hash);
173
+ this.removeFromAccessOrder(hash);
174
+ invalidatedCount++;
175
+ }
176
+ }
177
+ return invalidatedCount;
178
+ }
179
+ /**
180
+ * Escape special regex characters in a string
181
+ */
182
+ escapeRegex(str) {
183
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
184
+ }
185
+ /**
186
+ * Invalidate cache entries related to a specific table
187
+ */
188
+ invalidateTable(tableName) {
189
+ // Escape special regex characters in table name to prevent regex injection
190
+ const escapedTableName = this.escapeRegex(tableName);
191
+ // Match table name in various SQL patterns
192
+ const patterns = [
193
+ new RegExp(`\\bFROM\\s+[\`"']?${escapedTableName}[\`"']?\\b`, "i"),
194
+ new RegExp(`\\bJOIN\\s+[\`"']?${escapedTableName}[\`"']?\\b`, "i"),
195
+ new RegExp(`\\b${escapedTableName}\\b`, "i"),
196
+ ];
197
+ let invalidatedCount = 0;
198
+ for (const [hash, entry] of this.cache.entries()) {
199
+ for (const pattern of patterns) {
200
+ if (pattern.test(entry.sql)) {
201
+ this.cache.delete(hash);
202
+ this.removeFromAccessOrder(hash);
203
+ invalidatedCount++;
204
+ break;
205
+ }
206
+ }
207
+ }
208
+ return invalidatedCount;
209
+ }
210
+ /**
211
+ * Evict least recently used entries if cache is full
212
+ */
213
+ evictIfNeeded() {
214
+ // Check size limit
215
+ while (this.cache.size >= this.config.maxSize &&
216
+ this.accessOrder.length > 0) {
217
+ const lruHash = this.accessOrder.shift();
218
+ if (lruHash) {
219
+ this.cache.delete(lruHash);
220
+ }
221
+ }
222
+ // Check memory limit (approximate) - recalculate each iteration
223
+ const maxMemoryBytes = this.config.maxMemoryMB * 1024 * 1024;
224
+ while (this.estimateMemoryUsage() > maxMemoryBytes &&
225
+ this.accessOrder.length > 0) {
226
+ const lruHash = this.accessOrder.shift();
227
+ if (lruHash) {
228
+ this.cache.delete(lruHash);
229
+ }
230
+ }
231
+ // Also evict expired entries
232
+ const now = Date.now();
233
+ const expiredHashes = [];
234
+ for (const [hash, entry] of this.cache.entries()) {
235
+ if (now - entry.timestamp > this.config.ttlMs) {
236
+ expiredHashes.push(hash);
237
+ }
238
+ }
239
+ // Delete after iteration to avoid modifying map during iteration
240
+ for (const hash of expiredHashes) {
241
+ this.cache.delete(hash);
242
+ this.removeFromAccessOrder(hash);
243
+ }
244
+ }
245
+ /**
246
+ * Update access order for LRU tracking
247
+ */
248
+ updateAccessOrder(hash) {
249
+ this.removeFromAccessOrder(hash);
250
+ this.accessOrder.push(hash);
251
+ }
252
+ /**
253
+ * Remove hash from access order
254
+ */
255
+ removeFromAccessOrder(hash) {
256
+ const index = this.accessOrder.indexOf(hash);
257
+ if (index > -1) {
258
+ this.accessOrder.splice(index, 1);
259
+ }
260
+ }
261
+ /**
262
+ * Estimate memory usage of the cache
263
+ */
264
+ estimateMemoryUsage() {
265
+ let totalSize = 0;
266
+ for (const [, entry] of this.cache.entries()) {
267
+ totalSize += JSON.stringify(entry).length * 2; // UTF-16 encoding
268
+ }
269
+ return totalSize;
270
+ }
271
+ /**
272
+ * Get cache statistics
273
+ */
274
+ getStats() {
275
+ const totalRequests = this.stats.totalHits + this.stats.totalMisses;
276
+ return {
277
+ totalHits: this.stats.totalHits,
278
+ totalMisses: this.stats.totalMisses,
279
+ hitRate: totalRequests > 0 ? this.stats.totalHits / totalRequests : 0,
280
+ currentSize: this.cache.size,
281
+ maxSize: this.config.maxSize,
282
+ ttlMs: this.config.ttlMs,
283
+ enabled: this.config.enabled,
284
+ };
285
+ }
286
+ /**
287
+ * Get current cache configuration
288
+ */
289
+ getConfig() {
290
+ return { ...this.config };
291
+ }
292
+ /**
293
+ * Update cache configuration
294
+ */
295
+ setConfig(config) {
296
+ this.config = { ...this.config, ...config };
297
+ // If cache is disabled, clear it
298
+ if (!this.config.enabled) {
299
+ this.clear();
300
+ }
301
+ }
302
+ /**
303
+ * Enable caching
304
+ */
305
+ enable() {
306
+ this.config.enabled = true;
307
+ }
308
+ /**
309
+ * Disable caching
310
+ */
311
+ disable() {
312
+ this.config.enabled = false;
313
+ this.clear();
314
+ }
315
+ /**
316
+ * Clear all cache entries
317
+ */
318
+ clear() {
319
+ this.cache.clear();
320
+ this.accessOrder = [];
321
+ }
322
+ /**
323
+ * Reset statistics
324
+ */
325
+ resetStats() {
326
+ this.stats.totalHits = 0;
327
+ this.stats.totalMisses = 0;
328
+ }
329
+ /**
330
+ * Get all cached entries (for debugging)
331
+ */
332
+ getAllEntries() {
333
+ return Array.from(this.cache.values());
334
+ }
335
+ }
336
+ exports.QueryCache = QueryCache;
337
+ exports.default = QueryCache;
@@ -21,59 +21,68 @@ var ToolCategory;
21
21
  ToolCategory["DDL"] = "ddl";
22
22
  ToolCategory["UTILITY"] = "utility";
23
23
  ToolCategory["TRANSACTION"] = "transaction";
24
- ToolCategory["PROCEDURE"] = "procedure"; // Stored procedure operations (CREATE, EXECUTE, DROP procedures)
24
+ ToolCategory["PROCEDURE"] = "procedure";
25
25
  })(ToolCategory || (exports.ToolCategory = ToolCategory = {}));
26
26
  /**
27
27
  * Map of tool names to their categories
28
28
  */
29
29
  exports.toolCategoryMap = {
30
30
  // Database tools
31
- 'listDatabases': ToolCategory.LIST,
32
- 'listTables': ToolCategory.LIST,
33
- 'readTableSchema': ToolCategory.LIST,
31
+ listDatabases: ToolCategory.LIST,
32
+ listTables: ToolCategory.LIST,
33
+ readTableSchema: ToolCategory.LIST,
34
34
  // CRUD tools
35
- 'createRecord': ToolCategory.CREATE,
36
- 'readRecords': ToolCategory.READ,
37
- 'updateRecord': ToolCategory.UPDATE,
38
- 'deleteRecord': ToolCategory.DELETE,
35
+ createRecord: ToolCategory.CREATE,
36
+ readRecords: ToolCategory.READ,
37
+ updateRecord: ToolCategory.UPDATE,
38
+ deleteRecord: ToolCategory.DELETE,
39
39
  // Bulk operations
40
- 'bulkInsert': ToolCategory.CREATE,
41
- 'bulkUpdate': ToolCategory.UPDATE,
42
- 'bulkDelete': ToolCategory.DELETE,
40
+ bulkInsert: ToolCategory.CREATE,
41
+ bulkUpdate: ToolCategory.UPDATE,
42
+ bulkDelete: ToolCategory.DELETE,
43
43
  // Query tools
44
- 'runQuery': ToolCategory.READ,
45
- 'executeSql': ToolCategory.EXECUTE,
44
+ runQuery: ToolCategory.READ,
45
+ executeSql: ToolCategory.EXECUTE,
46
46
  // DDL tools
47
- 'createTable': ToolCategory.DDL,
48
- 'alterTable': ToolCategory.DDL,
49
- 'dropTable': ToolCategory.DDL,
50
- 'executeDdl': ToolCategory.DDL,
47
+ createTable: ToolCategory.DDL,
48
+ alterTable: ToolCategory.DDL,
49
+ dropTable: ToolCategory.DDL,
50
+ executeDdl: ToolCategory.DDL,
51
51
  // Utility tools
52
- 'describeConnection': ToolCategory.UTILITY,
53
- 'testConnection': ToolCategory.UTILITY,
54
- 'getTableRelationships': ToolCategory.UTILITY,
55
- 'exportTableToCSV': ToolCategory.UTILITY,
56
- 'exportQueryToCSV': ToolCategory.UTILITY,
52
+ describeConnection: ToolCategory.UTILITY,
53
+ testConnection: ToolCategory.UTILITY,
54
+ getTableRelationships: ToolCategory.UTILITY,
55
+ exportTableToCSV: ToolCategory.UTILITY,
56
+ exportQueryToCSV: ToolCategory.UTILITY,
57
57
  // Transaction tools
58
- 'beginTransaction': ToolCategory.TRANSACTION,
59
- 'commitTransaction': ToolCategory.TRANSACTION,
60
- 'rollbackTransaction': ToolCategory.TRANSACTION,
61
- 'getTransactionStatus': ToolCategory.TRANSACTION,
62
- 'executeInTransaction': ToolCategory.TRANSACTION,
58
+ beginTransaction: ToolCategory.TRANSACTION,
59
+ commitTransaction: ToolCategory.TRANSACTION,
60
+ rollbackTransaction: ToolCategory.TRANSACTION,
61
+ getTransactionStatus: ToolCategory.TRANSACTION,
62
+ executeInTransaction: ToolCategory.TRANSACTION,
63
63
  // Stored procedure tools
64
- 'listStoredProcedures': ToolCategory.LIST,
65
- 'getStoredProcedureInfo': ToolCategory.LIST,
66
- 'executeStoredProcedure': ToolCategory.PROCEDURE,
67
- 'createStoredProcedure': ToolCategory.PROCEDURE,
68
- 'dropStoredProcedure': ToolCategory.PROCEDURE,
69
- 'showCreateProcedure': ToolCategory.LIST
64
+ listStoredProcedures: ToolCategory.LIST,
65
+ getStoredProcedureInfo: ToolCategory.LIST,
66
+ executeStoredProcedure: ToolCategory.PROCEDURE,
67
+ createStoredProcedure: ToolCategory.PROCEDURE,
68
+ dropStoredProcedure: ToolCategory.PROCEDURE,
69
+ showCreateProcedure: ToolCategory.LIST,
70
+ // Cache management tools
71
+ getCacheStats: ToolCategory.UTILITY,
72
+ getCacheConfig: ToolCategory.UTILITY,
73
+ configureCacheSettings: ToolCategory.UTILITY,
74
+ clearCache: ToolCategory.UTILITY,
75
+ invalidateCacheForTable: ToolCategory.UTILITY,
76
+ // Query optimization tools
77
+ analyzeQuery: ToolCategory.UTILITY,
78
+ getOptimizationHints: ToolCategory.UTILITY,
70
79
  };
71
80
  /**
72
81
  * Class to manage feature configuration based on runtime or environment variables
73
82
  */
74
83
  class FeatureConfig {
75
84
  constructor(configStr) {
76
- this.originalConfigString = configStr || process.env.MCP_CONFIG || '';
85
+ this.originalConfigString = configStr || process.env.MCP_CONFIG || "";
77
86
  this.enabledCategories = this.parseConfig(configStr);
78
87
  }
79
88
  /**
@@ -81,14 +90,14 @@ class FeatureConfig {
81
90
  */
82
91
  parseConfig(configStr) {
83
92
  // Priority: 1. Provided config, 2. Environment variable, 3. Enable all
84
- const config = configStr || process.env.MCP_CONFIG || '';
93
+ const config = configStr || process.env.MCP_CONFIG || "";
85
94
  // If config is empty, enable all features
86
95
  if (!config.trim()) {
87
96
  return new Set(Object.values(ToolCategory));
88
97
  }
89
98
  // Parse comma-separated list
90
- const categories = config.split(',').map(c => c.trim().toLowerCase());
91
- const validCategories = categories.filter(c => Object.values(ToolCategory).includes(c));
99
+ const categories = config.split(",").map((c) => c.trim().toLowerCase());
100
+ const validCategories = categories.filter((c) => Object.values(ToolCategory).includes(c));
92
101
  return new Set(validCategories);
93
102
  }
94
103
  /**
@@ -119,47 +128,49 @@ class FeatureConfig {
119
128
  return `Unknown tool '${toolName}'. This tool is not recognized by the MCP server.`;
120
129
  }
121
130
  const isAllPermissions = !this.originalConfigString.trim();
122
- const currentPermissions = isAllPermissions ? 'all' : this.originalConfigString;
131
+ const currentPermissions = isAllPermissions
132
+ ? "all"
133
+ : this.originalConfigString;
123
134
  const actionDescriptions = {
124
- [ToolCategory.LIST]: 'list databases and tables',
125
- [ToolCategory.READ]: 'read data from tables',
126
- [ToolCategory.CREATE]: 'create new records',
127
- [ToolCategory.UPDATE]: 'update existing records',
128
- [ToolCategory.DELETE]: 'delete records',
129
- [ToolCategory.EXECUTE]: 'execute custom SQL queries',
130
- [ToolCategory.DDL]: 'create, alter, or drop tables (schema changes)',
131
- [ToolCategory.UTILITY]: 'use utility functions',
132
- [ToolCategory.TRANSACTION]: 'manage database transactions',
133
- [ToolCategory.PROCEDURE]: 'manage stored procedures'
135
+ [ToolCategory.LIST]: "list databases and tables",
136
+ [ToolCategory.READ]: "read data from tables",
137
+ [ToolCategory.CREATE]: "create new records",
138
+ [ToolCategory.UPDATE]: "update existing records",
139
+ [ToolCategory.DELETE]: "delete records",
140
+ [ToolCategory.EXECUTE]: "execute custom SQL queries",
141
+ [ToolCategory.DDL]: "create, alter, or drop tables (schema changes)",
142
+ [ToolCategory.UTILITY]: "use utility functions",
143
+ [ToolCategory.TRANSACTION]: "manage database transactions",
144
+ [ToolCategory.PROCEDURE]: "manage stored procedures",
134
145
  };
135
146
  const toolDescriptions = {
136
- 'createTable': 'create new tables',
137
- 'alterTable': 'modify table structure',
138
- 'dropTable': 'delete tables',
139
- 'executeDdl': 'execute DDL statements',
140
- 'createRecord': 'insert new records',
141
- 'updateRecord': 'update existing records',
142
- 'deleteRecord': 'delete records',
143
- 'bulkInsert': 'insert multiple records in batches',
144
- 'bulkUpdate': 'update multiple records in batches',
145
- 'bulkDelete': 'delete multiple records in batches',
146
- 'executeSql': 'execute custom SQL statements',
147
- 'runQuery': 'run SELECT queries',
148
- 'beginTransaction': 'start database transactions',
149
- 'commitTransaction': 'commit database transactions',
150
- 'rollbackTransaction': 'rollback database transactions',
151
- 'executeInTransaction': 'execute queries within transactions',
152
- 'createStoredProcedure': 'create stored procedures',
153
- 'dropStoredProcedure': 'delete stored procedures',
154
- 'executeStoredProcedure': 'execute stored procedures',
155
- 'exportTableToCSV': 'export table data to CSV',
156
- 'exportQueryToCSV': 'export query results to CSV'
147
+ createTable: "create new tables",
148
+ alterTable: "modify table structure",
149
+ dropTable: "delete tables",
150
+ executeDdl: "execute DDL statements",
151
+ createRecord: "insert new records",
152
+ updateRecord: "update existing records",
153
+ deleteRecord: "delete records",
154
+ bulkInsert: "insert multiple records in batches",
155
+ bulkUpdate: "update multiple records in batches",
156
+ bulkDelete: "delete multiple records in batches",
157
+ executeSql: "execute custom SQL statements",
158
+ runQuery: "run SELECT queries",
159
+ beginTransaction: "start database transactions",
160
+ commitTransaction: "commit database transactions",
161
+ rollbackTransaction: "rollback database transactions",
162
+ executeInTransaction: "execute queries within transactions",
163
+ createStoredProcedure: "create stored procedures",
164
+ dropStoredProcedure: "delete stored procedures",
165
+ executeStoredProcedure: "execute stored procedures",
166
+ exportTableToCSV: "export table data to CSV",
167
+ exportQueryToCSV: "export query results to CSV",
157
168
  };
158
169
  const toolDescription = toolDescriptions[toolName] || actionDescriptions[category];
159
170
  const requiredPermission = category;
160
- return `Permission denied: Cannot ${toolDescription}. ` +
171
+ return (`Permission denied: Cannot ${toolDescription}. ` +
161
172
  `This action requires '${requiredPermission}' permission, but your current MCP configuration only allows: ${currentPermissions}. ` +
162
- `To enable this feature, update your MCP server configuration to include '${requiredPermission}' in the permissions list.`;
173
+ `To enable this feature, update your MCP server configuration to include '${requiredPermission}' in the permissions list.`);
163
174
  }
164
175
  /**
165
176
  * Check if a category is enabled
@@ -1,12 +1,17 @@
1
- import mysql from 'mysql2/promise';
1
+ import mysql from "mysql2/promise";
2
2
  declare class DatabaseConnection {
3
3
  private static instance;
4
4
  private pool;
5
5
  private activeTransactions;
6
+ private queryCache;
6
7
  private constructor();
7
8
  static getInstance(): DatabaseConnection;
8
9
  getConnection(): Promise<mysql.PoolConnection>;
9
- query<T>(sql: string, params?: any[]): Promise<T>;
10
+ query<T>(sql: string, params?: any[], useCache?: boolean): Promise<T>;
11
+ /**
12
+ * Invalidate cache entries when write operations occur
13
+ */
14
+ private invalidateCacheForWriteOperation;
10
15
  testConnection(): Promise<{
11
16
  connected: boolean;
12
17
  latency: number;
@@ -20,6 +25,20 @@ declare class DatabaseConnection {
20
25
  getQueryLogs(): import("./queryLogger").QueryLog[];
21
26
  getLastQueryLog(): import("./queryLogger").QueryLog | undefined;
22
27
  getFormattedQueryLogs(count?: number): string;
28
+ getCacheStats(): import("../cache/queryCache").CacheStats;
29
+ getCacheConfig(): import("../cache/queryCache").CacheConfig;
30
+ setCacheConfig(config: {
31
+ enabled?: boolean;
32
+ ttlMs?: number;
33
+ maxSize?: number;
34
+ maxMemoryMB?: number;
35
+ }): void;
36
+ clearCache(): number;
37
+ invalidateCache(pattern?: string | RegExp): number;
38
+ invalidateCacheForTable(tableName: string): number;
39
+ enableCache(): void;
40
+ disableCache(): void;
41
+ resetCacheStats(): void;
23
42
  executeInTransaction<T>(transactionId: string, sql: string, params?: any[]): Promise<T>;
24
43
  }
25
44
  export default DatabaseConnection;