@garuhq/cli 0.12.0 → 0.13.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,16 @@
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.13.0] — 2026-08-22
7
+
8
+ ### Added
9
+
10
+ - `--idempotency-key <key>` on `garu customers create`, `garu charges refund`,
11
+ and `garu installment-plans request-refund` (auto-generated if omitted).
12
+ The gateway now dedupes all three against the header (bumped
13
+ `@garuhq/node` to 4.1.0), so a retried command can no longer register a
14
+ duplicate customer or open a second refund request.
15
+
6
16
  ## [0.12.0] — 2026-08-22
7
17
 
8
18
  ### Changed
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.12.0";
18
+ var CLI_VERSION = "0.13.0";
19
19
  var CliError = class extends Error {
20
20
  code;
21
21
  exitCode;
@@ -490,6 +490,7 @@ async function chargesRefundCommand(opts) {
490
490
  const params = {};
491
491
  if (opts.amount !== void 0) params.amount = opts.amount;
492
492
  if (opts.reason !== void 0) params.reason = opts.reason;
493
+ if (opts.idempotencyKey !== void 0) params.idempotencyKey = opts.idempotencyKey;
493
494
  const charge = await garu.charges.refund(opts.id, params);
494
495
  printResult(charge, { ...opts, prettyPrint: prettyCharge });
495
496
  return charge;
@@ -559,6 +560,7 @@ async function customersCreateCommand(opts) {
559
560
  if (opts.neighborhood !== void 0) params.neighborhood = opts.neighborhood;
560
561
  if (opts.city !== void 0) params.city = opts.city;
561
562
  if (opts.state !== void 0) params.state = opts.state;
563
+ if (opts.idempotencyKey !== void 0) params.idempotencyKey = opts.idempotencyKey;
562
564
  const customer = await garu.customers.create(params);
563
565
  printResult(customer, { ...opts, prettyPrint: prettyCustomer });
564
566
  return customer;
@@ -809,6 +811,7 @@ async function installmentPlansRequestRefundCommand(opts) {
809
811
  const params = {};
810
812
  if (opts.amount !== void 0) params.amount = opts.amount;
811
813
  if (opts.reason !== void 0) params.reason = opts.reason;
814
+ if (opts.idempotencyKey !== void 0) params.idempotencyKey = opts.idempotencyKey;
812
815
  const request = await garu.installmentPlans.requestRefund(opts.uuid, params);
813
816
  printResult(request, { ...opts, prettyPrint: prettyRefundRequest });
814
817
  return request;
@@ -1435,13 +1438,14 @@ Recipes:
1435
1438
  "--amount <reais>",
1436
1439
  "partial refund amount in decimal BRL, e.g. 10.00",
1437
1440
  (v) => parseNonNegativeBrl(v, "--amount")
1438
- ).option("--reason <text>", "optional refund reason").action(async (id, cmdOpts) => {
1441
+ ).option("--reason <text>", "optional refund reason").option("--idempotency-key <key>", "idempotency key (auto-generated if omitted)").action(async (id, cmdOpts) => {
1439
1442
  const base = toCommandOptions(program);
1440
1443
  await chargesRefundCommand({
1441
1444
  ...base,
1442
1445
  id,
1443
1446
  amount: cmdOpts.amount,
1444
- reason: cmdOpts.reason
1447
+ reason: cmdOpts.reason,
1448
+ idempotencyKey: cmdOpts.idempotencyKey
1445
1449
  }).catch((err) => printErrorAndExit(err, base));
1446
1450
  });
1447
1451
  const scheduled = program.command("scheduled-charges").description("Schedule, inspect, and act on future-dated charges");
@@ -1656,7 +1660,7 @@ Recipes:
1656
1660
  );
1657
1661
  });
1658
1662
  const customers = program.command("customers").description("Manage your customer base");
1659
- customers.command("create").description("Register a customer for the current seller (dedup by document)").requiredOption("--name <name>", "customer name").requiredOption("--email <email>", "customer email").requiredOption("--document <document>", "CPF (11 digits) or CNPJ (14 digits), digits only").requiredOption("--phone <phone>", "phone with area code, 10-11 digits").requiredOption("--person-type <type>", "'fisica' or 'juridica'").option("--zip-code <cep>", "ZIP code, 8 digits").option("--street <street>", "street address").option("--number <number>", "address number").option("--complement <text>", "address complement").option("--neighborhood <text>", "neighborhood").option("--city <city>", "city").option("--state <uf>", "2-letter state code, e.g. SP").action(async (cmdOpts) => {
1663
+ customers.command("create").description("Register a customer for the current seller (dedup by document)").requiredOption("--name <name>", "customer name").requiredOption("--email <email>", "customer email").requiredOption("--document <document>", "CPF (11 digits) or CNPJ (14 digits), digits only").requiredOption("--phone <phone>", "phone with area code, 10-11 digits").requiredOption("--person-type <type>", "'fisica' or 'juridica'").option("--zip-code <cep>", "ZIP code, 8 digits").option("--street <street>", "street address").option("--number <number>", "address number").option("--complement <text>", "address complement").option("--neighborhood <text>", "neighborhood").option("--city <city>", "city").option("--state <uf>", "2-letter state code, e.g. SP").option("--idempotency-key <key>", "idempotency key (auto-generated if omitted)").action(async (cmdOpts) => {
1660
1664
  const base = toCommandOptions(program);
1661
1665
  await customersCreateCommand({
1662
1666
  ...base,
@@ -1671,7 +1675,8 @@ Recipes:
1671
1675
  complement: cmdOpts.complement,
1672
1676
  neighborhood: cmdOpts.neighborhood,
1673
1677
  city: cmdOpts.city,
1674
- state: cmdOpts.state
1678
+ state: cmdOpts.state,
1679
+ idempotencyKey: cmdOpts.idempotencyKey
1675
1680
  }).catch((err) => printErrorAndExit(err, base));
1676
1681
  });
1677
1682
  customers.command("list").description("List customers with pagination and search").option("--page <n>", "page number (1-based)", (v) => parseInt(v, 10)).option("--limit <n>", "items per page (1-100)", (v) => parseInt(v, 10)).option("--search <query>", "search by name, email, or document").option(
@@ -1824,15 +1829,18 @@ Recipes:
1824
1829
  "--amount <reais>",
1825
1830
  "defaults to everything the carn\xEA has collected",
1826
1831
  (v) => parseNonNegativeBrl(v, "--amount")
1827
- ).option("--reason <text>", "optional reason").action(async (uuid, cmdOpts) => {
1828
- const base = toCommandOptions(program);
1829
- await installmentPlansRequestRefundCommand({
1830
- ...base,
1831
- uuid,
1832
- amount: cmdOpts.amount,
1833
- reason: cmdOpts.reason
1834
- }).catch((err) => printErrorAndExit(err, base));
1835
- });
1832
+ ).option("--reason <text>", "optional reason").option("--idempotency-key <key>", "idempotency key (auto-generated if omitted)").action(
1833
+ async (uuid, cmdOpts) => {
1834
+ const base = toCommandOptions(program);
1835
+ await installmentPlansRequestRefundCommand({
1836
+ ...base,
1837
+ uuid,
1838
+ amount: cmdOpts.amount,
1839
+ reason: cmdOpts.reason,
1840
+ idempotencyKey: cmdOpts.idempotencyKey
1841
+ }).catch((err) => printErrorAndExit(err, base));
1842
+ }
1843
+ );
1836
1844
  const refundRequests = program.command("refund-requests").description("Inspect and resolve refund requests (carn\xEA and Pix/boleto)");
1837
1845
  refundRequests.command("list").description("List refund requests with pagination and filters").option("--page <n>", "page number (1-based)", (v) => parseInt(v, 10)).option("--limit <n>", "items per page (1-100)", (v) => parseInt(v, 10)).option("--plan-id <uuid>", "filter by carn\xEA uuid").option("--charge-id <uuid>", "filter by charge uuid (Pix/boleto)").option(
1838
1846
  "--status <status>",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@garuhq/cli",
3
- "version": "0.12.0",
3
+ "version": "0.13.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": "4.0.0",
49
+ "@garuhq/node": "4.1.0",
50
50
  "@inquirer/prompts": "8.4.1",
51
51
  "commander": "12.0.0",
52
52
  "picocolors": "1.0.0",