@nmakarov/cli-toolkit 0.73.0 → 0.76.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.
@@ -2516,7 +2516,8 @@ var LEVEL_COLORS = {
2516
2516
  silly: chalk.gray,
2517
2517
  request: chalk.green,
2518
2518
  response: chalk.yellow,
2519
- progress: chalk.green,
2519
+ // Magenta stands out from white info / green request lines.
2520
+ progress: chalk.magentaBright,
2520
2521
  results: chalk.magenta
2521
2522
  };
2522
2523
  var Logger = class _Logger {
@@ -2535,7 +2536,8 @@ var Logger = class _Logger {
2535
2536
  this.updateTransport();
2536
2537
  }
2537
2538
  /**
2538
- * Configure logger options. Accepts both LoggerOptions shape and flat param names (levels string, progressWithTimes, progressThrottleMs).
2539
+ * Configure logger options. Accepts both LoggerOptions shape and flat param names
2540
+ * (levels string, progressWithTimes, progressWithRate, progressThrottleMs).
2539
2541
  */
2540
2542
  configure(options) {
2541
2543
  if (options.mode !== void 0) {
@@ -2555,10 +2557,12 @@ var Logger = class _Logger {
2555
2557
  }
2556
2558
  if (options.progress !== void 0) {
2557
2559
  if (options.progress.withTimes !== void 0) this.options.progressTimes = options.progress.withTimes;
2560
+ if (options.progress.withRate !== void 0) this.options.progressRate = options.progress.withRate;
2558
2561
  if (options.progress.throttleMs !== void 0) this.options.progressThrottle = options.progress.throttleMs;
2559
2562
  }
2560
2563
  const flat = options;
2561
2564
  if (flat.progressWithTimes !== void 0) this.options.progressTimes = flat.progressWithTimes;
2565
+ if (flat.progressWithRate !== void 0) this.options.progressRate = flat.progressWithRate;
2562
2566
  if (flat.progressThrottleMs !== void 0) this.options.progressThrottle = flat.progressThrottleMs;
2563
2567
  }
2564
2568
  /**
@@ -2575,6 +2579,7 @@ var Logger = class _Logger {
2575
2579
  timestamp: "boolean default false",
2576
2580
  levels: "string",
2577
2581
  progressWithTimes: "boolean default false",
2582
+ progressWithRate: "boolean default false",
2578
2583
  progressThrottleMs: "number"
2579
2584
  };
2580
2585
  const discovered = context.params.getAllForModule("logger", paramDefs);
@@ -2593,6 +2598,7 @@ var Logger = class _Logger {
2593
2598
  timestamp: false,
2594
2599
  levels: DEFAULT_LEVELS,
2595
2600
  progressTimes: false,
2601
+ progressRate: false,
2596
2602
  progressThrottle: void 0
2597
2603
  };
2598
2604
  }
@@ -2658,15 +2664,23 @@ var Logger = class _Logger {
2658
2664
  if (!this.startTimes[prefix ?? ""]) {
2659
2665
  this.startTimes[prefix ?? ""] = Date.now();
2660
2666
  }
2661
- if (this.options.progressTimes) {
2667
+ const wantTimes = this.options.progressTimes;
2668
+ const wantRate = this.options.progressRate;
2669
+ if (wantTimes || wantRate) {
2662
2670
  const elapsedSeconds = (Date.now() - this.startTimes[prefix ?? ""]) / 1e3;
2663
- let remaining = -1;
2664
- if (count > 1) {
2665
- const rate = elapsedSeconds / (count - 1);
2666
- remaining = (total - count) * rate;
2671
+ const intervals = count > 1 ? count - 1 : 0;
2672
+ const itemsPerSec = intervals > 0 && elapsedSeconds > 0 ? intervals / elapsedSeconds : -1;
2673
+ if (wantTimes) {
2674
+ let remaining = -1;
2675
+ if (itemsPerSec > 0) {
2676
+ remaining = (total - count) / itemsPerSec;
2677
+ }
2678
+ payload.elapsed = this.round(elapsedSeconds, 2);
2679
+ payload.remaining = remaining >= 0 ? this.round(remaining, 2) : remaining;
2680
+ }
2681
+ if (wantRate) {
2682
+ payload.rate = itemsPerSec >= 0 ? this.round(itemsPerSec, 2) : itemsPerSec;
2667
2683
  }
2668
- payload.elapsed = this.round(elapsedSeconds, 2);
2669
- payload.remaining = remaining >= 0 ? this.round(remaining, 2) : remaining;
2670
2684
  }
2671
2685
  if (count >= total) {
2672
2686
  delete this.startTimes[prefix ?? ""];
@@ -2731,10 +2745,13 @@ var Logger = class _Logger {
2731
2745
  parts.push(formatter.bold(struct.message));
2732
2746
  }
2733
2747
  if (struct.level === "progress") {
2748
+ const formatter = LEVEL_COLORS[struct.level];
2734
2749
  if (struct.elapsed !== void 0 && struct.remaining !== void 0) {
2735
- const formatter = LEVEL_COLORS[struct.level];
2736
2750
  parts.push(formatter(`${struct.elapsed}/${struct.remaining}`));
2737
2751
  }
2752
+ if (struct.rate !== void 0) {
2753
+ parts.push(formatter(struct.rate >= 0 ? `${struct.rate}/s` : "-/s"));
2754
+ }
2738
2755
  }
2739
2756
  if (struct.chunks && struct.chunks.length) {
2740
2757
  parts.push(this.inspectChunks(struct.chunks));
@@ -2794,6 +2811,7 @@ function setup(opts = {}) {
2794
2811
  const partialContext = {
2795
2812
  emitter: new EventEmitter(),
2796
2813
  isStop: () => false,
2814
+ isKill: () => false,
2797
2815
  cleanupFunctions: [],
2798
2816
  registerCleanup: (fn) => {
2799
2817
  partialContext.cleanupFunctions.push(fn);
@@ -2815,6 +2833,7 @@ function setup(opts = {}) {
2815
2833
  logger,
2816
2834
  emitter: partialContext.emitter,
2817
2835
  isStop: partialContext.isStop,
2836
+ isKill: partialContext.isKill,
2818
2837
  cleanupFunctions: partialContext.cleanupFunctions,
2819
2838
  registerCleanup: partialContext.registerCleanup,
2820
2839
  // For long-running scripts (servers): with --showUsedParams=top, print
@@ -2864,6 +2883,7 @@ function printAllParameters(context) {
2864
2883
  }
2865
2884
  async function init(flow2, opts = {}) {
2866
2885
  let stop = false;
2886
+ let kill = false;
2867
2887
  let context = null;
2868
2888
  let cleanupRan = false;
2869
2889
  const runRegisteredCleanups = async (ctx) => {
@@ -2893,6 +2913,7 @@ async function init(flow2, opts = {}) {
2893
2913
  }
2894
2914
  context = setup(opts);
2895
2915
  context.isStop = () => stop;
2916
+ context.isKill = () => kill;
2896
2917
  context = await setupModules(context, opts);
2897
2918
  const stopAfter = context.args.get("stopAfter");
2898
2919
  const stopAllowanceSec = Number(context.params.get("stopAllowance", "number default 60"));
@@ -2931,6 +2952,14 @@ async function init(flow2, opts = {}) {
2931
2952
  );
2932
2953
  context.emitter.emit("stop", stopAllowanceMs);
2933
2954
  });
2955
+ process.on("SIGUSR2", () => {
2956
+ if (!context || kill) return;
2957
+ kill = true;
2958
+ stop = true;
2959
+ context.logger.warn(">> SIGUSR2: emitting kill (urgent stop)");
2960
+ context.emitter.emit("kill");
2961
+ context.emitter.emit("stop", stopAllowanceMs);
2962
+ });
2934
2963
  await flow2(context);
2935
2964
  } catch (error) {
2936
2965
  const errorLocation = error instanceof Error && error.stack ? error.stack.split("\n")[1]?.trim() || "Unknown location" : "Unknown location";
@@ -2957,7 +2986,7 @@ async function init(flow2, opts = {}) {
2957
2986
  }
2958
2987
  if (process.exitCode && process.exitCode !== 0) {
2959
2988
  process.exit(process.exitCode);
2960
- } else if (stop) {
2989
+ } else if (stop || kill) {
2961
2990
  process.exit(0);
2962
2991
  }
2963
2992
  }
@@ -6530,6 +6559,7 @@ var LOGGER_RUNTIME_KEYS = [
6530
6559
  "route",
6531
6560
  "prefix",
6532
6561
  "progressWithTimes",
6562
+ "progressWithRate",
6533
6563
  "progressThrottleMs"
6534
6564
  ];
6535
6565
  var DEFAULT_RUNTIME_PARAM_SPECS = [
@@ -6633,6 +6663,7 @@ function coerceRuntimeValue(key, value) {
6633
6663
  case "showLevel":
6634
6664
  case "timestamp":
6635
6665
  case "progressWithTimes":
6666
+ case "progressWithRate":
6636
6667
  if (typeof value === "boolean") return value;
6637
6668
  if (value === "true" || value === "1") return true;
6638
6669
  if (value === "false" || value === "0") return false;