@inforge/migrations-tools-cli 1.1.1 → 1.2.1

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 (3) hide show
  1. package/README.md +29 -0
  2. package/dist/index.js +83 -19
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -103,6 +103,35 @@ Select "Logs" to see recent operations with status, timestamps, and details.
103
103
 
104
104
  All operations are logged to `.logs/operations.log` (JSON format, one per line).
105
105
 
106
+ ## Debugging
107
+
108
+ ### Debug Logs
109
+
110
+ When errors occur, detailed error information including stack traces and API request/response data is automatically logged to `.logs/debug.log`. The error message will show you the exact path to the debug log file.
111
+
112
+ **Example error message:**
113
+ ```
114
+ Failed to apply changes: The requested resource does not exist
115
+
116
+ Error details logged to: /path/to/your/project/.logs/debug.log
117
+ ```
118
+
119
+ ### Enable Verbose Debug Logging
120
+
121
+ For more detailed troubleshooting, enable debug mode to see all API calls and internal operations:
122
+
123
+ ```bash
124
+ DEBUG=true imigrate
125
+ ```
126
+
127
+ This will log detailed information about:
128
+ - API queries and their results
129
+ - Request/response payloads
130
+ - Internal state changes
131
+ - Detailed error contexts
132
+
133
+ Debug logs are written in JSON format with timestamps and structured context for easy analysis.
134
+
106
135
  ## Safety Features
107
136
 
108
137
  ### Atomic Operations
package/dist/index.js CHANGED
@@ -248,12 +248,15 @@ var BackupManager = class {
248
248
  // src/core/logger.ts
249
249
  import * as fs2 from "fs/promises";
250
250
  import * as path2 from "path";
251
- var Logger = class {
251
+ var Logger = class _Logger {
252
252
  logDir;
253
253
  logFile;
254
+ debugLogFile;
255
+ static debugEnabled = process.env.DEBUG === "true";
254
256
  constructor(logDir = ".logs") {
255
257
  this.logDir = logDir;
256
258
  this.logFile = path2.join(logDir, "operations.log");
259
+ this.debugLogFile = path2.join(logDir, "debug.log");
257
260
  }
258
261
  async log(operation) {
259
262
  await this.ensureLogDir();
@@ -277,6 +280,38 @@ var Logger = class {
277
280
  const random = Math.random().toString(36).substring(2, 9);
278
281
  return `op_${timestamp}${random}`;
279
282
  }
283
+ async debug(message, context) {
284
+ await this.writeDebugLog("DEBUG", message, context);
285
+ }
286
+ async info(message, context) {
287
+ await this.writeDebugLog("INFO", message, context);
288
+ }
289
+ async error(message, error, context) {
290
+ const errorDetails = error ? {
291
+ message: error.message || String(error),
292
+ stack: error.stack,
293
+ details: error.response?.data || error.details || error
294
+ } : void 0;
295
+ await this.writeDebugLog("ERROR", message, context, errorDetails);
296
+ }
297
+ getDebugLogPath() {
298
+ return path2.resolve(this.debugLogFile);
299
+ }
300
+ async writeDebugLog(level, message, context, error) {
301
+ if (!_Logger.debugEnabled && level === "DEBUG") {
302
+ return;
303
+ }
304
+ await this.ensureLogDir();
305
+ const entry = {
306
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
307
+ level,
308
+ message,
309
+ ...context && { context },
310
+ ...error && { error }
311
+ };
312
+ const logLine = JSON.stringify(entry, null, 2) + "\n---\n";
313
+ await fs2.appendFile(this.debugLogFile, logLine, "utf-8");
314
+ }
280
315
  async ensureLogDir() {
281
316
  try {
282
317
  await fs2.mkdir(this.logDir, { recursive: true });
@@ -427,6 +462,10 @@ var FlowsHandler = class {
427
462
 
428
463
  // src/core/metadata/triggers.ts
429
464
  var TriggersHandler = class {
465
+ logger;
466
+ constructor() {
467
+ this.logger = new Logger();
468
+ }
430
469
  async fetch(connection, objectName) {
431
470
  const query = `
432
471
  SELECT Id, Name, TableEnumOrId, Status, NamespacePrefix
@@ -465,25 +504,39 @@ var TriggersHandler = class {
465
504
  await this.updateStatus(connection, triggerNames, "Active");
466
505
  }
467
506
  async updateStatus(connection, triggerNames, status) {
468
- const query = `
469
- SELECT Id, Name
470
- FROM ApexTrigger
471
- WHERE Name IN (${triggerNames.map((n) => `'${n}'`).join(", ")})
472
- `;
473
- const result = await connection.tooling.query(query);
474
- if (result.records.length === 0) {
475
- throw new Error("No triggers found with the specified names");
476
- }
477
- const updates = result.records.map((trigger) => ({
478
- Id: trigger.Id,
479
- Status: status
480
- }));
481
- const results = await connection.tooling.update("ApexTrigger", updates);
482
- if (Array.isArray(results)) {
483
- const failures = results.filter((r) => !r.success);
507
+ await this.logger.debug("TriggersHandler.updateStatus called", {
508
+ triggerNames,
509
+ status
510
+ });
511
+ try {
512
+ const updates = triggerNames.map((name) => ({
513
+ fullName: name,
514
+ status
515
+ }));
516
+ await this.logger.debug("Preparing Metadata API update", { updates });
517
+ const results = await connection.metadata.update("ApexTrigger", updates);
518
+ await this.logger.debug("Metadata API update results", {
519
+ results: Array.isArray(results) ? results : [results]
520
+ });
521
+ const resultArray = Array.isArray(results) ? results : [results];
522
+ const failures = resultArray.filter((r) => !r.success);
484
523
  if (failures.length > 0) {
485
- throw new Error(`Failed to update ${failures.length} trigger(s)`);
524
+ await this.logger.error("Some triggers failed to update", null, {
525
+ failures,
526
+ totalAttempted: resultArray.length
527
+ });
528
+ throw new Error(`Failed to update ${failures.length} trigger(s): ${JSON.stringify(failures)}`);
486
529
  }
530
+ await this.logger.info("Successfully updated trigger status", {
531
+ triggerCount: triggerNames.length,
532
+ status
533
+ });
534
+ } catch (error) {
535
+ await this.logger.error("Error in updateStatus", error, {
536
+ triggerNames,
537
+ status
538
+ });
539
+ throw error;
487
540
  }
488
541
  }
489
542
  };
@@ -1199,6 +1252,14 @@ Select items to toggle (Space to select, Enter to continue):`,
1199
1252
  );
1200
1253
  } catch (error) {
1201
1254
  applySpinner.stop("Changes failed");
1255
+ await this.logger.error("Failed to apply changes in IndividualCommand", error, {
1256
+ org: org.alias,
1257
+ object: selectedObject,
1258
+ automationType,
1259
+ selectedFullNames,
1260
+ toActivate,
1261
+ toDeactivate
1262
+ });
1202
1263
  await this.logger.log({
1203
1264
  id: operationId,
1204
1265
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -1212,7 +1273,10 @@ Select items to toggle (Space to select, Enter to continue):`,
1212
1273
  backupPath,
1213
1274
  error: error.message
1214
1275
  });
1215
- this.prompts.error(`Failed to apply changes: ${error.message}`);
1276
+ const debugLogPath = this.logger.getDebugLogPath();
1277
+ this.prompts.error(`Failed to apply changes: ${error.message}
1278
+
1279
+ Error details logged to: ${debugLogPath}`);
1216
1280
  throw error;
1217
1281
  }
1218
1282
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inforge/migrations-tools-cli",
3
- "version": "1.1.1",
3
+ "version": "1.2.1",
4
4
  "description": "Inforge's interactive CLI for side-effect-free Salesforce data operations by managing automation",
5
5
  "main": "index.js",
6
6
  "type": "module",