@garuhq/cli 0.11.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 +24 -0
- package/dist/index.cjs +26 -22
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,30 @@
|
|
|
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
|
+
|
|
16
|
+
## [0.12.0] — 2026-08-22
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **`garu scheduled-charges` now targets `/api/v1/scheduled-charges`.**
|
|
21
|
+
`list`/`attempts` pretty-print output reports `count`/`totalCount`/
|
|
22
|
+
`totalPages` instead of a `page`/`total` counter. No command flags or
|
|
23
|
+
arguments changed — scheduled-charge ids were already opaque strings
|
|
24
|
+
(`sch_...`), so this is a wire-level move, not an identifier change.
|
|
25
|
+
- **`@garuhq/node` bumped to `4.0.0`.** Breaking for
|
|
26
|
+
`garu.scheduledCharges.list()`/`.listAttempts()` (see that package's
|
|
27
|
+
changelog); `garu-cli`'s own commands are unaffected beyond the
|
|
28
|
+
pretty-print header above.
|
|
29
|
+
|
|
6
30
|
## [0.11.0] — 2026-08-22
|
|
7
31
|
|
|
8
32
|
### 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.
|
|
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;
|
|
@@ -1226,10 +1229,8 @@ function prettyScheduledCharge(c) {
|
|
|
1226
1229
|
return lines.join("\n");
|
|
1227
1230
|
}
|
|
1228
1231
|
function prettyScheduledChargeList(list) {
|
|
1229
|
-
if (list.data.length === 0)
|
|
1230
|
-
|
|
1231
|
-
}
|
|
1232
|
-
const header = `Scheduled charges (page ${list.meta.page}/${list.meta.totalPages || "?"}, ${list.meta.total} total)`;
|
|
1232
|
+
if (list.data.length === 0) return "No scheduled charges found";
|
|
1233
|
+
const header = `Scheduled charges (${list.count} of ${list.totalCount} total, ${list.totalPages} page(s))`;
|
|
1233
1234
|
const rows = list.data.map(
|
|
1234
1235
|
(c) => ` ${c.id.padEnd(20)} ${String(c.status).padEnd(18)} ${String(c.type).padEnd(9)} ${String(c.amount).padStart(10)} ${c.dueDate}`
|
|
1235
1236
|
);
|
|
@@ -1252,10 +1253,8 @@ function prettyScheduledChargeDetail(detail) {
|
|
|
1252
1253
|
return lines.join("\n");
|
|
1253
1254
|
}
|
|
1254
1255
|
function prettyAttemptList(list) {
|
|
1255
|
-
if (list.data.length === 0)
|
|
1256
|
-
|
|
1257
|
-
}
|
|
1258
|
-
const header = `Billing attempts (page ${list.meta.page}/${list.meta.totalPages || "?"}, ${list.meta.total} total)`;
|
|
1256
|
+
if (list.data.length === 0) return "No billing attempts found";
|
|
1257
|
+
const header = `Billing attempts (${list.count} of ${list.totalCount} total, ${list.totalPages} page(s))`;
|
|
1259
1258
|
const rows = list.data.map(
|
|
1260
1259
|
(a) => ` cycle ${String(a.cycleNumber).padStart(3)} #${a.attemptNumber} ${a.status.padEnd(10)} ${a.paymentMethod.padEnd(7)} ${a.failureCode ?? ""} ${a.attemptedAt}`
|
|
1261
1260
|
);
|
|
@@ -1439,13 +1438,14 @@ Recipes:
|
|
|
1439
1438
|
"--amount <reais>",
|
|
1440
1439
|
"partial refund amount in decimal BRL, e.g. 10.00",
|
|
1441
1440
|
(v) => parseNonNegativeBrl(v, "--amount")
|
|
1442
|
-
).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) => {
|
|
1443
1442
|
const base = toCommandOptions(program);
|
|
1444
1443
|
await chargesRefundCommand({
|
|
1445
1444
|
...base,
|
|
1446
1445
|
id,
|
|
1447
1446
|
amount: cmdOpts.amount,
|
|
1448
|
-
reason: cmdOpts.reason
|
|
1447
|
+
reason: cmdOpts.reason,
|
|
1448
|
+
idempotencyKey: cmdOpts.idempotencyKey
|
|
1449
1449
|
}).catch((err) => printErrorAndExit(err, base));
|
|
1450
1450
|
});
|
|
1451
1451
|
const scheduled = program.command("scheduled-charges").description("Schedule, inspect, and act on future-dated charges");
|
|
@@ -1660,7 +1660,7 @@ Recipes:
|
|
|
1660
1660
|
);
|
|
1661
1661
|
});
|
|
1662
1662
|
const customers = program.command("customers").description("Manage your customer base");
|
|
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").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) => {
|
|
1664
1664
|
const base = toCommandOptions(program);
|
|
1665
1665
|
await customersCreateCommand({
|
|
1666
1666
|
...base,
|
|
@@ -1675,7 +1675,8 @@ Recipes:
|
|
|
1675
1675
|
complement: cmdOpts.complement,
|
|
1676
1676
|
neighborhood: cmdOpts.neighborhood,
|
|
1677
1677
|
city: cmdOpts.city,
|
|
1678
|
-
state: cmdOpts.state
|
|
1678
|
+
state: cmdOpts.state,
|
|
1679
|
+
idempotencyKey: cmdOpts.idempotencyKey
|
|
1679
1680
|
}).catch((err) => printErrorAndExit(err, base));
|
|
1680
1681
|
});
|
|
1681
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(
|
|
@@ -1828,15 +1829,18 @@ Recipes:
|
|
|
1828
1829
|
"--amount <reais>",
|
|
1829
1830
|
"defaults to everything the carn\xEA has collected",
|
|
1830
1831
|
(v) => parseNonNegativeBrl(v, "--amount")
|
|
1831
|
-
).option("--reason <text>", "optional reason").
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
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
|
+
);
|
|
1840
1844
|
const refundRequests = program.command("refund-requests").description("Inspect and resolve refund requests (carn\xEA and Pix/boleto)");
|
|
1841
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(
|
|
1842
1846
|
"--status <status>",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@garuhq/cli",
|
|
3
|
-
"version": "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": "
|
|
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",
|