@berthojoris/mcp-mysql-server 1.10.2 → 1.10.4

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 (44) hide show
  1. package/CHANGELOG.md +25 -7
  2. package/DOCUMENTATIONS.md +2 -2
  3. package/README.md +1 -1
  4. package/dist/index.d.ts +0 -99
  5. package/dist/mcp-server.js +0 -21
  6. package/dist/tools/backupRestoreTools.d.ts +1 -6
  7. package/dist/tools/backupRestoreTools.js +99 -97
  8. package/dist/tools/constraintTools.d.ts +4 -11
  9. package/dist/tools/constraintTools.js +114 -115
  10. package/dist/tools/crudTools.d.ts +2 -6
  11. package/dist/tools/crudTools.js +186 -189
  12. package/dist/tools/dataExportTools.d.ts +0 -7
  13. package/dist/tools/dataExportTools.js +0 -15
  14. package/dist/tools/databaseTools.d.ts +1 -4
  15. package/dist/tools/databaseTools.js +29 -33
  16. package/dist/tools/ddlTools.d.ts +1 -5
  17. package/dist/tools/ddlTools.js +68 -53
  18. package/dist/tools/functionTools.d.ts +3 -9
  19. package/dist/tools/functionTools.js +111 -104
  20. package/dist/tools/indexTools.d.ts +3 -8
  21. package/dist/tools/indexTools.js +99 -95
  22. package/dist/tools/maintenanceTools.d.ts +2 -10
  23. package/dist/tools/maintenanceTools.js +66 -80
  24. package/dist/tools/migrationTools.d.ts +0 -5
  25. package/dist/tools/migrationTools.js +56 -24
  26. package/dist/tools/performanceTools.d.ts +1 -11
  27. package/dist/tools/performanceTools.js +278 -267
  28. package/dist/tools/processTools.d.ts +4 -13
  29. package/dist/tools/processTools.js +78 -80
  30. package/dist/tools/queryTools.d.ts +0 -2
  31. package/dist/tools/queryTools.js +0 -4
  32. package/dist/tools/schemaVersioningTools.d.ts +0 -9
  33. package/dist/tools/schemaVersioningTools.js +167 -166
  34. package/dist/tools/storedProcedureTools.d.ts +2 -4
  35. package/dist/tools/storedProcedureTools.js +143 -134
  36. package/dist/tools/transactionTools.d.ts +2 -3
  37. package/dist/tools/transactionTools.js +28 -29
  38. package/dist/tools/triggerTools.d.ts +3 -8
  39. package/dist/tools/triggerTools.js +98 -85
  40. package/dist/tools/utilityTools.d.ts +0 -1
  41. package/dist/tools/utilityTools.js +0 -2
  42. package/dist/tools/viewTools.d.ts +7 -13
  43. package/dist/tools/viewTools.js +100 -93
  44. package/package.json +1 -1
@@ -18,8 +18,8 @@ class CrudTools {
18
18
  // Validate input schema
19
19
  if (!(0, schemas_1.validateCreateRecord)(params)) {
20
20
  return {
21
- status: 'error',
22
- error: 'Invalid parameters: ' + JSON.stringify(schemas_1.validateCreateRecord.errors)
21
+ status: "error",
22
+ error: "Invalid parameters: " + JSON.stringify(schemas_1.validateCreateRecord.errors),
23
23
  };
24
24
  }
25
25
  try {
@@ -28,8 +28,8 @@ class CrudTools {
28
28
  const tableValidation = this.security.validateIdentifier(table_name);
29
29
  if (!tableValidation.valid) {
30
30
  return {
31
- status: 'error',
32
- error: `Invalid table name: ${tableValidation.error}`
31
+ status: "error",
32
+ error: `Invalid table name: ${tableValidation.error}`,
33
33
  };
34
34
  }
35
35
  // Validate column names
@@ -38,8 +38,8 @@ class CrudTools {
38
38
  const columnValidation = this.security.validateIdentifier(column);
39
39
  if (!columnValidation.valid) {
40
40
  return {
41
- status: 'error',
42
- error: `Invalid column name '${column}': ${columnValidation.error}`
41
+ status: "error",
42
+ error: `Invalid column name '${column}': ${columnValidation.error}`,
43
43
  };
44
44
  }
45
45
  }
@@ -48,31 +48,29 @@ class CrudTools {
48
48
  const paramValidation = this.security.validateParameters(values);
49
49
  if (!paramValidation.valid) {
50
50
  return {
51
- status: 'error',
52
- error: `Invalid parameter values: ${paramValidation.error}`
51
+ status: "error",
52
+ error: `Invalid parameter values: ${paramValidation.error}`,
53
53
  };
54
54
  }
55
55
  // Build the query with escaped identifiers
56
56
  const escapedTableName = this.security.escapeIdentifier(table_name);
57
- const escapedColumns = columns.map(col => this.security.escapeIdentifier(col));
58
- const placeholders = columns.map(() => '?').join(', ');
59
- const query = `INSERT INTO ${escapedTableName} (${escapedColumns.join(', ')}) VALUES (${placeholders})`;
57
+ const escapedColumns = columns.map((col) => this.security.escapeIdentifier(col));
58
+ const placeholders = columns.map(() => "?").join(", ");
59
+ const query = `INSERT INTO ${escapedTableName} (${escapedColumns.join(", ")}) VALUES (${placeholders})`;
60
60
  // Execute the query with sanitized parameters
61
61
  const result = await this.db.query(query, paramValidation.sanitizedParams);
62
62
  return {
63
- status: 'success',
63
+ status: "success",
64
64
  data: {
65
65
  insertId: result.insertId,
66
- affectedRows: result.affectedRows
66
+ affectedRows: result.affectedRows,
67
67
  },
68
- queryLog: this.db.getFormattedQueryLogs(1)
69
68
  };
70
69
  }
71
70
  catch (error) {
72
71
  return {
73
- status: 'error',
72
+ status: "error",
74
73
  error: error.message,
75
- queryLog: this.db.getFormattedQueryLogs(1)
76
74
  };
77
75
  }
78
76
  }
@@ -83,8 +81,8 @@ class CrudTools {
83
81
  // Validate input schema
84
82
  if (!(0, schemas_1.validateReadRecords)(params)) {
85
83
  return {
86
- status: 'error',
87
- error: 'Invalid parameters: ' + JSON.stringify(schemas_1.validateReadRecords.errors)
84
+ status: "error",
85
+ error: "Invalid parameters: " + JSON.stringify(schemas_1.validateReadRecords.errors),
88
86
  };
89
87
  }
90
88
  try {
@@ -93,8 +91,8 @@ class CrudTools {
93
91
  const tableValidation = this.security.validateIdentifier(table_name);
94
92
  if (!tableValidation.valid) {
95
93
  return {
96
- status: 'error',
97
- error: `Invalid table name: ${tableValidation.error}`
94
+ status: "error",
95
+ error: `Invalid table name: ${tableValidation.error}`,
98
96
  };
99
97
  }
100
98
  // Validate sorting field if provided
@@ -102,8 +100,8 @@ class CrudTools {
102
100
  const sortFieldValidation = this.security.validateIdentifier(sorting.field);
103
101
  if (!sortFieldValidation.valid) {
104
102
  return {
105
- status: 'error',
106
- error: `Invalid sorting field: ${sortFieldValidation.error}`
103
+ status: "error",
104
+ error: `Invalid sorting field: ${sortFieldValidation.error}`,
107
105
  };
108
106
  }
109
107
  }
@@ -113,69 +111,69 @@ class CrudTools {
113
111
  const fieldValidation = this.security.validateIdentifier(filter.field);
114
112
  if (!fieldValidation.valid) {
115
113
  return {
116
- status: 'error',
117
- error: `Invalid filter field '${filter.field}': ${fieldValidation.error}`
114
+ status: "error",
115
+ error: `Invalid filter field '${filter.field}': ${fieldValidation.error}`,
118
116
  };
119
117
  }
120
118
  }
121
119
  }
122
120
  // Build the WHERE clause if filters are provided
123
- let whereClause = '';
121
+ let whereClause = "";
124
122
  let queryParams = [];
125
123
  if (filters && filters.length > 0) {
126
- const conditions = filters.map(filter => {
124
+ const conditions = filters.map((filter) => {
127
125
  const escapedField = this.security.escapeIdentifier(filter.field);
128
126
  switch (filter.operator) {
129
- case 'eq':
127
+ case "eq":
130
128
  queryParams.push(filter.value);
131
129
  return `${escapedField} = ?`;
132
- case 'neq':
130
+ case "neq":
133
131
  queryParams.push(filter.value);
134
132
  return `${escapedField} != ?`;
135
- case 'gt':
133
+ case "gt":
136
134
  queryParams.push(filter.value);
137
135
  return `${escapedField} > ?`;
138
- case 'gte':
136
+ case "gte":
139
137
  queryParams.push(filter.value);
140
138
  return `${escapedField} >= ?`;
141
- case 'lt':
139
+ case "lt":
142
140
  queryParams.push(filter.value);
143
141
  return `${escapedField} < ?`;
144
- case 'lte':
142
+ case "lte":
145
143
  queryParams.push(filter.value);
146
144
  return `${escapedField} <= ?`;
147
- case 'like':
145
+ case "like":
148
146
  queryParams.push(`%${filter.value}%`);
149
147
  return `${escapedField} LIKE ?`;
150
- case 'in':
148
+ case "in":
151
149
  if (Array.isArray(filter.value)) {
152
- const placeholders = filter.value.map(() => '?').join(', ');
150
+ const placeholders = filter.value.map(() => "?").join(", ");
153
151
  queryParams.push(...filter.value);
154
152
  return `${escapedField} IN (${placeholders})`;
155
153
  }
156
- return '1=1'; // Default true condition if value is not an array
154
+ return "1=1"; // Default true condition if value is not an array
157
155
  default:
158
- return '1=1'; // Default true condition
156
+ return "1=1"; // Default true condition
159
157
  }
160
158
  });
161
- whereClause = 'WHERE ' + conditions.join(' AND ');
159
+ whereClause = "WHERE " + conditions.join(" AND ");
162
160
  }
163
161
  // Validate all query parameters
164
162
  const paramValidation = this.security.validateParameters(queryParams);
165
163
  if (!paramValidation.valid) {
166
164
  return {
167
- status: 'error',
168
- error: `Invalid query parameters: ${paramValidation.error}`
165
+ status: "error",
166
+ error: `Invalid query parameters: ${paramValidation.error}`,
169
167
  };
170
168
  }
171
169
  // Build the ORDER BY clause if sorting is provided
172
- let orderByClause = '';
170
+ let orderByClause = "";
173
171
  if (sorting) {
174
172
  const escapedSortField = this.security.escapeIdentifier(sorting.field);
175
173
  orderByClause = `ORDER BY ${escapedSortField} ${sorting.direction.toUpperCase()}`;
176
174
  }
177
175
  // Build the LIMIT clause if pagination is provided
178
- let limitClause = '';
176
+ let limitClause = "";
179
177
  const escapedTableName = this.security.escapeIdentifier(table_name);
180
178
  if (pagination) {
181
179
  const offset = (pagination.page - 1) * pagination.limit;
@@ -188,10 +186,9 @@ class CrudTools {
188
186
  const query = `SELECT * FROM ${escapedTableName} ${whereClause} ${orderByClause} ${limitClause}`;
189
187
  const results = await this.db.query(query, paramValidation.sanitizedParams);
190
188
  return {
191
- status: 'success',
189
+ status: "success",
192
190
  data: results,
193
191
  total,
194
- queryLog: this.db.getFormattedQueryLogs(2)
195
192
  };
196
193
  }
197
194
  else {
@@ -199,18 +196,16 @@ class CrudTools {
199
196
  const query = `SELECT * FROM ${escapedTableName} ${whereClause} ${orderByClause}`;
200
197
  const results = await this.db.query(query, paramValidation.sanitizedParams);
201
198
  return {
202
- status: 'success',
199
+ status: "success",
203
200
  data: results,
204
201
  total: results.length,
205
- queryLog: this.db.getFormattedQueryLogs(1)
206
202
  };
207
203
  }
208
204
  }
209
205
  catch (error) {
210
206
  return {
211
- status: 'error',
207
+ status: "error",
212
208
  error: error.message,
213
- queryLog: this.db.getFormattedQueryLogs(1)
214
209
  };
215
210
  }
216
211
  }
@@ -221,8 +216,8 @@ class CrudTools {
221
216
  // Validate input schema
222
217
  if (!(0, schemas_1.validateUpdateRecord)(params)) {
223
218
  return {
224
- status: 'error',
225
- error: 'Invalid parameters: ' + JSON.stringify(schemas_1.validateUpdateRecord.errors)
219
+ status: "error",
220
+ error: "Invalid parameters: " + JSON.stringify(schemas_1.validateUpdateRecord.errors),
226
221
  };
227
222
  }
228
223
  try {
@@ -231,8 +226,8 @@ class CrudTools {
231
226
  const tableValidation = this.security.validateIdentifier(table_name);
232
227
  if (!tableValidation.valid) {
233
228
  return {
234
- status: 'error',
235
- error: `Invalid table name: ${tableValidation.error}`
229
+ status: "error",
230
+ error: `Invalid table name: ${tableValidation.error}`,
236
231
  };
237
232
  }
238
233
  // Validate column names in data
@@ -241,8 +236,8 @@ class CrudTools {
241
236
  const columnValidation = this.security.validateIdentifier(column);
242
237
  if (!columnValidation.valid) {
243
238
  return {
244
- status: 'error',
245
- error: `Invalid column name '${column}': ${columnValidation.error}`
239
+ status: "error",
240
+ error: `Invalid column name '${column}': ${columnValidation.error}`,
246
241
  };
247
242
  }
248
243
  }
@@ -251,53 +246,53 @@ class CrudTools {
251
246
  const fieldValidation = this.security.validateIdentifier(condition.field);
252
247
  if (!fieldValidation.valid) {
253
248
  return {
254
- status: 'error',
255
- error: `Invalid condition field '${condition.field}': ${fieldValidation.error}`
249
+ status: "error",
250
+ error: `Invalid condition field '${condition.field}': ${fieldValidation.error}`,
256
251
  };
257
252
  }
258
253
  }
259
254
  // Build SET clause with escaped identifiers
260
255
  const setClause = Object.entries(data)
261
256
  .map(([column, _]) => `${this.security.escapeIdentifier(column)} = ?`)
262
- .join(', ');
257
+ .join(", ");
263
258
  const setValues = Object.values(data);
264
259
  // Build the WHERE clause
265
260
  const whereConditions = [];
266
261
  const whereValues = [];
267
- conditions.forEach(condition => {
262
+ conditions.forEach((condition) => {
268
263
  const escapedField = this.security.escapeIdentifier(condition.field);
269
264
  switch (condition.operator) {
270
- case 'eq':
265
+ case "eq":
271
266
  whereConditions.push(`${escapedField} = ?`);
272
267
  whereValues.push(condition.value);
273
268
  break;
274
- case 'neq':
269
+ case "neq":
275
270
  whereConditions.push(`${escapedField} != ?`);
276
271
  whereValues.push(condition.value);
277
272
  break;
278
- case 'gt':
273
+ case "gt":
279
274
  whereConditions.push(`${escapedField} > ?`);
280
275
  whereValues.push(condition.value);
281
276
  break;
282
- case 'gte':
277
+ case "gte":
283
278
  whereConditions.push(`${escapedField} >= ?`);
284
279
  whereValues.push(condition.value);
285
280
  break;
286
- case 'lt':
281
+ case "lt":
287
282
  whereConditions.push(`${escapedField} < ?`);
288
283
  whereValues.push(condition.value);
289
284
  break;
290
- case 'lte':
285
+ case "lte":
291
286
  whereConditions.push(`${escapedField} <= ?`);
292
287
  whereValues.push(condition.value);
293
288
  break;
294
- case 'like':
289
+ case "like":
295
290
  whereConditions.push(`${escapedField} LIKE ?`);
296
291
  whereValues.push(`%${condition.value}%`);
297
292
  break;
298
- case 'in':
293
+ case "in":
299
294
  if (Array.isArray(condition.value)) {
300
- const placeholders = condition.value.map(() => '?').join(', ');
295
+ const placeholders = condition.value.map(() => "?").join(", ");
301
296
  whereConditions.push(`${escapedField} IN (${placeholders})`);
302
297
  whereValues.push(...condition.value);
303
298
  }
@@ -305,15 +300,15 @@ class CrudTools {
305
300
  }
306
301
  });
307
302
  const whereClause = whereConditions.length > 0
308
- ? 'WHERE ' + whereConditions.join(' AND ')
309
- : '';
303
+ ? "WHERE " + whereConditions.join(" AND ")
304
+ : "";
310
305
  // Validate all parameters
311
306
  const allParams = [...setValues, ...whereValues];
312
307
  const paramValidation = this.security.validateParameters(allParams);
313
308
  if (!paramValidation.valid) {
314
309
  return {
315
- status: 'error',
316
- error: `Invalid parameters: ${paramValidation.error}`
310
+ status: "error",
311
+ error: `Invalid parameters: ${paramValidation.error}`,
317
312
  };
318
313
  }
319
314
  // Build the query with escaped table name
@@ -322,18 +317,16 @@ class CrudTools {
322
317
  // Execute the query with sanitized parameters
323
318
  const result = await this.db.query(query, paramValidation.sanitizedParams);
324
319
  return {
325
- status: 'success',
320
+ status: "success",
326
321
  data: {
327
- affectedRows: result.affectedRows
322
+ affectedRows: result.affectedRows,
328
323
  },
329
- queryLog: this.db.getFormattedQueryLogs(1)
330
324
  };
331
325
  }
332
326
  catch (error) {
333
327
  return {
334
- status: 'error',
328
+ status: "error",
335
329
  error: error.message,
336
- queryLog: this.db.getFormattedQueryLogs(1)
337
330
  };
338
331
  }
339
332
  }
@@ -344,8 +337,8 @@ class CrudTools {
344
337
  // Validate input schema
345
338
  if (!(0, schemas_1.validateDeleteRecord)(params)) {
346
339
  return {
347
- status: 'error',
348
- error: 'Invalid parameters: ' + JSON.stringify(schemas_1.validateDeleteRecord.errors)
340
+ status: "error",
341
+ error: "Invalid parameters: " + JSON.stringify(schemas_1.validateDeleteRecord.errors),
349
342
  };
350
343
  }
351
344
  try {
@@ -354,15 +347,15 @@ class CrudTools {
354
347
  const tableValidation = this.security.validateIdentifier(table_name);
355
348
  if (!tableValidation.valid) {
356
349
  return {
357
- status: 'error',
358
- error: `Invalid table name: ${tableValidation.error}`
350
+ status: "error",
351
+ error: `Invalid table name: ${tableValidation.error}`,
359
352
  };
360
353
  }
361
354
  // Ensure there are conditions for safety
362
355
  if (!conditions || conditions.length === 0) {
363
356
  return {
364
- status: 'error',
365
- error: 'DELETE operations require at least one condition for safety'
357
+ status: "error",
358
+ error: "DELETE operations require at least one condition for safety",
366
359
  };
367
360
  }
368
361
  // Validate condition fields
@@ -370,61 +363,61 @@ class CrudTools {
370
363
  const fieldValidation = this.security.validateIdentifier(condition.field);
371
364
  if (!fieldValidation.valid) {
372
365
  return {
373
- status: 'error',
374
- error: `Invalid condition field '${condition.field}': ${fieldValidation.error}`
366
+ status: "error",
367
+ error: `Invalid condition field '${condition.field}': ${fieldValidation.error}`,
375
368
  };
376
369
  }
377
370
  }
378
371
  // Build the WHERE clause
379
372
  const whereConditions = [];
380
373
  const whereValues = [];
381
- conditions.forEach(condition => {
374
+ conditions.forEach((condition) => {
382
375
  const escapedField = this.security.escapeIdentifier(condition.field);
383
376
  switch (condition.operator) {
384
- case 'eq':
377
+ case "eq":
385
378
  whereConditions.push(`${escapedField} = ?`);
386
379
  whereValues.push(condition.value);
387
380
  break;
388
- case 'neq':
381
+ case "neq":
389
382
  whereConditions.push(`${escapedField} != ?`);
390
383
  whereValues.push(condition.value);
391
384
  break;
392
- case 'gt':
385
+ case "gt":
393
386
  whereConditions.push(`${escapedField} > ?`);
394
387
  whereValues.push(condition.value);
395
388
  break;
396
- case 'gte':
389
+ case "gte":
397
390
  whereConditions.push(`${escapedField} >= ?`);
398
391
  whereValues.push(condition.value);
399
392
  break;
400
- case 'lt':
393
+ case "lt":
401
394
  whereConditions.push(`${escapedField} < ?`);
402
395
  whereValues.push(condition.value);
403
396
  break;
404
- case 'lte':
397
+ case "lte":
405
398
  whereConditions.push(`${escapedField} <= ?`);
406
399
  whereValues.push(condition.value);
407
400
  break;
408
- case 'like':
401
+ case "like":
409
402
  whereConditions.push(`${escapedField} LIKE ?`);
410
403
  whereValues.push(`%${condition.value}%`);
411
404
  break;
412
- case 'in':
405
+ case "in":
413
406
  if (Array.isArray(condition.value)) {
414
- const placeholders = condition.value.map(() => '?').join(', ');
407
+ const placeholders = condition.value.map(() => "?").join(", ");
415
408
  whereConditions.push(`${escapedField} IN (${placeholders})`);
416
409
  whereValues.push(...condition.value);
417
410
  }
418
411
  break;
419
412
  }
420
413
  });
421
- const whereClause = 'WHERE ' + whereConditions.join(' AND ');
414
+ const whereClause = "WHERE " + whereConditions.join(" AND ");
422
415
  // Validate all parameters
423
416
  const paramValidation = this.security.validateParameters(whereValues);
424
417
  if (!paramValidation.valid) {
425
418
  return {
426
- status: 'error',
427
- error: `Invalid parameters: ${paramValidation.error}`
419
+ status: "error",
420
+ error: `Invalid parameters: ${paramValidation.error}`,
428
421
  };
429
422
  }
430
423
  // Build the query with escaped table name
@@ -433,18 +426,16 @@ class CrudTools {
433
426
  // Execute the query with sanitized parameters
434
427
  const result = await this.db.query(query, paramValidation.sanitizedParams);
435
428
  return {
436
- status: 'success',
429
+ status: "success",
437
430
  data: {
438
- affectedRows: result.affectedRows
431
+ affectedRows: result.affectedRows,
439
432
  },
440
- queryLog: this.db.getFormattedQueryLogs(1)
441
433
  };
442
434
  }
443
435
  catch (error) {
444
436
  return {
445
- status: 'error',
437
+ status: "error",
446
438
  error: error.message,
447
- queryLog: this.db.getFormattedQueryLogs(1)
448
439
  };
449
440
  }
450
441
  }
@@ -455,8 +446,8 @@ class CrudTools {
455
446
  // Validate input schema
456
447
  if (!(0, schemas_1.validateBulkInsert)(params)) {
457
448
  return {
458
- status: 'error',
459
- error: 'Invalid parameters: ' + JSON.stringify(schemas_1.validateBulkInsert.errors)
449
+ status: "error",
450
+ error: "Invalid parameters: " + JSON.stringify(schemas_1.validateBulkInsert.errors),
460
451
  };
461
452
  }
462
453
  try {
@@ -465,15 +456,15 @@ class CrudTools {
465
456
  const tableValidation = this.security.validateIdentifier(table_name);
466
457
  if (!tableValidation.valid) {
467
458
  return {
468
- status: 'error',
469
- error: `Invalid table name: ${tableValidation.error}`
459
+ status: "error",
460
+ error: `Invalid table name: ${tableValidation.error}`,
470
461
  };
471
462
  }
472
463
  // Ensure data is not empty
473
464
  if (!data || data.length === 0) {
474
465
  return {
475
- status: 'error',
476
- error: 'Data array cannot be empty'
466
+ status: "error",
467
+ error: "Data array cannot be empty",
477
468
  };
478
469
  }
479
470
  // Validate that all records have the same columns
@@ -482,10 +473,10 @@ class CrudTools {
482
473
  for (let i = 1; i < data.length; i++) {
483
474
  const recordColumns = Object.keys(data[i]);
484
475
  if (recordColumns.length !== columns.length ||
485
- !recordColumns.every(col => columns.includes(col))) {
476
+ !recordColumns.every((col) => columns.includes(col))) {
486
477
  return {
487
- status: 'error',
488
- error: `All records must have the same columns. Record ${i + 1} has different columns.`
478
+ status: "error",
479
+ error: `All records must have the same columns. Record ${i + 1} has different columns.`,
489
480
  };
490
481
  }
491
482
  }
@@ -494,8 +485,8 @@ class CrudTools {
494
485
  const columnValidation = this.security.validateIdentifier(column);
495
486
  if (!columnValidation.valid) {
496
487
  return {
497
- status: 'error',
498
- error: `Invalid column name '${column}': ${columnValidation.error}`
488
+ status: "error",
489
+ error: `Invalid column name '${column}': ${columnValidation.error}`,
499
490
  };
500
491
  }
501
492
  }
@@ -507,46 +498,48 @@ class CrudTools {
507
498
  // Prepare batch values
508
499
  const batchValues = [];
509
500
  for (const record of batch) {
510
- const values = columns.map(col => record[col]);
501
+ const values = columns.map((col) => record[col]);
511
502
  // Validate and sanitize parameter values for this record
512
503
  const paramValidation = this.security.validateParameters(values);
513
504
  if (!paramValidation.valid) {
514
505
  return {
515
- status: 'error',
516
- error: `Invalid parameter values in record ${i + batchValues.length / columns.length + 1}: ${paramValidation.error}`
506
+ status: "error",
507
+ error: `Invalid parameter values in record ${i + batchValues.length / columns.length + 1}: ${paramValidation.error}`,
517
508
  };
518
509
  }
519
510
  batchValues.push(...paramValidation.sanitizedParams);
520
511
  }
521
512
  // Build the query with escaped identifiers
522
513
  const escapedTableName = this.security.escapeIdentifier(table_name);
523
- const escapedColumns = columns.map(col => this.security.escapeIdentifier(col));
524
- const valueGroups = batch.map(() => `(${columns.map(() => '?').join(', ')})`).join(', ');
525
- const query = `INSERT INTO ${escapedTableName} (${escapedColumns.join(', ')}) VALUES ${valueGroups}`;
514
+ const escapedColumns = columns.map((col) => this.security.escapeIdentifier(col));
515
+ const valueGroups = batch
516
+ .map(() => `(${columns.map(() => "?").join(", ")})`)
517
+ .join(", ");
518
+ const query = `INSERT INTO ${escapedTableName} (${escapedColumns.join(", ")}) VALUES ${valueGroups}`;
526
519
  // Execute the batch query
527
520
  const result = await this.db.query(query, batchValues);
528
521
  results.push({
529
522
  batchNumber: Math.floor(i / batch_size) + 1,
530
523
  recordsInserted: batch.length,
531
524
  firstInsertId: result.insertId,
532
- affectedRows: result.affectedRows
525
+ affectedRows: result.affectedRows,
533
526
  });
534
527
  totalInserted += result.affectedRows;
535
528
  }
536
529
  return {
537
- status: 'success',
530
+ status: "success",
538
531
  data: {
539
532
  totalRecords: data.length,
540
533
  totalInserted,
541
534
  batches: results.length,
542
- batchResults: results
543
- }
535
+ batchResults: results,
536
+ },
544
537
  };
545
538
  }
546
539
  catch (error) {
547
540
  return {
548
- status: 'error',
549
- error: error.message
541
+ status: "error",
542
+ error: error.message,
550
543
  };
551
544
  }
552
545
  }
@@ -557,8 +550,8 @@ class CrudTools {
557
550
  // Validate input schema
558
551
  if (!(0, schemas_1.validateBulkUpdate)(params)) {
559
552
  return {
560
- status: 'error',
561
- error: 'Invalid parameters: ' + JSON.stringify(schemas_1.validateBulkUpdate.errors)
553
+ status: "error",
554
+ error: "Invalid parameters: " + JSON.stringify(schemas_1.validateBulkUpdate.errors),
562
555
  };
563
556
  }
564
557
  try {
@@ -567,15 +560,15 @@ class CrudTools {
567
560
  const tableValidation = this.security.validateIdentifier(table_name);
568
561
  if (!tableValidation.valid) {
569
562
  return {
570
- status: 'error',
571
- error: `Invalid table name: ${tableValidation.error}`
563
+ status: "error",
564
+ error: `Invalid table name: ${tableValidation.error}`,
572
565
  };
573
566
  }
574
567
  // Ensure updates is not empty
575
568
  if (!updates || updates.length === 0) {
576
569
  return {
577
- status: 'error',
578
- error: 'Updates array cannot be empty'
570
+ status: "error",
571
+ error: "Updates array cannot be empty",
579
572
  };
580
573
  }
581
574
  // Validate each update operation
@@ -587,8 +580,8 @@ class CrudTools {
587
580
  const columnValidation = this.security.validateIdentifier(column);
588
581
  if (!columnValidation.valid) {
589
582
  return {
590
- status: 'error',
591
- error: `Invalid column name '${column}' in update ${i + 1}: ${columnValidation.error}`
583
+ status: "error",
584
+ error: `Invalid column name '${column}' in update ${i + 1}: ${columnValidation.error}`,
592
585
  };
593
586
  }
594
587
  }
@@ -597,8 +590,8 @@ class CrudTools {
597
590
  const fieldValidation = this.security.validateIdentifier(condition.field);
598
591
  if (!fieldValidation.valid) {
599
592
  return {
600
- status: 'error',
601
- error: `Invalid condition field '${condition.field}' in update ${i + 1}: ${fieldValidation.error}`
593
+ status: "error",
594
+ error: `Invalid condition field '${condition.field}' in update ${i + 1}: ${fieldValidation.error}`,
602
595
  };
603
596
  }
604
597
  }
@@ -609,52 +602,54 @@ class CrudTools {
609
602
  for (let i = 0; i < updates.length; i += batch_size) {
610
603
  const batch = updates.slice(i, i + batch_size);
611
604
  // Start a transaction for this batch
612
- await this.db.query('START TRANSACTION');
605
+ await this.db.query("START TRANSACTION");
613
606
  try {
614
607
  const batchResults = [];
615
608
  for (const update of batch) {
616
609
  // Build SET clause
617
610
  const setClause = Object.entries(update.data)
618
611
  .map(([column, _]) => `${this.security.escapeIdentifier(column)} = ?`)
619
- .join(', ');
612
+ .join(", ");
620
613
  const setValues = Object.values(update.data);
621
614
  // Build WHERE clause
622
615
  const whereConditions = [];
623
616
  const whereValues = [];
624
- update.conditions.forEach(condition => {
617
+ update.conditions.forEach((condition) => {
625
618
  const escapedField = this.security.escapeIdentifier(condition.field);
626
619
  switch (condition.operator) {
627
- case 'eq':
620
+ case "eq":
628
621
  whereConditions.push(`${escapedField} = ?`);
629
622
  whereValues.push(condition.value);
630
623
  break;
631
- case 'neq':
624
+ case "neq":
632
625
  whereConditions.push(`${escapedField} != ?`);
633
626
  whereValues.push(condition.value);
634
627
  break;
635
- case 'gt':
628
+ case "gt":
636
629
  whereConditions.push(`${escapedField} > ?`);
637
630
  whereValues.push(condition.value);
638
631
  break;
639
- case 'gte':
632
+ case "gte":
640
633
  whereConditions.push(`${escapedField} >= ?`);
641
634
  whereValues.push(condition.value);
642
635
  break;
643
- case 'lt':
636
+ case "lt":
644
637
  whereConditions.push(`${escapedField} < ?`);
645
638
  whereValues.push(condition.value);
646
639
  break;
647
- case 'lte':
640
+ case "lte":
648
641
  whereConditions.push(`${escapedField} <= ?`);
649
642
  whereValues.push(condition.value);
650
643
  break;
651
- case 'like':
644
+ case "like":
652
645
  whereConditions.push(`${escapedField} LIKE ?`);
653
646
  whereValues.push(`%${condition.value}%`);
654
647
  break;
655
- case 'in':
648
+ case "in":
656
649
  if (Array.isArray(condition.value)) {
657
- const placeholders = condition.value.map(() => '?').join(', ');
650
+ const placeholders = condition.value
651
+ .map(() => "?")
652
+ .join(", ");
658
653
  whereConditions.push(`${escapedField} IN (${placeholders})`);
659
654
  whereValues.push(...condition.value);
660
655
  }
@@ -662,8 +657,8 @@ class CrudTools {
662
657
  }
663
658
  });
664
659
  const whereClause = whereConditions.length > 0
665
- ? 'WHERE ' + whereConditions.join(' AND ')
666
- : '';
660
+ ? "WHERE " + whereConditions.join(" AND ")
661
+ : "";
667
662
  // Validate all parameters
668
663
  const allParams = [...setValues, ...whereValues];
669
664
  const paramValidation = this.security.validateParameters(allParams);
@@ -675,38 +670,38 @@ class CrudTools {
675
670
  const query = `UPDATE ${escapedTableName} SET ${setClause} ${whereClause}`;
676
671
  const result = await this.db.query(query, paramValidation.sanitizedParams);
677
672
  batchResults.push({
678
- affectedRows: result.affectedRows
673
+ affectedRows: result.affectedRows,
679
674
  });
680
675
  totalAffected += result.affectedRows;
681
676
  }
682
677
  // Commit the transaction
683
- await this.db.query('COMMIT');
678
+ await this.db.query("COMMIT");
684
679
  results.push({
685
680
  batchNumber: Math.floor(i / batch_size) + 1,
686
681
  updatesProcessed: batch.length,
687
- results: batchResults
682
+ results: batchResults,
688
683
  });
689
684
  }
690
685
  catch (error) {
691
686
  // Rollback on error
692
- await this.db.query('ROLLBACK');
687
+ await this.db.query("ROLLBACK");
693
688
  throw error;
694
689
  }
695
690
  }
696
691
  return {
697
- status: 'success',
692
+ status: "success",
698
693
  data: {
699
694
  totalUpdates: updates.length,
700
695
  totalAffectedRows: totalAffected,
701
696
  batches: results.length,
702
- batchResults: results
703
- }
697
+ batchResults: results,
698
+ },
704
699
  };
705
700
  }
706
701
  catch (error) {
707
702
  return {
708
- status: 'error',
709
- error: error.message
703
+ status: "error",
704
+ error: error.message,
710
705
  };
711
706
  }
712
707
  }
@@ -717,8 +712,8 @@ class CrudTools {
717
712
  // Validate input schema
718
713
  if (!(0, schemas_1.validateBulkDelete)(params)) {
719
714
  return {
720
- status: 'error',
721
- error: 'Invalid parameters: ' + JSON.stringify(schemas_1.validateBulkDelete.errors)
715
+ status: "error",
716
+ error: "Invalid parameters: " + JSON.stringify(schemas_1.validateBulkDelete.errors),
722
717
  };
723
718
  }
724
719
  try {
@@ -727,15 +722,15 @@ class CrudTools {
727
722
  const tableValidation = this.security.validateIdentifier(table_name);
728
723
  if (!tableValidation.valid) {
729
724
  return {
730
- status: 'error',
731
- error: `Invalid table name: ${tableValidation.error}`
725
+ status: "error",
726
+ error: `Invalid table name: ${tableValidation.error}`,
732
727
  };
733
728
  }
734
729
  // Ensure condition_sets is not empty
735
730
  if (!condition_sets || condition_sets.length === 0) {
736
731
  return {
737
- status: 'error',
738
- error: 'Condition sets array cannot be empty'
732
+ status: "error",
733
+ error: "Condition sets array cannot be empty",
739
734
  };
740
735
  }
741
736
  // Validate each condition set
@@ -744,8 +739,8 @@ class CrudTools {
744
739
  // Ensure there are conditions for safety
745
740
  if (!conditions || conditions.length === 0) {
746
741
  return {
747
- status: 'error',
748
- error: `DELETE operations require at least one condition for safety. Condition set ${i + 1} is empty.`
742
+ status: "error",
743
+ error: `DELETE operations require at least one condition for safety. Condition set ${i + 1} is empty.`,
749
744
  };
750
745
  }
751
746
  // Validate condition fields
@@ -753,8 +748,8 @@ class CrudTools {
753
748
  const fieldValidation = this.security.validateIdentifier(condition.field);
754
749
  if (!fieldValidation.valid) {
755
750
  return {
756
- status: 'error',
757
- error: `Invalid condition field '${condition.field}' in condition set ${i + 1}: ${fieldValidation.error}`
751
+ status: "error",
752
+ error: `Invalid condition field '${condition.field}' in condition set ${i + 1}: ${fieldValidation.error}`,
758
753
  };
759
754
  }
760
755
  }
@@ -765,54 +760,56 @@ class CrudTools {
765
760
  for (let i = 0; i < condition_sets.length; i += batch_size) {
766
761
  const batch = condition_sets.slice(i, i + batch_size);
767
762
  // Start a transaction for this batch
768
- await this.db.query('START TRANSACTION');
763
+ await this.db.query("START TRANSACTION");
769
764
  try {
770
765
  const batchResults = [];
771
766
  for (const conditions of batch) {
772
767
  // Build WHERE clause
773
768
  const whereConditions = [];
774
769
  const whereValues = [];
775
- conditions.forEach(condition => {
770
+ conditions.forEach((condition) => {
776
771
  const escapedField = this.security.escapeIdentifier(condition.field);
777
772
  switch (condition.operator) {
778
- case 'eq':
773
+ case "eq":
779
774
  whereConditions.push(`${escapedField} = ?`);
780
775
  whereValues.push(condition.value);
781
776
  break;
782
- case 'neq':
777
+ case "neq":
783
778
  whereConditions.push(`${escapedField} != ?`);
784
779
  whereValues.push(condition.value);
785
780
  break;
786
- case 'gt':
781
+ case "gt":
787
782
  whereConditions.push(`${escapedField} > ?`);
788
783
  whereValues.push(condition.value);
789
784
  break;
790
- case 'gte':
785
+ case "gte":
791
786
  whereConditions.push(`${escapedField} >= ?`);
792
787
  whereValues.push(condition.value);
793
788
  break;
794
- case 'lt':
789
+ case "lt":
795
790
  whereConditions.push(`${escapedField} < ?`);
796
791
  whereValues.push(condition.value);
797
792
  break;
798
- case 'lte':
793
+ case "lte":
799
794
  whereConditions.push(`${escapedField} <= ?`);
800
795
  whereValues.push(condition.value);
801
796
  break;
802
- case 'like':
797
+ case "like":
803
798
  whereConditions.push(`${escapedField} LIKE ?`);
804
799
  whereValues.push(`%${condition.value}%`);
805
800
  break;
806
- case 'in':
801
+ case "in":
807
802
  if (Array.isArray(condition.value)) {
808
- const placeholders = condition.value.map(() => '?').join(', ');
803
+ const placeholders = condition.value
804
+ .map(() => "?")
805
+ .join(", ");
809
806
  whereConditions.push(`${escapedField} IN (${placeholders})`);
810
807
  whereValues.push(...condition.value);
811
808
  }
812
809
  break;
813
810
  }
814
811
  });
815
- const whereClause = 'WHERE ' + whereConditions.join(' AND ');
812
+ const whereClause = "WHERE " + whereConditions.join(" AND ");
816
813
  // Validate all parameters
817
814
  const paramValidation = this.security.validateParameters(whereValues);
818
815
  if (!paramValidation.valid) {
@@ -823,38 +820,38 @@ class CrudTools {
823
820
  const query = `DELETE FROM ${escapedTableName} ${whereClause}`;
824
821
  const result = await this.db.query(query, paramValidation.sanitizedParams);
825
822
  batchResults.push({
826
- affectedRows: result.affectedRows
823
+ affectedRows: result.affectedRows,
827
824
  });
828
825
  totalDeleted += result.affectedRows;
829
826
  }
830
827
  // Commit the transaction
831
- await this.db.query('COMMIT');
828
+ await this.db.query("COMMIT");
832
829
  results.push({
833
830
  batchNumber: Math.floor(i / batch_size) + 1,
834
831
  deletesProcessed: batch.length,
835
- results: batchResults
832
+ results: batchResults,
836
833
  });
837
834
  }
838
835
  catch (error) {
839
836
  // Rollback on error
840
- await this.db.query('ROLLBACK');
837
+ await this.db.query("ROLLBACK");
841
838
  throw error;
842
839
  }
843
840
  }
844
841
  return {
845
- status: 'success',
842
+ status: "success",
846
843
  data: {
847
844
  totalDeletes: condition_sets.length,
848
845
  totalDeletedRows: totalDeleted,
849
846
  batches: results.length,
850
- batchResults: results
851
- }
847
+ batchResults: results,
848
+ },
852
849
  };
853
850
  }
854
851
  catch (error) {
855
852
  return {
856
- status: 'error',
857
- error: error.message
853
+ status: "error",
854
+ error: error.message,
858
855
  };
859
856
  }
860
857
  }