@garuhq/cli 0.4.2 → 0.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,41 @@
3
3
  All notable changes to `@garuhq/cli` are documented in this file. Format:
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versioning: [SemVer](https://semver.org/).
5
5
 
6
+ ## [0.5.0] — 2026-05-19
7
+
8
+ ### Added
9
+
10
+ - `garu webhooks events resend <id>` — audit-trail-preserving replay
11
+ of a webhook event. Unlike `retry`, this does **not** mutate the
12
+ original row: the gateway inserts a fresh event with its own
13
+ numeric id that points back at the source via `manualResendOf`,
14
+ then dispatches that clone. The original failure record (response
15
+ status, response body, attempts, timestamps) stays intact.
16
+ - In pretty mode the CLI prints `✓ Resent event <src> → new event
17
+ <clone>` to stderr so the new id is impossible to miss; the
18
+ cloned event itself is rendered on stdout with a new `resendOf:`
19
+ line.
20
+ - In JSON mode the cloned event is the full stdout payload —
21
+ `.id` is the new event, `.manualResendOf` is the source.
22
+ - Recipient handlers will see this as a distinct delivery: the
23
+ gateway POSTs the clone with `Idempotency-Key:
24
+ resend_<originalId>`.
25
+
26
+ ### Deprecated
27
+
28
+ - `garu webhooks events retry <id>` — kept for backwards
29
+ compatibility but now marked `[deprecated: prefer resend]` in
30
+ `--help`. `retry` resets the original row in place, which means
31
+ once the replay succeeds the historical record of the prior
32
+ failure is gone. For incident response, support workflows, and
33
+ any backfill where the audit trail matters, use `resend` instead.
34
+
35
+ ### Changed
36
+
37
+ - `@garuhq/node` SDK bumped to 0.12.0 for the new
38
+ `webhookEvents.resend()` method and the `manualResendOf` field on
39
+ `WebhookEvent`.
40
+
6
41
  ## [0.4.2] — 2026-05-19
7
42
 
8
43
  ### Fixed
package/dist/index.cjs CHANGED
@@ -15,7 +15,7 @@ var pc__default = /*#__PURE__*/_interopDefault(pc);
15
15
  // src/index.ts
16
16
 
17
17
  // src/version.ts
18
- var CLI_VERSION = "0.4.2";
18
+ var CLI_VERSION = "0.5.0";
19
19
  var CliError = class extends Error {
20
20
  code;
21
21
  exitCode;
@@ -510,6 +510,13 @@ async function webhooksEventsRetryCommand(opts) {
510
510
  printResult(event, { ...opts, prettyPrint: prettyWebhookEvent });
511
511
  return event;
512
512
  }
513
+ async function webhooksEventsResendCommand(opts) {
514
+ const garu = await getClient2(opts);
515
+ const clone = await garu.webhookEvents.resend(opts.id);
516
+ printSuccess(`Resent event ${opts.id} \u2192 new event ${clone.id}`, opts);
517
+ printResult(clone, { ...opts, prettyPrint: prettyWebhookEvent });
518
+ return clone;
519
+ }
513
520
  function statusBadge(status) {
514
521
  const padded = status.padEnd(7);
515
522
  if (status === "success") return pc__default.default.green(padded);
@@ -535,6 +542,7 @@ function prettyWebhookEvent(event) {
535
542
  ` endpoint: [${event.webhookEndpoint.id}] ${event.webhookEndpoint.url}`,
536
543
  ` createdAt: ${event.createdAt}`
537
544
  ];
545
+ if (event.manualResendOf !== null) lines.push(` resendOf: ${event.manualResendOf}`);
538
546
  if (event.lastAttemptAt) lines.push(` lastAttemptAt: ${event.lastAttemptAt}`);
539
547
  if (event.nextRetryAt) lines.push(` nextRetryAt: ${event.nextRetryAt}`);
540
548
  if (event.responseStatus !== null) lines.push(` responseStatus: ${event.responseStatus}`);
@@ -672,13 +680,24 @@ function buildCli() {
672
680
  id: parsePositiveIntId(id, "Webhook event ID")
673
681
  }).catch((err) => printErrorAndExit(err, base));
674
682
  });
675
- events.command("retry <id>").description("Re-deliver a webhook event (resets to pending and triggers an immediate attempt)").action(async (id) => {
683
+ events.command("retry <id>").description(
684
+ "[deprecated: prefer `resend`] Re-deliver a webhook event in place (resets the original row to pending and triggers an immediate attempt; destroys the prior failure record)"
685
+ ).action(async (id) => {
676
686
  const base = toCommandOptions(program);
677
687
  await webhooksEventsRetryCommand({
678
688
  ...base,
679
689
  id: parsePositiveIntId(id, "Webhook event ID")
680
690
  }).catch((err) => printErrorAndExit(err, base));
681
691
  });
692
+ events.command("resend <id>").description(
693
+ "Re-deliver a webhook event by cloning it (audit-trail preserving: original row is untouched, clone gets a new id and points back via manualResendOf)"
694
+ ).action(async (id) => {
695
+ const base = toCommandOptions(program);
696
+ await webhooksEventsResendCommand({
697
+ ...base,
698
+ id: parsePositiveIntId(id, "Webhook event ID")
699
+ }).catch((err) => printErrorAndExit(err, base));
700
+ });
682
701
  program.command("doctor").description("Environment diagnostic").action(async () => {
683
702
  const base = toCommandOptions(program);
684
703
  await doctorCommand(base).catch((err) => printErrorAndExit(err, base));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@garuhq/cli",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "Official command-line interface for the Garu payment gateway.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://garu.com.br",
@@ -46,7 +46,7 @@
46
46
  "prepublishOnly": "npm run check:version-sync && npm run typecheck && npm test && npm run build"
47
47
  },
48
48
  "dependencies": {
49
- "@garuhq/node": "0.11.1",
49
+ "@garuhq/node": "0.12.0",
50
50
  "@inquirer/prompts": "8.4.1",
51
51
  "commander": "12.0.0",
52
52
  "picocolors": "1.0.0",