@garuhq/cli 0.9.0 → 0.10.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 +16 -1
- package/README.md +37 -0
- package/dist/index.cjs +223 -37
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,21 @@
|
|
|
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.10.0] — 2026-08-22
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- **`garu customers` — manage your customer base.** `create`, `list`, `get`,
|
|
11
|
+
`update`, `set-billing-email`, `clear-billing-email`, `delete`. Backed by
|
|
12
|
+
the new `/api/v1/customers`, keyed on `uuid`.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- **`@garuhq/node` bumped to `2.0.0`.** Breaking for `garu.customers.*` (see
|
|
17
|
+
that package's changelog); does not affect any other `garu-cli` command —
|
|
18
|
+
`customers` is a new command group in this release, so nothing here
|
|
19
|
+
changes behavior.
|
|
20
|
+
|
|
6
21
|
## [0.9.0] — 2026-08-21
|
|
7
22
|
|
|
8
23
|
### Added
|
|
@@ -42,7 +57,7 @@ All notable changes to `@garuhq/cli` are documented in this file. Format:
|
|
|
42
57
|
`.expiresAt` (was `.date` / `.deadline`), and a new `charge.chargedTotal`
|
|
43
58
|
field (what was actually charged, vs. `.amount`, the product's base
|
|
44
59
|
price). `charges list`'s response shape is now `{ data, count, totalCount,
|
|
45
|
-
|
|
60
|
+
totalPages }` (was `{ data, meta }`).
|
|
46
61
|
|
|
47
62
|
## [0.8.0] — 2026-07-18
|
|
48
63
|
|
package/README.md
CHANGED
|
@@ -402,6 +402,43 @@ garu refund-requests reject a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
|
|
|
402
402
|
|
|
403
403
|
---
|
|
404
404
|
|
|
405
|
+
### `garu customers create`
|
|
406
|
+
|
|
407
|
+
Register a customer for the current seller. Registering the same `document`
|
|
408
|
+
twice attaches your profile to the existing global customer instead of
|
|
409
|
+
erroring — safe to call once per seller per person.
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
garu customers create \
|
|
413
|
+
--name "Maria Silva" --email maria@exemplo.com.br \
|
|
414
|
+
--document 12345678909 --phone 11987654321 \
|
|
415
|
+
--person-type fisica
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
| Flag | Description |
|
|
419
|
+
| ----------------------- | ---------------------------------------------- |
|
|
420
|
+
| `--name <name>` | Customer name (required) |
|
|
421
|
+
| `--email <email>` | Customer email (required) |
|
|
422
|
+
| `--document <document>` | CPF (11 digits) or CNPJ (14 digits) (required) |
|
|
423
|
+
| `--phone <phone>` | Phone with area code, 10-11 digits (required) |
|
|
424
|
+
| `--person-type <type>` | `fisica` or `juridica` (required) |
|
|
425
|
+
| `--zip-code <cep>` etc. | Address fields (all optional) |
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
### `garu customers` — other subcommands
|
|
430
|
+
|
|
431
|
+
| Command | Description |
|
|
432
|
+
| ------------------------------------------ | ---------------------------------------------------------------- |
|
|
433
|
+
| `list [--page --limit --search --status]` | List customers (`--status overdue` filters to at-risk customers) |
|
|
434
|
+
| `get <uuid>` | Fetch a single customer |
|
|
435
|
+
| `update <uuid> [...]` | Partial update — same flags as `create`, all optional |
|
|
436
|
+
| `set-billing-email <uuid> --email <email>` | Set the sticky per-seller billing-email override |
|
|
437
|
+
| `clear-billing-email <uuid>` | Clear the override, falling back to the last-used email |
|
|
438
|
+
| `delete <uuid>` | Unlink the customer from the current seller |
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
405
442
|
### `garu doctor`
|
|
406
443
|
|
|
407
444
|
Run environment diagnostics. Verifies your CLI version, API connectivity, credentials, and detects AI agent integrations.
|
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.10.0";
|
|
19
19
|
var CliError = class extends Error {
|
|
20
20
|
code;
|
|
21
21
|
exitCode;
|
|
@@ -251,6 +251,13 @@ function parsePaymentMethod(raw) {
|
|
|
251
251
|
function toChargePaymentMethod(type) {
|
|
252
252
|
return type === "credit_card" ? "creditCard" : type;
|
|
253
253
|
}
|
|
254
|
+
function parsePersonType(raw) {
|
|
255
|
+
if (raw === "fisica" || raw === "juridica") return raw;
|
|
256
|
+
throw new CliError(
|
|
257
|
+
"invalid_input",
|
|
258
|
+
`--person-type must be 'fisica' or 'juridica' (got '${raw}')`
|
|
259
|
+
);
|
|
260
|
+
}
|
|
254
261
|
function parseChargePaymentMethodFilter(raw) {
|
|
255
262
|
return toChargePaymentMethod(parsePaymentMethod(raw));
|
|
256
263
|
}
|
|
@@ -523,6 +530,108 @@ function prettyCharge(charge) {
|
|
|
523
530
|
lines.push(` refund: ${charge.refund.amount} (${charge.refund.reason ?? "no reason"})`);
|
|
524
531
|
return lines.join("\n");
|
|
525
532
|
}
|
|
533
|
+
|
|
534
|
+
// src/commands/customers.ts
|
|
535
|
+
async function getClient2(opts) {
|
|
536
|
+
if (opts.garu) return opts.garu;
|
|
537
|
+
const auth = await resolveAuth({
|
|
538
|
+
...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
|
|
539
|
+
...opts.profile !== void 0 ? { profile: opts.profile } : {}
|
|
540
|
+
});
|
|
541
|
+
return createGaruClient({
|
|
542
|
+
auth,
|
|
543
|
+
...opts.baseUrl !== void 0 ? { baseUrl: opts.baseUrl } : {}
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
async function customersCreateCommand(opts) {
|
|
547
|
+
const garu = await getClient2(opts);
|
|
548
|
+
const params = {
|
|
549
|
+
name: opts.name,
|
|
550
|
+
email: opts.email,
|
|
551
|
+
document: opts.document,
|
|
552
|
+
phone: opts.phone,
|
|
553
|
+
personType: opts.personType
|
|
554
|
+
};
|
|
555
|
+
if (opts.zipCode !== void 0) params.zipCode = opts.zipCode;
|
|
556
|
+
if (opts.street !== void 0) params.street = opts.street;
|
|
557
|
+
if (opts.number !== void 0) params.number = opts.number;
|
|
558
|
+
if (opts.complement !== void 0) params.complement = opts.complement;
|
|
559
|
+
if (opts.neighborhood !== void 0) params.neighborhood = opts.neighborhood;
|
|
560
|
+
if (opts.city !== void 0) params.city = opts.city;
|
|
561
|
+
if (opts.state !== void 0) params.state = opts.state;
|
|
562
|
+
const customer = await garu.customers.create(params);
|
|
563
|
+
printResult(customer, { ...opts, prettyPrint: prettyCustomer });
|
|
564
|
+
return customer;
|
|
565
|
+
}
|
|
566
|
+
async function customersListCommand(opts) {
|
|
567
|
+
const garu = await getClient2(opts);
|
|
568
|
+
const params = {};
|
|
569
|
+
if (opts.page !== void 0) params.page = opts.page;
|
|
570
|
+
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
571
|
+
if (opts.search !== void 0) params.search = opts.search;
|
|
572
|
+
if (opts.status !== void 0) params.status = opts.status;
|
|
573
|
+
const result = await garu.customers.list(params);
|
|
574
|
+
printResult(result, { ...opts, prettyPrint: prettyCustomerList });
|
|
575
|
+
return result;
|
|
576
|
+
}
|
|
577
|
+
async function customersGetCommand(opts) {
|
|
578
|
+
const garu = await getClient2(opts);
|
|
579
|
+
const customer = await garu.customers.get(opts.uuid);
|
|
580
|
+
printResult(customer, { ...opts, prettyPrint: prettyCustomer });
|
|
581
|
+
return customer;
|
|
582
|
+
}
|
|
583
|
+
async function customersUpdateCommand(opts) {
|
|
584
|
+
const garu = await getClient2(opts);
|
|
585
|
+
const params = {};
|
|
586
|
+
if (opts.name !== void 0) params.name = opts.name;
|
|
587
|
+
if (opts.email !== void 0) params.email = opts.email;
|
|
588
|
+
if (opts.phone !== void 0) params.phone = opts.phone;
|
|
589
|
+
if (opts.document !== void 0) params.document = opts.document;
|
|
590
|
+
if (opts.personType !== void 0) params.personType = opts.personType;
|
|
591
|
+
if (opts.zipCode !== void 0) params.zipCode = opts.zipCode;
|
|
592
|
+
if (opts.street !== void 0) params.street = opts.street;
|
|
593
|
+
if (opts.number !== void 0) params.number = opts.number;
|
|
594
|
+
if (opts.complement !== void 0) params.complement = opts.complement;
|
|
595
|
+
if (opts.neighborhood !== void 0) params.neighborhood = opts.neighborhood;
|
|
596
|
+
if (opts.city !== void 0) params.city = opts.city;
|
|
597
|
+
if (opts.state !== void 0) params.state = opts.state;
|
|
598
|
+
const customer = await garu.customers.update(opts.uuid, params);
|
|
599
|
+
printResult(customer, { ...opts, prettyPrint: prettyCustomer });
|
|
600
|
+
return customer;
|
|
601
|
+
}
|
|
602
|
+
async function customersSetBillingEmailOverrideCommand(opts) {
|
|
603
|
+
const garu = await getClient2(opts);
|
|
604
|
+
const params = {
|
|
605
|
+
billingEmailOverride: opts.billingEmailOverride
|
|
606
|
+
};
|
|
607
|
+
const customer = await garu.customers.setBillingEmailOverride(opts.uuid, params);
|
|
608
|
+
printResult(customer, { ...opts, prettyPrint: prettyCustomer });
|
|
609
|
+
return customer;
|
|
610
|
+
}
|
|
611
|
+
async function customersDeleteCommand(opts) {
|
|
612
|
+
const garu = await getClient2(opts);
|
|
613
|
+
const result = await garu.customers.delete(opts.uuid);
|
|
614
|
+
printResult(result, { ...opts });
|
|
615
|
+
return result;
|
|
616
|
+
}
|
|
617
|
+
function prettyCustomerList(list) {
|
|
618
|
+
if (list.data.length === 0) return "No customers found";
|
|
619
|
+
const header = `Customers (${list.count} of ${list.totalCount} total, ${list.totalPages} page(s))`;
|
|
620
|
+
const rows = list.data.map((c) => ` ${c.uuid} ${c.name.padEnd(30)} ${c.email}`);
|
|
621
|
+
return [header, ...rows].join("\n");
|
|
622
|
+
}
|
|
623
|
+
function prettyCustomer(c) {
|
|
624
|
+
const lines = [
|
|
625
|
+
`Customer ${c.uuid}`,
|
|
626
|
+
` name: ${c.name}`,
|
|
627
|
+
` email: ${c.email}`,
|
|
628
|
+
` phone: ${c.phone}`,
|
|
629
|
+
` document: ${c.document}`,
|
|
630
|
+
` personType: ${c.personType}`,
|
|
631
|
+
` billingEmail: ${c.billingEmail}${c.hasBillingEmailOverride ? " (override)" : ""}`
|
|
632
|
+
];
|
|
633
|
+
return lines.join("\n");
|
|
634
|
+
}
|
|
526
635
|
async function doctorCommand(opts = {}) {
|
|
527
636
|
const home = opts.home ?? os.homedir();
|
|
528
637
|
const cwd = opts.cwd ?? process.cwd();
|
|
@@ -617,7 +726,7 @@ function prettyDoctor(r) {
|
|
|
617
726
|
}
|
|
618
727
|
|
|
619
728
|
// src/commands/installment-plans.ts
|
|
620
|
-
async function
|
|
729
|
+
async function getClient3(opts) {
|
|
621
730
|
if (opts.garu) return opts.garu;
|
|
622
731
|
const auth = await resolveAuth({
|
|
623
732
|
...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
|
|
@@ -629,7 +738,7 @@ async function getClient2(opts) {
|
|
|
629
738
|
});
|
|
630
739
|
}
|
|
631
740
|
async function installmentPlansCreateCommand(opts) {
|
|
632
|
-
const garu = await
|
|
741
|
+
const garu = await getClient3(opts);
|
|
633
742
|
const params = {
|
|
634
743
|
productId: opts.productId,
|
|
635
744
|
customerId: opts.customerId,
|
|
@@ -643,7 +752,7 @@ async function installmentPlansCreateCommand(opts) {
|
|
|
643
752
|
return plan;
|
|
644
753
|
}
|
|
645
754
|
async function installmentPlansListCommand(opts) {
|
|
646
|
-
const garu = await
|
|
755
|
+
const garu = await getClient3(opts);
|
|
647
756
|
const params = {};
|
|
648
757
|
if (opts.page !== void 0) params.page = opts.page;
|
|
649
758
|
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
@@ -659,19 +768,19 @@ async function installmentPlansListCommand(opts) {
|
|
|
659
768
|
return result;
|
|
660
769
|
}
|
|
661
770
|
async function installmentPlansGetCommand(opts) {
|
|
662
|
-
const garu = await
|
|
771
|
+
const garu = await getClient3(opts);
|
|
663
772
|
const plan = await garu.installmentPlans.get(opts.uuid);
|
|
664
773
|
printResult(plan, { ...opts, prettyPrint: prettyInstallmentPlanDetail });
|
|
665
774
|
return plan;
|
|
666
775
|
}
|
|
667
776
|
async function installmentPlansReissueCommand(opts) {
|
|
668
|
-
const garu = await
|
|
777
|
+
const garu = await getClient3(opts);
|
|
669
778
|
const result = await garu.installmentPlans.reissueInstallment(opts.uuid, opts.number);
|
|
670
779
|
printResult(result, { ...opts, prettyPrint: prettyReissueResult });
|
|
671
780
|
return result;
|
|
672
781
|
}
|
|
673
782
|
async function installmentPlansPostponeCommand(opts) {
|
|
674
|
-
const garu = await
|
|
783
|
+
const garu = await getClient3(opts);
|
|
675
784
|
const params = { newDueDate: opts.newDueDate };
|
|
676
785
|
const installment = await garu.installmentPlans.postponeInstallment(
|
|
677
786
|
opts.uuid,
|
|
@@ -682,13 +791,13 @@ async function installmentPlansPostponeCommand(opts) {
|
|
|
682
791
|
return installment;
|
|
683
792
|
}
|
|
684
793
|
async function installmentPlansMarkPaidCommand(opts) {
|
|
685
|
-
const garu = await
|
|
794
|
+
const garu = await getClient3(opts);
|
|
686
795
|
const installment = await garu.installmentPlans.markInstallmentPaid(opts.uuid, opts.number);
|
|
687
796
|
printResult(installment, { ...opts, prettyPrint: prettyInstallment });
|
|
688
797
|
return installment;
|
|
689
798
|
}
|
|
690
799
|
async function installmentPlansCancelCommand(opts) {
|
|
691
|
-
const garu = await
|
|
800
|
+
const garu = await getClient3(opts);
|
|
692
801
|
const params = {};
|
|
693
802
|
if (opts.note !== void 0) params.note = opts.note;
|
|
694
803
|
const plan = await garu.installmentPlans.cancel(opts.uuid, params);
|
|
@@ -696,7 +805,7 @@ async function installmentPlansCancelCommand(opts) {
|
|
|
696
805
|
return plan;
|
|
697
806
|
}
|
|
698
807
|
async function installmentPlansRequestRefundCommand(opts) {
|
|
699
|
-
const garu = await
|
|
808
|
+
const garu = await getClient3(opts);
|
|
700
809
|
const params = {};
|
|
701
810
|
if (opts.amount !== void 0) params.amount = opts.amount;
|
|
702
811
|
if (opts.reason !== void 0) params.reason = opts.reason;
|
|
@@ -808,7 +917,7 @@ async function logoutCommand(opts = {}) {
|
|
|
808
917
|
}
|
|
809
918
|
|
|
810
919
|
// src/commands/products.ts
|
|
811
|
-
async function
|
|
920
|
+
async function getClient4(opts) {
|
|
812
921
|
if (opts.garu) return opts.garu;
|
|
813
922
|
const auth = await resolveAuth({
|
|
814
923
|
...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
|
|
@@ -839,7 +948,7 @@ function buildProductBody(opts) {
|
|
|
839
948
|
return body;
|
|
840
949
|
}
|
|
841
950
|
async function productsCreateCommand(opts) {
|
|
842
|
-
const garu = await
|
|
951
|
+
const garu = await getClient4(opts);
|
|
843
952
|
const params = { ...buildProductBody(opts), name: opts.name };
|
|
844
953
|
const product = await garu.products.create(params);
|
|
845
954
|
printSuccess(`Created product ${product.uuid ?? product.id}`, opts);
|
|
@@ -851,7 +960,7 @@ async function productsUpdateCommand(opts) {
|
|
|
851
960
|
if (Object.keys(body).length === 0) {
|
|
852
961
|
throw new CliError("invalid_input", "Nothing to update \u2014 pass at least one field to change.");
|
|
853
962
|
}
|
|
854
|
-
const garu = await
|
|
963
|
+
const garu = await getClient4(opts);
|
|
855
964
|
const product = await garu.products.update(opts.id, body);
|
|
856
965
|
printSuccess(`Updated product ${product.uuid ?? product.id}`, opts);
|
|
857
966
|
printResult(product, { ...opts, prettyPrint: prettyProduct });
|
|
@@ -875,7 +984,7 @@ function prettyProduct(p) {
|
|
|
875
984
|
}
|
|
876
985
|
|
|
877
986
|
// src/commands/refund-requests.ts
|
|
878
|
-
async function
|
|
987
|
+
async function getClient5(opts) {
|
|
879
988
|
if (opts.garu) return opts.garu;
|
|
880
989
|
const auth = await resolveAuth({
|
|
881
990
|
...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
|
|
@@ -887,7 +996,7 @@ async function getClient4(opts) {
|
|
|
887
996
|
});
|
|
888
997
|
}
|
|
889
998
|
async function refundRequestsListCommand(opts) {
|
|
890
|
-
const garu = await
|
|
999
|
+
const garu = await getClient5(opts);
|
|
891
1000
|
const params = {};
|
|
892
1001
|
if (opts.page !== void 0) params.page = opts.page;
|
|
893
1002
|
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
@@ -901,13 +1010,13 @@ async function refundRequestsListCommand(opts) {
|
|
|
901
1010
|
return result;
|
|
902
1011
|
}
|
|
903
1012
|
async function refundRequestsGetCommand(opts) {
|
|
904
|
-
const garu = await
|
|
1013
|
+
const garu = await getClient5(opts);
|
|
905
1014
|
const request = await garu.refundRequests.get(opts.uuid);
|
|
906
1015
|
printResult(request, { ...opts, prettyPrint: prettyRefundRequest2 });
|
|
907
1016
|
return request;
|
|
908
1017
|
}
|
|
909
1018
|
async function refundRequestsConfirmCommand(opts) {
|
|
910
|
-
const garu = await
|
|
1019
|
+
const garu = await getClient5(opts);
|
|
911
1020
|
const params = {};
|
|
912
1021
|
if (opts.note !== void 0) params.note = opts.note;
|
|
913
1022
|
const request = await garu.refundRequests.confirm(opts.uuid, params);
|
|
@@ -915,7 +1024,7 @@ async function refundRequestsConfirmCommand(opts) {
|
|
|
915
1024
|
return request;
|
|
916
1025
|
}
|
|
917
1026
|
async function refundRequestsRejectCommand(opts) {
|
|
918
|
-
const garu = await
|
|
1027
|
+
const garu = await getClient5(opts);
|
|
919
1028
|
const params = {};
|
|
920
1029
|
if (opts.note !== void 0) params.note = opts.note;
|
|
921
1030
|
const request = await garu.refundRequests.reject(opts.uuid, params);
|
|
@@ -941,7 +1050,7 @@ function prettyRefundRequest2(r) {
|
|
|
941
1050
|
}
|
|
942
1051
|
|
|
943
1052
|
// src/commands/scheduled-charges.ts
|
|
944
|
-
async function
|
|
1053
|
+
async function getClient6(opts) {
|
|
945
1054
|
if (opts.garu) return opts.garu;
|
|
946
1055
|
const auth = await resolveAuth({
|
|
947
1056
|
...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
|
|
@@ -978,7 +1087,7 @@ function assertPixAutomaticRequirements(opts) {
|
|
|
978
1087
|
}
|
|
979
1088
|
async function scheduledChargesCreateCommand(opts) {
|
|
980
1089
|
assertPixAutomaticRequirements(opts);
|
|
981
|
-
const garu = await
|
|
1090
|
+
const garu = await getClient6(opts);
|
|
982
1091
|
const params = {
|
|
983
1092
|
customerId: opts.customerId,
|
|
984
1093
|
amount: opts.amount,
|
|
@@ -1000,7 +1109,7 @@ async function scheduledChargesCreateCommand(opts) {
|
|
|
1000
1109
|
return charge;
|
|
1001
1110
|
}
|
|
1002
1111
|
async function scheduledChargesListCommand(opts) {
|
|
1003
|
-
const garu = await
|
|
1112
|
+
const garu = await getClient6(opts);
|
|
1004
1113
|
const params = {};
|
|
1005
1114
|
if (opts.page !== void 0) params.page = opts.page;
|
|
1006
1115
|
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
@@ -1017,13 +1126,13 @@ async function scheduledChargesListCommand(opts) {
|
|
|
1017
1126
|
return result;
|
|
1018
1127
|
}
|
|
1019
1128
|
async function scheduledChargesGetCommand(opts) {
|
|
1020
|
-
const garu = await
|
|
1129
|
+
const garu = await getClient6(opts);
|
|
1021
1130
|
const detail = await garu.scheduledCharges.get(opts.id);
|
|
1022
1131
|
printResult(detail, { ...opts, prettyPrint: prettyScheduledChargeDetail });
|
|
1023
1132
|
return detail;
|
|
1024
1133
|
}
|
|
1025
1134
|
async function scheduledChargesPostponeCommand(opts) {
|
|
1026
|
-
const garu = await
|
|
1135
|
+
const garu = await getClient6(opts);
|
|
1027
1136
|
const params = { newDueDate: opts.newDueDate };
|
|
1028
1137
|
if (opts.reason !== void 0) params.reason = opts.reason;
|
|
1029
1138
|
const charge = await garu.scheduledCharges.postpone(opts.id, params);
|
|
@@ -1031,7 +1140,7 @@ async function scheduledChargesPostponeCommand(opts) {
|
|
|
1031
1140
|
return charge;
|
|
1032
1141
|
}
|
|
1033
1142
|
async function scheduledChargesPauseCommand(opts) {
|
|
1034
|
-
const garu = await
|
|
1143
|
+
const garu = await getClient6(opts);
|
|
1035
1144
|
const params = {};
|
|
1036
1145
|
if (opts.reason !== void 0) params.reason = opts.reason;
|
|
1037
1146
|
const charge = await garu.scheduledCharges.pause(opts.id, params);
|
|
@@ -1039,13 +1148,13 @@ async function scheduledChargesPauseCommand(opts) {
|
|
|
1039
1148
|
return charge;
|
|
1040
1149
|
}
|
|
1041
1150
|
async function scheduledChargesResumeCommand(opts) {
|
|
1042
|
-
const garu = await
|
|
1151
|
+
const garu = await getClient6(opts);
|
|
1043
1152
|
const charge = await garu.scheduledCharges.resume(opts.id);
|
|
1044
1153
|
printResult(charge, { ...opts, prettyPrint: prettyScheduledCharge });
|
|
1045
1154
|
return charge;
|
|
1046
1155
|
}
|
|
1047
1156
|
async function scheduledChargesMarkPaidCommand(opts) {
|
|
1048
|
-
const garu = await
|
|
1157
|
+
const garu = await getClient6(opts);
|
|
1049
1158
|
const params = { paymentDate: opts.paymentDate };
|
|
1050
1159
|
if (opts.externalReference !== void 0) params.externalReference = opts.externalReference;
|
|
1051
1160
|
if (opts.cycleNumber !== void 0) params.cycleNumber = opts.cycleNumber;
|
|
@@ -1054,7 +1163,7 @@ async function scheduledChargesMarkPaidCommand(opts) {
|
|
|
1054
1163
|
return charge;
|
|
1055
1164
|
}
|
|
1056
1165
|
async function scheduledChargesCancelRecurrenceCommand(opts) {
|
|
1057
|
-
const garu = await
|
|
1166
|
+
const garu = await getClient6(opts);
|
|
1058
1167
|
const params = {};
|
|
1059
1168
|
if (opts.reason !== void 0) params.reason = opts.reason;
|
|
1060
1169
|
const charge = await garu.scheduledCharges.cancelRecurrence(opts.id, params);
|
|
@@ -1062,14 +1171,14 @@ async function scheduledChargesCancelRecurrenceCommand(opts) {
|
|
|
1062
1171
|
return charge;
|
|
1063
1172
|
}
|
|
1064
1173
|
async function scheduledChargesCancelAtPeriodEndCommand(opts) {
|
|
1065
|
-
const garu = await
|
|
1174
|
+
const garu = await getClient6(opts);
|
|
1066
1175
|
const params = { enabled: opts.enabled };
|
|
1067
1176
|
const charge = await garu.scheduledCharges.setCancelAtPeriodEnd(opts.id, params);
|
|
1068
1177
|
printResult(charge, { ...opts, prettyPrint: prettyScheduledCharge });
|
|
1069
1178
|
return charge;
|
|
1070
1179
|
}
|
|
1071
1180
|
async function scheduledChargesChangePaymentMethodCommand(opts) {
|
|
1072
|
-
const garu = await
|
|
1181
|
+
const garu = await getClient6(opts);
|
|
1073
1182
|
const params = {
|
|
1074
1183
|
paymentMethodId: opts.paymentMethodId
|
|
1075
1184
|
};
|
|
@@ -1078,13 +1187,13 @@ async function scheduledChargesChangePaymentMethodCommand(opts) {
|
|
|
1078
1187
|
return charge;
|
|
1079
1188
|
}
|
|
1080
1189
|
async function scheduledChargesClearPaymentMethodCommand(opts) {
|
|
1081
|
-
const garu = await
|
|
1190
|
+
const garu = await getClient6(opts);
|
|
1082
1191
|
const charge = await garu.scheduledCharges.clearPaymentMethod(opts.id);
|
|
1083
1192
|
printResult(charge, { ...opts, prettyPrint: prettyScheduledCharge });
|
|
1084
1193
|
return charge;
|
|
1085
1194
|
}
|
|
1086
1195
|
async function scheduledChargesAttemptsCommand(opts) {
|
|
1087
|
-
const garu = await
|
|
1196
|
+
const garu = await getClient6(opts);
|
|
1088
1197
|
const params = {};
|
|
1089
1198
|
if (opts.page !== void 0) params.page = opts.page;
|
|
1090
1199
|
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
@@ -1094,7 +1203,7 @@ async function scheduledChargesAttemptsCommand(opts) {
|
|
|
1094
1203
|
return result;
|
|
1095
1204
|
}
|
|
1096
1205
|
async function scheduledChargesChargeNowCommand(opts) {
|
|
1097
|
-
const garu = await
|
|
1206
|
+
const garu = await getClient6(opts);
|
|
1098
1207
|
const result = await garu.scheduledCharges.chargeNow(opts.id);
|
|
1099
1208
|
printResult(result, { ...opts, prettyPrint: prettyChargeNow });
|
|
1100
1209
|
if (result.outcome === "failed" || result.outcome === "not_sent") {
|
|
@@ -1158,7 +1267,7 @@ function prettyChargeNow(result) {
|
|
|
1158
1267
|
if (result.reason) lines.push(` reason: ${result.reason}`);
|
|
1159
1268
|
return lines.join("\n");
|
|
1160
1269
|
}
|
|
1161
|
-
async function
|
|
1270
|
+
async function getClient7(opts) {
|
|
1162
1271
|
if (opts.garu) return opts.garu;
|
|
1163
1272
|
const auth = await resolveAuth({
|
|
1164
1273
|
...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
|
|
@@ -1170,7 +1279,7 @@ async function getClient6(opts) {
|
|
|
1170
1279
|
});
|
|
1171
1280
|
}
|
|
1172
1281
|
async function webhooksEventsListCommand(opts) {
|
|
1173
|
-
const garu = await
|
|
1282
|
+
const garu = await getClient7(opts);
|
|
1174
1283
|
const params = {};
|
|
1175
1284
|
if (opts.page !== void 0) params.page = opts.page;
|
|
1176
1285
|
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
@@ -1182,19 +1291,19 @@ async function webhooksEventsListCommand(opts) {
|
|
|
1182
1291
|
return result;
|
|
1183
1292
|
}
|
|
1184
1293
|
async function webhooksEventsGetCommand(opts) {
|
|
1185
|
-
const garu = await
|
|
1294
|
+
const garu = await getClient7(opts);
|
|
1186
1295
|
const event = await garu.webhookEvents.get(opts.id);
|
|
1187
1296
|
printResult(event, { ...opts, prettyPrint: prettyWebhookEvent });
|
|
1188
1297
|
return event;
|
|
1189
1298
|
}
|
|
1190
1299
|
async function webhooksEventsRetryCommand(opts) {
|
|
1191
|
-
const garu = await
|
|
1300
|
+
const garu = await getClient7(opts);
|
|
1192
1301
|
const event = await garu.webhookEvents.retry(opts.id);
|
|
1193
1302
|
printResult(event, { ...opts, prettyPrint: prettyWebhookEvent });
|
|
1194
1303
|
return event;
|
|
1195
1304
|
}
|
|
1196
1305
|
async function webhooksEventsResendCommand(opts) {
|
|
1197
|
-
const garu = await
|
|
1306
|
+
const garu = await getClient7(opts);
|
|
1198
1307
|
const clone = await garu.webhookEvents.resend(opts.id);
|
|
1199
1308
|
printSuccess(`Resent event ${opts.id} \u2192 new event ${clone.id}`, opts);
|
|
1200
1309
|
printResult(clone, { ...opts, prettyPrint: prettyWebhookEvent });
|
|
@@ -1555,6 +1664,83 @@ Recipes:
|
|
|
1555
1664
|
id: parsePositiveIntId(id, "Webhook event ID")
|
|
1556
1665
|
}).catch((err) => printErrorAndExit(err, base));
|
|
1557
1666
|
});
|
|
1667
|
+
const customers = program.command("customers").description("Manage your customer base");
|
|
1668
|
+
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) => {
|
|
1669
|
+
const base = toCommandOptions(program);
|
|
1670
|
+
await customersCreateCommand({
|
|
1671
|
+
...base,
|
|
1672
|
+
name: cmdOpts.name,
|
|
1673
|
+
email: cmdOpts.email,
|
|
1674
|
+
document: cmdOpts.document,
|
|
1675
|
+
phone: cmdOpts.phone,
|
|
1676
|
+
personType: parsePersonType(cmdOpts.personType),
|
|
1677
|
+
zipCode: cmdOpts.zipCode,
|
|
1678
|
+
street: cmdOpts.street,
|
|
1679
|
+
number: cmdOpts.number,
|
|
1680
|
+
complement: cmdOpts.complement,
|
|
1681
|
+
neighborhood: cmdOpts.neighborhood,
|
|
1682
|
+
city: cmdOpts.city,
|
|
1683
|
+
state: cmdOpts.state
|
|
1684
|
+
}).catch((err) => printErrorAndExit(err, base));
|
|
1685
|
+
});
|
|
1686
|
+
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(
|
|
1687
|
+
"--status <status>",
|
|
1688
|
+
"'overdue' returns customers with at least one overdue scheduled charge"
|
|
1689
|
+
).action(
|
|
1690
|
+
async (cmdOpts) => {
|
|
1691
|
+
const base = toCommandOptions(program);
|
|
1692
|
+
await customersListCommand({
|
|
1693
|
+
...base,
|
|
1694
|
+
page: cmdOpts.page,
|
|
1695
|
+
limit: cmdOpts.limit,
|
|
1696
|
+
search: cmdOpts.search,
|
|
1697
|
+
status: cmdOpts.status === "overdue" ? "overdue" : void 0
|
|
1698
|
+
}).catch((err) => printErrorAndExit(err, base));
|
|
1699
|
+
}
|
|
1700
|
+
);
|
|
1701
|
+
customers.command("get <uuid>").description("Fetch a single customer by uuid").action(async (uuid) => {
|
|
1702
|
+
const base = toCommandOptions(program);
|
|
1703
|
+
await customersGetCommand({ ...base, uuid }).catch((err) => printErrorAndExit(err, base));
|
|
1704
|
+
});
|
|
1705
|
+
customers.command("update <uuid>").description("Partially update a customer (only the flags you pass change)").option("--name <name>", "customer name").option("--email <email>", "customer email").option("--phone <phone>", "phone with area code, 10-11 digits").option("--document <document>", "CPF (11 digits) or CNPJ (14 digits), digits only").option("--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 (uuid, cmdOpts) => {
|
|
1706
|
+
const base = toCommandOptions(program);
|
|
1707
|
+
await customersUpdateCommand({
|
|
1708
|
+
...base,
|
|
1709
|
+
uuid,
|
|
1710
|
+
name: cmdOpts.name,
|
|
1711
|
+
email: cmdOpts.email,
|
|
1712
|
+
phone: cmdOpts.phone,
|
|
1713
|
+
document: cmdOpts.document,
|
|
1714
|
+
personType: cmdOpts.personType ? parsePersonType(cmdOpts.personType) : void 0,
|
|
1715
|
+
zipCode: cmdOpts.zipCode,
|
|
1716
|
+
street: cmdOpts.street,
|
|
1717
|
+
number: cmdOpts.number,
|
|
1718
|
+
complement: cmdOpts.complement,
|
|
1719
|
+
neighborhood: cmdOpts.neighborhood,
|
|
1720
|
+
city: cmdOpts.city,
|
|
1721
|
+
state: cmdOpts.state
|
|
1722
|
+
}).catch((err) => printErrorAndExit(err, base));
|
|
1723
|
+
});
|
|
1724
|
+
customers.command("set-billing-email <uuid>").description("Set the sticky per-seller billing-email override").requiredOption("--email <email>", "the billing email to set").action(async (uuid, cmdOpts) => {
|
|
1725
|
+
const base = toCommandOptions(program);
|
|
1726
|
+
await customersSetBillingEmailOverrideCommand({
|
|
1727
|
+
...base,
|
|
1728
|
+
uuid,
|
|
1729
|
+
billingEmailOverride: cmdOpts.email
|
|
1730
|
+
}).catch((err) => printErrorAndExit(err, base));
|
|
1731
|
+
});
|
|
1732
|
+
customers.command("clear-billing-email <uuid>").description("Clear the billing-email override, falling back to the last-used email").action(async (uuid) => {
|
|
1733
|
+
const base = toCommandOptions(program);
|
|
1734
|
+
await customersSetBillingEmailOverrideCommand({
|
|
1735
|
+
...base,
|
|
1736
|
+
uuid,
|
|
1737
|
+
billingEmailOverride: null
|
|
1738
|
+
}).catch((err) => printErrorAndExit(err, base));
|
|
1739
|
+
});
|
|
1740
|
+
customers.command("delete <uuid>").description("Remove a customer from the current seller (unlinks your profile only)").action(async (uuid) => {
|
|
1741
|
+
const base = toCommandOptions(program);
|
|
1742
|
+
await customersDeleteCommand({ ...base, uuid }).catch((err) => printErrorAndExit(err, base));
|
|
1743
|
+
});
|
|
1558
1744
|
const installmentPlans = program.command("installment-plans").description("Sell a product as boleto parcelado (carn\xEA) and manage its installments");
|
|
1559
1745
|
installmentPlans.command("create").description("Sell a product as a carn\xEA (installments of boleto slips)").requiredOption("--product-id <uuid>", "product uuid (must have boleto parcelado enabled)").requiredOption(
|
|
1560
1746
|
"--customer-id <n>",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@garuhq/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.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": "2.0.0",
|
|
50
50
|
"@inquirer/prompts": "8.4.1",
|
|
51
51
|
"commander": "12.0.0",
|
|
52
52
|
"picocolors": "1.0.0",
|