@garuhq/cli 0.6.0 → 0.8.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,50 @@
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.8.0] — 2026-07-18
7
+
8
+ ### Changed
9
+
10
+ - **Products now use the versioned public API.** Via `@garuhq/node@0.16.0`,
11
+ `garu products create` / `update` hit `/api/v1/products` (uuid-keyed). The
12
+ numeric product id is no longer returned; product output shows the `uuid`.
13
+
14
+ ### Fixed
15
+
16
+ - **`--value` is Reais, not centavos.** The flag was documented and parsed as
17
+ centavos; following the help (`--value 4990`) created a product priced 100×
18
+ (R$ 4.990,00 instead of R$ 49,90). `--value` now takes a decimal amount in
19
+ Reais (e.g. `49.90`). `charges` / refund `--amount` remain centavos.
20
+
21
+ ## [0.7.0] — 2026-05-31
22
+
23
+ ### Added
24
+
25
+ - **Pix Automático** (BACEN auto-debit recurring Pix) across the CLI.
26
+ - `garu scheduled-charges create --methods pix_automatic` — schedule a
27
+ Pix Automático recurring series. The CLI validates locally that
28
+ `pix_automatic` is paired with `--type=recurring` **and** a
29
+ `--product-id`, returning an `invalid_input` error before any network
30
+ round-trip if either is missing.
31
+ - `garu products` — a new command group wrapping the SDK's product
32
+ write surface:
33
+ - `garu products create --name <name> [...]` — create a product.
34
+ - `garu products update <id> [...]` — partial update by numeric id or
35
+ UUID; only the flags you pass are changed.
36
+ - Both accept `--pix-automatic` / `--no-pix-automatic` to toggle Pix
37
+ Automático on the product's subscription checkout, alongside
38
+ `--pix`, `--boleto`, `--credit-card`, `--value` (centavos),
39
+ `--installments`, `--subscription`, and related fields.
40
+ - `garu --help` now includes an end-to-end **Pix Automático recurring
41
+ subscription** recipe (create the product, then schedule the
42
+ recurring charge).
43
+
44
+ ### Changed
45
+
46
+ - `@garuhq/node` SDK bumped to 0.15.0 for `pix_automatic` on scheduled
47
+ charges, the `pixAutomatic` product field, and the new
48
+ `products.create()` / `products.update()` methods.
49
+
6
50
  ## [0.6.0] — 2026-05-25
7
51
 
8
52
  ### Added
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.6.0";
18
+ var CLI_VERSION = "0.8.0";
19
19
  var CliError = class extends Error {
20
20
  code;
21
21
  exitCode;
@@ -476,7 +476,7 @@ async function logoutCommand(opts = {}) {
476
476
  return { cleared: opts.profile };
477
477
  }
478
478
 
479
- // src/commands/scheduled-charges.ts
479
+ // src/commands/products.ts
480
480
  async function getClient2(opts) {
481
481
  if (opts.garu) return opts.garu;
482
482
  const auth = await resolveAuth({
@@ -488,6 +488,73 @@ async function getClient2(opts) {
488
488
  ...opts.baseUrl !== void 0 ? { baseUrl: opts.baseUrl } : {}
489
489
  });
490
490
  }
491
+ function buildProductBody(opts) {
492
+ const body = {};
493
+ if (opts.name !== void 0) body.name = opts.name;
494
+ if (opts.value !== void 0) body.value = opts.value;
495
+ if (opts.description !== void 0) body.description = opts.description;
496
+ if (opts.image !== void 0) body.image = opts.image;
497
+ if (opts.tags !== void 0) body.tags = opts.tags;
498
+ if (opts.pix !== void 0) body.pix = opts.pix;
499
+ if (opts.boleto !== void 0) body.boleto = opts.boleto;
500
+ if (opts.creditCard !== void 0) body.creditCard = opts.creditCard;
501
+ if (opts.pixAutomatic !== void 0) body.pixAutomatic = opts.pixAutomatic;
502
+ if (opts.installments !== void 0) body.installments = opts.installments;
503
+ if (opts.isSubscription !== void 0) body.isSubscription = opts.isSubscription;
504
+ if (opts.subscriptionType !== void 0) body.subscriptionType = opts.subscriptionType;
505
+ if (opts.unitLabel !== void 0) body.unitLabel = opts.unitLabel;
506
+ if (opts.returnUrl !== void 0) body.returnUrl = opts.returnUrl;
507
+ if (opts.returnUrlButtonText !== void 0) body.returnUrlButtonText = opts.returnUrlButtonText;
508
+ return body;
509
+ }
510
+ async function productsCreateCommand(opts) {
511
+ const garu = await getClient2(opts);
512
+ const params = { ...buildProductBody(opts), name: opts.name };
513
+ const product = await garu.products.create(params);
514
+ printSuccess(`Created product ${product.uuid ?? product.id}`, opts);
515
+ printResult(product, { ...opts, prettyPrint: prettyProduct });
516
+ return product;
517
+ }
518
+ async function productsUpdateCommand(opts) {
519
+ const body = buildProductBody(opts);
520
+ if (Object.keys(body).length === 0) {
521
+ throw new CliError("invalid_input", "Nothing to update \u2014 pass at least one field to change.");
522
+ }
523
+ const garu = await getClient2(opts);
524
+ const product = await garu.products.update(opts.id, body);
525
+ printSuccess(`Updated product ${product.uuid ?? product.id}`, opts);
526
+ printResult(product, { ...opts, prettyPrint: prettyProduct });
527
+ return product;
528
+ }
529
+ function prettyProduct(p) {
530
+ const methods = [
531
+ p.pix ? "pix" : null,
532
+ p.boleto ? "boleto" : null,
533
+ p.creditCard ? "card" : null,
534
+ p.pixAutomatic ? "pix_automatic" : null
535
+ ].filter(Boolean).join(", ");
536
+ const lines = [
537
+ `Product ${p.uuid ?? p.id}`,
538
+ ` name: ${p.name}`,
539
+ ` value: ${p.value} (reais)`,
540
+ ` methods: ${methods || "(none)"}`
541
+ ];
542
+ if (p.description) lines.push(` description: ${p.description}`);
543
+ return lines.join("\n");
544
+ }
545
+
546
+ // src/commands/scheduled-charges.ts
547
+ async function getClient3(opts) {
548
+ if (opts.garu) return opts.garu;
549
+ const auth = await resolveAuth({
550
+ ...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
551
+ ...opts.profile !== void 0 ? { profile: opts.profile } : {}
552
+ });
553
+ return createGaruClient({
554
+ auth,
555
+ ...opts.baseUrl !== void 0 ? { baseUrl: opts.baseUrl } : {}
556
+ });
557
+ }
491
558
  function buildRecurrence(opts) {
492
559
  if (opts.recurrenceInterval === void 0) return void 0;
493
560
  const recurrence = { interval: opts.recurrenceInterval };
@@ -497,8 +564,24 @@ function buildRecurrence(opts) {
497
564
  if (opts.recurrenceEndsOn !== void 0) recurrence.endsOn = opts.recurrenceEndsOn;
498
565
  return recurrence;
499
566
  }
567
+ function assertPixAutomaticRequirements(opts) {
568
+ if (!opts.methods.includes("pix_automatic")) return;
569
+ if (opts.type !== "recurring") {
570
+ throw new CliError(
571
+ "invalid_input",
572
+ `--methods pix_automatic requires --type=recurring (Pix Autom\xE1tico is auto-debit recurring; got '${opts.type}')`
573
+ );
574
+ }
575
+ if (opts.productId === void 0) {
576
+ throw new CliError(
577
+ "invalid_input",
578
+ "--methods pix_automatic requires --product-id (Pix Autom\xE1tico must be enabled on a product)"
579
+ );
580
+ }
581
+ }
500
582
  async function scheduledChargesCreateCommand(opts) {
501
- const garu = await getClient2(opts);
583
+ assertPixAutomaticRequirements(opts);
584
+ const garu = await getClient3(opts);
502
585
  const params = {
503
586
  customerId: opts.customerId,
504
587
  amount: opts.amount,
@@ -520,7 +603,7 @@ async function scheduledChargesCreateCommand(opts) {
520
603
  return charge;
521
604
  }
522
605
  async function scheduledChargesListCommand(opts) {
523
- const garu = await getClient2(opts);
606
+ const garu = await getClient3(opts);
524
607
  const params = {};
525
608
  if (opts.page !== void 0) params.page = opts.page;
526
609
  if (opts.limit !== void 0) params.limit = opts.limit;
@@ -537,13 +620,13 @@ async function scheduledChargesListCommand(opts) {
537
620
  return result;
538
621
  }
539
622
  async function scheduledChargesGetCommand(opts) {
540
- const garu = await getClient2(opts);
623
+ const garu = await getClient3(opts);
541
624
  const detail = await garu.scheduledCharges.get(opts.id);
542
625
  printResult(detail, { ...opts, prettyPrint: prettyScheduledChargeDetail });
543
626
  return detail;
544
627
  }
545
628
  async function scheduledChargesPostponeCommand(opts) {
546
- const garu = await getClient2(opts);
629
+ const garu = await getClient3(opts);
547
630
  const params = { newDueDate: opts.newDueDate };
548
631
  if (opts.reason !== void 0) params.reason = opts.reason;
549
632
  const charge = await garu.scheduledCharges.postpone(opts.id, params);
@@ -551,7 +634,7 @@ async function scheduledChargesPostponeCommand(opts) {
551
634
  return charge;
552
635
  }
553
636
  async function scheduledChargesPauseCommand(opts) {
554
- const garu = await getClient2(opts);
637
+ const garu = await getClient3(opts);
555
638
  const params = {};
556
639
  if (opts.reason !== void 0) params.reason = opts.reason;
557
640
  const charge = await garu.scheduledCharges.pause(opts.id, params);
@@ -559,13 +642,13 @@ async function scheduledChargesPauseCommand(opts) {
559
642
  return charge;
560
643
  }
561
644
  async function scheduledChargesResumeCommand(opts) {
562
- const garu = await getClient2(opts);
645
+ const garu = await getClient3(opts);
563
646
  const charge = await garu.scheduledCharges.resume(opts.id);
564
647
  printResult(charge, { ...opts, prettyPrint: prettyScheduledCharge });
565
648
  return charge;
566
649
  }
567
650
  async function scheduledChargesMarkPaidCommand(opts) {
568
- const garu = await getClient2(opts);
651
+ const garu = await getClient3(opts);
569
652
  const params = { paymentDate: opts.paymentDate };
570
653
  if (opts.externalReference !== void 0) params.externalReference = opts.externalReference;
571
654
  if (opts.cycleNumber !== void 0) params.cycleNumber = opts.cycleNumber;
@@ -574,7 +657,7 @@ async function scheduledChargesMarkPaidCommand(opts) {
574
657
  return charge;
575
658
  }
576
659
  async function scheduledChargesCancelRecurrenceCommand(opts) {
577
- const garu = await getClient2(opts);
660
+ const garu = await getClient3(opts);
578
661
  const params = {};
579
662
  if (opts.reason !== void 0) params.reason = opts.reason;
580
663
  const charge = await garu.scheduledCharges.cancelRecurrence(opts.id, params);
@@ -582,14 +665,14 @@ async function scheduledChargesCancelRecurrenceCommand(opts) {
582
665
  return charge;
583
666
  }
584
667
  async function scheduledChargesCancelAtPeriodEndCommand(opts) {
585
- const garu = await getClient2(opts);
668
+ const garu = await getClient3(opts);
586
669
  const params = { enabled: opts.enabled };
587
670
  const charge = await garu.scheduledCharges.setCancelAtPeriodEnd(opts.id, params);
588
671
  printResult(charge, { ...opts, prettyPrint: prettyScheduledCharge });
589
672
  return charge;
590
673
  }
591
674
  async function scheduledChargesChangePaymentMethodCommand(opts) {
592
- const garu = await getClient2(opts);
675
+ const garu = await getClient3(opts);
593
676
  const params = {
594
677
  paymentMethodId: opts.paymentMethodId
595
678
  };
@@ -598,13 +681,13 @@ async function scheduledChargesChangePaymentMethodCommand(opts) {
598
681
  return charge;
599
682
  }
600
683
  async function scheduledChargesClearPaymentMethodCommand(opts) {
601
- const garu = await getClient2(opts);
684
+ const garu = await getClient3(opts);
602
685
  const charge = await garu.scheduledCharges.clearPaymentMethod(opts.id);
603
686
  printResult(charge, { ...opts, prettyPrint: prettyScheduledCharge });
604
687
  return charge;
605
688
  }
606
689
  async function scheduledChargesAttemptsCommand(opts) {
607
- const garu = await getClient2(opts);
690
+ const garu = await getClient3(opts);
608
691
  const params = {};
609
692
  if (opts.page !== void 0) params.page = opts.page;
610
693
  if (opts.limit !== void 0) params.limit = opts.limit;
@@ -614,7 +697,7 @@ async function scheduledChargesAttemptsCommand(opts) {
614
697
  return result;
615
698
  }
616
699
  async function scheduledChargesChargeNowCommand(opts) {
617
- const garu = await getClient2(opts);
700
+ const garu = await getClient3(opts);
618
701
  const result = await garu.scheduledCharges.chargeNow(opts.id);
619
702
  printResult(result, { ...opts, prettyPrint: prettyChargeNow });
620
703
  if (result.outcome === "failed" || result.outcome === "not_sent") {
@@ -678,7 +761,7 @@ function prettyChargeNow(result) {
678
761
  if (result.reason) lines.push(` reason: ${result.reason}`);
679
762
  return lines.join("\n");
680
763
  }
681
- async function getClient3(opts) {
764
+ async function getClient4(opts) {
682
765
  if (opts.garu) return opts.garu;
683
766
  const auth = await resolveAuth({
684
767
  ...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
@@ -690,7 +773,7 @@ async function getClient3(opts) {
690
773
  });
691
774
  }
692
775
  async function webhooksEventsListCommand(opts) {
693
- const garu = await getClient3(opts);
776
+ const garu = await getClient4(opts);
694
777
  const params = {};
695
778
  if (opts.page !== void 0) params.page = opts.page;
696
779
  if (opts.limit !== void 0) params.limit = opts.limit;
@@ -702,19 +785,19 @@ async function webhooksEventsListCommand(opts) {
702
785
  return result;
703
786
  }
704
787
  async function webhooksEventsGetCommand(opts) {
705
- const garu = await getClient3(opts);
788
+ const garu = await getClient4(opts);
706
789
  const event = await garu.webhookEvents.get(opts.id);
707
790
  printResult(event, { ...opts, prettyPrint: prettyWebhookEvent });
708
791
  return event;
709
792
  }
710
793
  async function webhooksEventsRetryCommand(opts) {
711
- const garu = await getClient3(opts);
794
+ const garu = await getClient4(opts);
712
795
  const event = await garu.webhookEvents.retry(opts.id);
713
796
  printResult(event, { ...opts, prettyPrint: prettyWebhookEvent });
714
797
  return event;
715
798
  }
716
799
  async function webhooksEventsResendCommand(opts) {
717
- const garu = await getClient3(opts);
800
+ const garu = await getClient4(opts);
718
801
  const clone = await garu.webhookEvents.resend(opts.id);
719
802
  printSuccess(`Resent event ${opts.id} \u2192 new event ${clone.id}`, opts);
720
803
  printResult(clone, { ...opts, prettyPrint: prettyWebhookEvent });
@@ -782,9 +865,17 @@ function parseScheduledChargeType(raw) {
782
865
  if (raw === "one_time" || raw === "recurring") return raw;
783
866
  throw new CliError("invalid_input", `--type must be 'one_time' or 'recurring' (got '${raw}')`);
784
867
  }
785
- var SCHEDULED_PAYMENT_METHODS = ["pix", "boleto", "card"];
868
+ var SCHEDULED_PAYMENT_METHODS = [
869
+ "pix",
870
+ "boleto",
871
+ "card",
872
+ "pix_automatic"
873
+ ];
874
+ function parseCsvList(raw) {
875
+ return raw.split(",").map((s) => s.trim()).filter(Boolean);
876
+ }
786
877
  function parseScheduledPaymentMethods(raw) {
787
- const parts = raw.split(",").map((s) => s.trim()).filter(Boolean);
878
+ const parts = parseCsvList(raw);
788
879
  if (parts.length === 0) {
789
880
  throw new CliError(
790
881
  "invalid_input",
@@ -846,6 +937,17 @@ function parseIntInRange(raw, label, min, max) {
846
937
  }
847
938
  return n;
848
939
  }
940
+ function parseNonNegativeBrl(raw, label) {
941
+ const trimmed = raw.trim();
942
+ const n = Number(trimmed);
943
+ if (trimmed === "" || !Number.isFinite(n) || n < 0) {
944
+ throw new CliError(
945
+ "invalid_input",
946
+ `${label} must be a non-negative amount in BRL/reais, e.g. 49.90 (got '${raw}')`
947
+ );
948
+ }
949
+ return n;
950
+ }
849
951
  function parseAmountBrl(raw) {
850
952
  const n = Number(raw);
851
953
  if (!Number.isFinite(n) || n <= 0) {
@@ -872,7 +974,28 @@ function parseMetadata(raw) {
872
974
  // src/index.ts
873
975
  function buildCli() {
874
976
  const program = new commander.Command();
875
- program.name("garu").description("Command-line interface for the Garu payment gateway.").version(CLI_VERSION, "-v, --version").addOption(new commander.Option("--api-key <key>", "Garu API key (overrides env and credentials file)")).addOption(new commander.Option("-p, --profile <name>", "credentials profile name")).addOption(new commander.Option("--json", "emit strict JSON on stdout (forced in pipes)")).addOption(new commander.Option("-q, --quiet", "suppress status output; only print results and errors")).showHelpAfterError();
977
+ program.name("garu").description("Command-line interface for the Garu payment gateway.").version(CLI_VERSION, "-v, --version").addOption(new commander.Option("--api-key <key>", "Garu API key (overrides env and credentials file)")).addOption(new commander.Option("-p, --profile <name>", "credentials profile name")).addOption(new commander.Option("--json", "emit strict JSON on stdout (forced in pipes)")).addOption(new commander.Option("-q, --quiet", "suppress status output; only print results and errors")).showHelpAfterError().addHelpText(
978
+ "after",
979
+ `
980
+ Recipes:
981
+ Pix Autom\xE1tico recurring subscription (end-to-end):
982
+
983
+ # 1. Create a product with Pix Autom\xE1tico enabled
984
+ garu products create \\
985
+ --name "Plano Mensal" --value 49.90 \\
986
+ --pix --credit-card --pix-automatic \\
987
+ --subscription --subscription-type monthly
988
+
989
+ # 2. Schedule the recurring auto-debit charge for that product.
990
+ # pix_automatic requires --type=recurring and --product-id.
991
+ garu scheduled-charges create \\
992
+ --customer-id 42 --product-id 456 \\
993
+ --amount 49.90 --type recurring \\
994
+ --due-date 2026-06-15 \\
995
+ --methods pix_automatic \\
996
+ --recurrence-interval monthly
997
+ `
998
+ );
876
999
  program.command("login").description("Save a Garu API key to the credentials file").option("--api-key <key>", "pre-supply the key instead of prompting").option("-p, --profile <name>", "profile name to store under", "default").action(async (cmdOpts) => {
877
1000
  const base = toCommandOptions(program);
878
1001
  await loginCommand({
@@ -954,9 +1077,9 @@ function buildCli() {
954
1077
  "--customer-id <n>",
955
1078
  "customer id",
956
1079
  (v) => parsePositiveIntId(v, "--customer-id")
957
- ).requiredOption("--amount <brl>", "decimal BRL amount, e.g. 297.50").requiredOption("--type <type>", "one_time | recurring").requiredOption("--due-date <yyyy-mm-dd>", "first due date in S\xE3o Paulo time").requiredOption("--methods <list>", "comma-separated: pix,boleto,card").option(
1080
+ ).requiredOption("--amount <brl>", "decimal BRL amount, e.g. 297.50").requiredOption("--type <type>", "one_time | recurring").requiredOption("--due-date <yyyy-mm-dd>", "first due date in S\xE3o Paulo time").requiredOption("--methods <list>", "comma-separated: pix,boleto,card,pix_automatic").option(
958
1081
  "--product-id <n>",
959
- "product id (required when methods includes card)",
1082
+ "product id (required when methods includes card or pix_automatic)",
960
1083
  (v) => parsePositiveIntId(v, "--product-id")
961
1084
  ).option("--description <text>", "charge description").option("--recurrence-interval <interval>", "recurring cadence: weekly|monthly|yearly|\u2026").option(
962
1085
  "--recurrence-interval-count <n>",
@@ -1163,6 +1286,68 @@ function buildCli() {
1163
1286
  id: parsePositiveIntId(id, "Webhook event ID")
1164
1287
  }).catch((err) => printErrorAndExit(err, base));
1165
1288
  });
1289
+ const products = program.command("products").description("Create and update products");
1290
+ products.command("create").description("Create a product").requiredOption("--name <name>", "product name").option(
1291
+ "--value <reais>",
1292
+ "price in reais / decimal BRL (e.g. 49.90)",
1293
+ (v) => parseNonNegativeBrl(v, "--value")
1294
+ ).option("--description <text>", "product description").option("--image <url>", "HTTPS URL of the product cover image").option("--tags <list>", "comma-separated tags", parseCsvList).option("--pix", "accept PIX").option("--no-pix", "do not accept PIX").option("--boleto", "accept boleto").option("--no-boleto", "do not accept boleto").option("--credit-card", "accept credit card").option("--no-credit-card", "do not accept credit card").option("--pix-automatic", "expose Pix Autom\xE1tico on the subscription checkout").option("--no-pix-automatic", "do not expose Pix Autom\xE1tico").option(
1295
+ "--installments <n>",
1296
+ "max credit-card installments",
1297
+ (v) => parsePositiveIntId(v, "--installments")
1298
+ ).option("--subscription", "mark the product as a subscription").option("--no-subscription", "mark the product as one-time").option("--subscription-type <type>", "subscription cadence, e.g. monthly").option("--unit-label <label>", "unit label shown on the checkout").option("--return-url <url>", "post-purchase redirect URL").option("--return-url-button-text <text>", "label for the return-URL button").action(async (cmdOpts) => {
1299
+ const base = toCommandOptions(program);
1300
+ await productsCreateCommand({
1301
+ ...base,
1302
+ name: cmdOpts.name,
1303
+ value: cmdOpts.value,
1304
+ description: cmdOpts.description,
1305
+ image: cmdOpts.image,
1306
+ tags: cmdOpts.tags,
1307
+ pix: cmdOpts.pix,
1308
+ boleto: cmdOpts.boleto,
1309
+ creditCard: cmdOpts.creditCard,
1310
+ pixAutomatic: cmdOpts.pixAutomatic,
1311
+ installments: cmdOpts.installments,
1312
+ isSubscription: cmdOpts.subscription,
1313
+ subscriptionType: cmdOpts.subscriptionType,
1314
+ unitLabel: cmdOpts.unitLabel,
1315
+ returnUrl: cmdOpts.returnUrl,
1316
+ returnUrlButtonText: cmdOpts.returnUrlButtonText
1317
+ }).catch((err) => printErrorAndExit(err, base));
1318
+ });
1319
+ products.command("update <id>").description(
1320
+ "Update a product (partial \u2014 only the flags you pass change). <id> is the numeric id or UUID"
1321
+ ).option("--name <name>", "product name").option(
1322
+ "--value <reais>",
1323
+ "price in reais / decimal BRL (e.g. 49.90)",
1324
+ (v) => parseNonNegativeBrl(v, "--value")
1325
+ ).option("--description <text>", "product description").option("--image <url>", "HTTPS URL of the product cover image").option("--tags <list>", "comma-separated tags", parseCsvList).option("--pix", "accept PIX").option("--no-pix", "do not accept PIX").option("--boleto", "accept boleto").option("--no-boleto", "do not accept boleto").option("--credit-card", "accept credit card").option("--no-credit-card", "do not accept credit card").option("--pix-automatic", "expose Pix Autom\xE1tico on the subscription checkout").option("--no-pix-automatic", "do not expose Pix Autom\xE1tico").option(
1326
+ "--installments <n>",
1327
+ "max credit-card installments",
1328
+ (v) => parsePositiveIntId(v, "--installments")
1329
+ ).option("--subscription", "mark the product as a subscription").option("--no-subscription", "mark the product as one-time").option("--subscription-type <type>", "subscription cadence, e.g. monthly").option("--unit-label <label>", "unit label shown on the checkout").option("--return-url <url>", "post-purchase redirect URL").option("--return-url-button-text <text>", "label for the return-URL button").action(async (id, cmdOpts) => {
1330
+ const base = toCommandOptions(program);
1331
+ await productsUpdateCommand({
1332
+ ...base,
1333
+ id,
1334
+ name: cmdOpts.name,
1335
+ value: cmdOpts.value,
1336
+ description: cmdOpts.description,
1337
+ image: cmdOpts.image,
1338
+ tags: cmdOpts.tags,
1339
+ pix: cmdOpts.pix,
1340
+ boleto: cmdOpts.boleto,
1341
+ creditCard: cmdOpts.creditCard,
1342
+ pixAutomatic: cmdOpts.pixAutomatic,
1343
+ installments: cmdOpts.installments,
1344
+ isSubscription: cmdOpts.subscription,
1345
+ subscriptionType: cmdOpts.subscriptionType,
1346
+ unitLabel: cmdOpts.unitLabel,
1347
+ returnUrl: cmdOpts.returnUrl,
1348
+ returnUrlButtonText: cmdOpts.returnUrlButtonText
1349
+ }).catch((err) => printErrorAndExit(err, base));
1350
+ });
1166
1351
  program.command("doctor").description("Environment diagnostic").action(async () => {
1167
1352
  const base = toCommandOptions(program);
1168
1353
  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.6.0",
3
+ "version": "0.8.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.13.0",
49
+ "@garuhq/node": "0.16.0",
50
50
  "@inquirer/prompts": "8.4.1",
51
51
  "commander": "12.0.0",
52
52
  "picocolors": "1.0.0",