@garuhq/node 0.12.1 → 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 +26 -0
- package/README.md +12 -1
- package/dist/index.cjs +99 -36
- package/dist/index.d.cts +64 -1
- package/dist/index.d.ts +64 -1
- package/dist/index.js +99 -36
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,32 @@
|
|
|
3
3
|
All notable changes to `@garuhq/node` 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-05-25
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- `scheduledCharges.chargeNow(id)` — `POST /api/scheduled-charges/{id}/charge-now`.
|
|
11
|
+
Force-bills the current cycle right now instead of waiting for its due
|
|
12
|
+
date, running the same dispatch the daily billing cron would (customer
|
|
13
|
+
email/notification + outbound webhook + timeline event). Allowed only
|
|
14
|
+
from a billable status (`scheduled` / `due_today`); a recurring series
|
|
15
|
+
must have an open cycle. **Idempotent** — a cycle whose d-day was
|
|
16
|
+
already dispatched reports `already_sent` and does not re-charge.
|
|
17
|
+
Returns `{ outcome, cycleNumber, reason?, message }`:
|
|
18
|
+
- `outcome` is `'dispatched' | 'already_sent' | 'not_sent' | 'failed'`.
|
|
19
|
+
- `reason` (on `not_sent` / `failed`) is one of the documented literals
|
|
20
|
+
(`no_email`, `lock_lost`, `no_saved_payment_method`, `card_expired`,
|
|
21
|
+
`payment_method_missing`, `customer_missing`) or a raw gateway decline
|
|
22
|
+
code.
|
|
23
|
+
- `message` is a ready-to-show pt-BR string.
|
|
24
|
+
- `ChargeNowOutcome`, `ChargeNowReason`, and `ChargeNowResult` types
|
|
25
|
+
exported from the package root.
|
|
26
|
+
- `maxRecoveryDays?: number` (integer 1–365) on
|
|
27
|
+
`CreateScheduledChargeParams` — caps how many days past `dueDate` the
|
|
28
|
+
daily recovery sweep will still auto-bill a missed charge. Omit for the
|
|
29
|
+
system default (14). Also surfaced on the scheduled charge object as
|
|
30
|
+
`ScheduledChargeRecord.maxRecoveryDays: number | null`.
|
|
31
|
+
|
|
6
32
|
## [0.12.1] — 2026-05-19
|
|
7
33
|
|
|
8
34
|
### Fixed
|
package/README.md
CHANGED
|
@@ -203,6 +203,7 @@ Bill an existing customer on a future date — one-time or recurring with card t
|
|
|
203
203
|
| `create(params)` | Create one-time or recurring schedule. Auto-attaches `X-Idempotency-Key`. |
|
|
204
204
|
| `list(params?)` | Paginated list with status / type / dueFrom / dueTo / customerId filters. |
|
|
205
205
|
| `get(id)` | Detail bundle: charge + event timeline + linked transactions. |
|
|
206
|
+
| `chargeNow(id)` | Force-bill the current cycle now instead of waiting for the due date. |
|
|
206
207
|
| `markPaid(id, params)` | Mark cycle paid (off-Garu reconciliation). |
|
|
207
208
|
| `postpone(id, params)` | Move the next cycle's due date forward. |
|
|
208
209
|
| `pause(id, params?)` / `resume(id)` | Suspend / re-enable a series. |
|
|
@@ -213,7 +214,8 @@ Bill an existing customer on a future date — one-time or recurring with card t
|
|
|
213
214
|
| `listAttempts(id, params?)` | Per-attempt billing log — every silent-charge / retry / mark-paid (v0.8.2).|
|
|
214
215
|
|
|
215
216
|
```ts
|
|
216
|
-
// Recurring with 7-day trial
|
|
217
|
+
// Recurring with 7-day trial. `maxRecoveryDays` caps how long past the due
|
|
218
|
+
// date the daily recovery sweep keeps auto-billing a missed charge (default 14).
|
|
217
219
|
const series = await garu.scheduledCharges.create({
|
|
218
220
|
customerId: 42,
|
|
219
221
|
productId: 17,
|
|
@@ -223,8 +225,17 @@ const series = await garu.scheduledCharges.create({
|
|
|
223
225
|
methods: ['card', 'pix'],
|
|
224
226
|
recurrence: { interval: 'monthly' },
|
|
225
227
|
trialDays: 7,
|
|
228
|
+
maxRecoveryDays: 30,
|
|
226
229
|
});
|
|
227
230
|
|
|
231
|
+
// Force-bill the current cycle now instead of waiting for the due date.
|
|
232
|
+
// Idempotent: a cycle already dispatched today reports `already_sent`.
|
|
233
|
+
const result = await garu.scheduledCharges.chargeNow(series.id);
|
|
234
|
+
if (result.outcome === 'failed') {
|
|
235
|
+
// result.reason is e.g. 'card_expired' or a gateway decline code
|
|
236
|
+
console.error(`${result.message} (${result.reason})`);
|
|
237
|
+
}
|
|
238
|
+
|
|
228
239
|
// Audit why cycle 3 failed (v0.8.2)
|
|
229
240
|
const { data } = await garu.scheduledCharges.listAttempts(series.id, {
|
|
230
241
|
cycleNumber: 3,
|
package/dist/index.cjs
CHANGED
|
@@ -653,9 +653,9 @@ var ScheduledCharges = class {
|
|
|
653
653
|
*/
|
|
654
654
|
async get(id) {
|
|
655
655
|
return this.http.call(
|
|
656
|
-
(signal) => this.http.client.GET(`/api/scheduled-charges/${id}`, {
|
|
657
|
-
|
|
658
|
-
)
|
|
656
|
+
(signal) => this.http.client.GET(`/api/scheduled-charges/${encodeURIComponent(id)}`, {
|
|
657
|
+
signal
|
|
658
|
+
}).then((r) => r)
|
|
659
659
|
);
|
|
660
660
|
}
|
|
661
661
|
/**
|
|
@@ -671,10 +671,13 @@ var ScheduledCharges = class {
|
|
|
671
671
|
*/
|
|
672
672
|
async postpone(id, params) {
|
|
673
673
|
return this.http.call(
|
|
674
|
-
(signal) => this.http.client.POST(
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
674
|
+
(signal) => this.http.client.POST(
|
|
675
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/postpone`,
|
|
676
|
+
{
|
|
677
|
+
body: params,
|
|
678
|
+
signal
|
|
679
|
+
}
|
|
680
|
+
).then((r) => r)
|
|
678
681
|
);
|
|
679
682
|
}
|
|
680
683
|
/**
|
|
@@ -687,10 +690,13 @@ var ScheduledCharges = class {
|
|
|
687
690
|
*/
|
|
688
691
|
async pause(id, params = {}) {
|
|
689
692
|
return this.http.call(
|
|
690
|
-
(signal) => this.http.client.POST(
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
693
|
+
(signal) => this.http.client.POST(
|
|
694
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/pause`,
|
|
695
|
+
{
|
|
696
|
+
body: params,
|
|
697
|
+
signal
|
|
698
|
+
}
|
|
699
|
+
).then((r) => r)
|
|
694
700
|
);
|
|
695
701
|
}
|
|
696
702
|
/**
|
|
@@ -701,10 +707,13 @@ var ScheduledCharges = class {
|
|
|
701
707
|
*/
|
|
702
708
|
async resume(id) {
|
|
703
709
|
return this.http.call(
|
|
704
|
-
(signal) => this.http.client.POST(
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
710
|
+
(signal) => this.http.client.POST(
|
|
711
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/resume`,
|
|
712
|
+
{
|
|
713
|
+
body: {},
|
|
714
|
+
signal
|
|
715
|
+
}
|
|
716
|
+
).then((r) => r)
|
|
708
717
|
);
|
|
709
718
|
}
|
|
710
719
|
/**
|
|
@@ -732,10 +741,52 @@ var ScheduledCharges = class {
|
|
|
732
741
|
*/
|
|
733
742
|
async markPaid(id, params) {
|
|
734
743
|
return this.http.call(
|
|
735
|
-
(signal) => this.http.client.POST(
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
744
|
+
(signal) => this.http.client.POST(
|
|
745
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/mark-paid`,
|
|
746
|
+
{
|
|
747
|
+
body: params,
|
|
748
|
+
signal
|
|
749
|
+
}
|
|
750
|
+
).then((r) => r)
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Force-bill the current cycle right now instead of waiting for its due
|
|
755
|
+
* date. Runs the same dispatch the daily billing cron would (customer
|
|
756
|
+
* email/notification + outbound webhook + timeline event). Allowed only
|
|
757
|
+
* from a billable status (`scheduled` / `due_today`); a recurring series
|
|
758
|
+
* must have an open cycle (else the backend returns 400).
|
|
759
|
+
*
|
|
760
|
+
* Idempotent: if this cycle's d-day was already dispatched it reports
|
|
761
|
+
* `already_sent` and does not re-charge. Inspect `outcome` to branch.
|
|
762
|
+
*
|
|
763
|
+
* @example
|
|
764
|
+
* const result = await garu.scheduledCharges.chargeNow('sch_abc123');
|
|
765
|
+
* switch (result.outcome) {
|
|
766
|
+
* case 'dispatched':
|
|
767
|
+
* console.log(`Cobrança enviada (ciclo ${result.cycleNumber}).`);
|
|
768
|
+
* break;
|
|
769
|
+
* case 'already_sent':
|
|
770
|
+
* console.log('Já havia sido enviada — nada a fazer.');
|
|
771
|
+
* break;
|
|
772
|
+
* case 'failed':
|
|
773
|
+
* // result.reason is e.g. 'card_expired' or a gateway decline code
|
|
774
|
+
* console.error(`Falha na cobrança: ${result.reason}. ${result.message}`);
|
|
775
|
+
* break;
|
|
776
|
+
* case 'not_sent':
|
|
777
|
+
* console.warn(`Não enviada (${result.reason}): ${result.message}`);
|
|
778
|
+
* break;
|
|
779
|
+
* }
|
|
780
|
+
*/
|
|
781
|
+
async chargeNow(id) {
|
|
782
|
+
return this.http.call(
|
|
783
|
+
(signal) => this.http.client.POST(
|
|
784
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/charge-now`,
|
|
785
|
+
{
|
|
786
|
+
body: {},
|
|
787
|
+
signal
|
|
788
|
+
}
|
|
789
|
+
).then((r) => r)
|
|
739
790
|
);
|
|
740
791
|
}
|
|
741
792
|
/**
|
|
@@ -751,10 +802,13 @@ var ScheduledCharges = class {
|
|
|
751
802
|
*/
|
|
752
803
|
async cancelRecurrence(id, params = {}) {
|
|
753
804
|
return this.http.call(
|
|
754
|
-
(signal) => this.http.client.POST(
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
805
|
+
(signal) => this.http.client.POST(
|
|
806
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/cancel-recurrence`,
|
|
807
|
+
{
|
|
808
|
+
body: params,
|
|
809
|
+
signal
|
|
810
|
+
}
|
|
811
|
+
).then((r) => r)
|
|
758
812
|
);
|
|
759
813
|
}
|
|
760
814
|
/**
|
|
@@ -768,10 +822,13 @@ var ScheduledCharges = class {
|
|
|
768
822
|
*/
|
|
769
823
|
async setCancelAtPeriodEnd(id, params) {
|
|
770
824
|
return this.http.call(
|
|
771
|
-
(signal) => this.http.client.POST(
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
825
|
+
(signal) => this.http.client.POST(
|
|
826
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/cancel-at-period-end`,
|
|
827
|
+
{
|
|
828
|
+
body: params,
|
|
829
|
+
signal
|
|
830
|
+
}
|
|
831
|
+
).then((r) => r)
|
|
775
832
|
);
|
|
776
833
|
}
|
|
777
834
|
/**
|
|
@@ -784,10 +841,13 @@ var ScheduledCharges = class {
|
|
|
784
841
|
*/
|
|
785
842
|
async changePaymentMethod(id, params) {
|
|
786
843
|
return this.http.call(
|
|
787
|
-
(signal) => this.http.client.POST(
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
844
|
+
(signal) => this.http.client.POST(
|
|
845
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/payment-method`,
|
|
846
|
+
{
|
|
847
|
+
body: params,
|
|
848
|
+
signal
|
|
849
|
+
}
|
|
850
|
+
).then((r) => r)
|
|
791
851
|
);
|
|
792
852
|
}
|
|
793
853
|
/**
|
|
@@ -800,10 +860,13 @@ var ScheduledCharges = class {
|
|
|
800
860
|
*/
|
|
801
861
|
async clearPaymentMethod(id) {
|
|
802
862
|
return this.http.call(
|
|
803
|
-
(signal) => this.http.client.DELETE(
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
863
|
+
(signal) => this.http.client.DELETE(
|
|
864
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/payment-method`,
|
|
865
|
+
{
|
|
866
|
+
body: {},
|
|
867
|
+
signal
|
|
868
|
+
}
|
|
869
|
+
).then((r) => r)
|
|
807
870
|
);
|
|
808
871
|
}
|
|
809
872
|
/**
|
|
@@ -825,7 +888,7 @@ var ScheduledCharges = class {
|
|
|
825
888
|
if (params.limit !== void 0) qs.set("limit", String(params.limit));
|
|
826
889
|
if (params.cycleNumber !== void 0) qs.set("cycleNumber", String(params.cycleNumber));
|
|
827
890
|
const query = qs.toString();
|
|
828
|
-
const url = `/api/scheduled-charges/${id}/attempts${query ? `?${query}` : ""}`;
|
|
891
|
+
const url = `/api/scheduled-charges/${encodeURIComponent(id)}/attempts${query ? `?${query}` : ""}`;
|
|
829
892
|
return this.http.call(
|
|
830
893
|
(signal) => this.http.client.GET(url, { signal }).then(
|
|
831
894
|
(r) => r
|
package/dist/index.d.cts
CHANGED
|
@@ -312,6 +312,11 @@ interface ScheduledChargeRecord {
|
|
|
312
312
|
methods: ScheduledPaymentMethod[];
|
|
313
313
|
status: ScheduledChargeStatus;
|
|
314
314
|
externalReference: string | null;
|
|
315
|
+
/**
|
|
316
|
+
* Max days past `dueDate` the daily recovery sweep will still auto-bill a
|
|
317
|
+
* missed charge. `null` means the system default (14) applies.
|
|
318
|
+
*/
|
|
319
|
+
maxRecoveryDays: number | null;
|
|
315
320
|
metadata: Record<string, unknown> | null;
|
|
316
321
|
createdAt: string;
|
|
317
322
|
updatedAt: string;
|
|
@@ -407,6 +412,11 @@ interface CreateScheduledChargeParams {
|
|
|
407
412
|
trialDays?: number;
|
|
408
413
|
externalReference?: string;
|
|
409
414
|
metadata?: Record<string, unknown>;
|
|
415
|
+
/**
|
|
416
|
+
* Max days past `dueDate` the daily recovery sweep will still auto-bill a
|
|
417
|
+
* missed charge (integer 1..365). Omit for the system default (14).
|
|
418
|
+
*/
|
|
419
|
+
maxRecoveryDays?: number;
|
|
410
420
|
/**
|
|
411
421
|
* Optional idempotency key for safe retries. The SDK auto-generates a
|
|
412
422
|
* UUIDv4 when omitted and forwards it as `X-Idempotency-Key`.
|
|
@@ -456,6 +466,30 @@ interface ChangePaymentMethodScheduledChargeParams {
|
|
|
456
466
|
/** PaymentMethod id to bind. Must belong to the same customerId. */
|
|
457
467
|
paymentMethodId: number;
|
|
458
468
|
}
|
|
469
|
+
/**
|
|
470
|
+
* Result of `scheduledCharges.chargeNow(id)` — what the immediate dispatch did:
|
|
471
|
+
*
|
|
472
|
+
* - `dispatched` — sent now (customer email/notification + outbound webhook + timeline event).
|
|
473
|
+
* - `already_sent` — this cycle's d-day was already dispatched; no-op (the action is idempotent).
|
|
474
|
+
* - `not_sent` — couldn't send; see `reason` (e.g. `no_email`, `lock_lost`, `no_saved_payment_method`).
|
|
475
|
+
* - `failed` — card charge failed; see `reason` (e.g. `card_expired`, or a gateway decline code).
|
|
476
|
+
*/
|
|
477
|
+
type ChargeNowOutcome = 'dispatched' | 'already_sent' | 'not_sent' | 'failed';
|
|
478
|
+
/**
|
|
479
|
+
* Why a `not_sent` / `failed` charge-now didn't go through. The documented
|
|
480
|
+
* literals are stable; `failed` may also surface a raw gateway decline code,
|
|
481
|
+
* so the type stays open (`string & {}`) without losing autocomplete.
|
|
482
|
+
*/
|
|
483
|
+
type ChargeNowReason = 'no_email' | 'lock_lost' | 'no_saved_payment_method' | 'card_expired' | 'payment_method_missing' | 'customer_missing' | (string & {});
|
|
484
|
+
interface ChargeNowResult {
|
|
485
|
+
outcome: ChargeNowOutcome;
|
|
486
|
+
/** Cycle that was dispatched/attempted, or `null` for one-time charges. */
|
|
487
|
+
cycleNumber: number | null;
|
|
488
|
+
/** Present on `not_sent` / `failed`. See {@link ChargeNowReason}. */
|
|
489
|
+
reason?: ChargeNowReason;
|
|
490
|
+
/** Ready-to-show pt-BR message describing the outcome. */
|
|
491
|
+
message: string;
|
|
492
|
+
}
|
|
459
493
|
interface Product {
|
|
460
494
|
id: number;
|
|
461
495
|
uuid: string;
|
|
@@ -1035,6 +1069,35 @@ declare class ScheduledCharges {
|
|
|
1035
1069
|
* });
|
|
1036
1070
|
*/
|
|
1037
1071
|
markPaid(id: string, params: MarkPaidScheduledChargeParams): Promise<ScheduledChargeRecord>;
|
|
1072
|
+
/**
|
|
1073
|
+
* Force-bill the current cycle right now instead of waiting for its due
|
|
1074
|
+
* date. Runs the same dispatch the daily billing cron would (customer
|
|
1075
|
+
* email/notification + outbound webhook + timeline event). Allowed only
|
|
1076
|
+
* from a billable status (`scheduled` / `due_today`); a recurring series
|
|
1077
|
+
* must have an open cycle (else the backend returns 400).
|
|
1078
|
+
*
|
|
1079
|
+
* Idempotent: if this cycle's d-day was already dispatched it reports
|
|
1080
|
+
* `already_sent` and does not re-charge. Inspect `outcome` to branch.
|
|
1081
|
+
*
|
|
1082
|
+
* @example
|
|
1083
|
+
* const result = await garu.scheduledCharges.chargeNow('sch_abc123');
|
|
1084
|
+
* switch (result.outcome) {
|
|
1085
|
+
* case 'dispatched':
|
|
1086
|
+
* console.log(`Cobrança enviada (ciclo ${result.cycleNumber}).`);
|
|
1087
|
+
* break;
|
|
1088
|
+
* case 'already_sent':
|
|
1089
|
+
* console.log('Já havia sido enviada — nada a fazer.');
|
|
1090
|
+
* break;
|
|
1091
|
+
* case 'failed':
|
|
1092
|
+
* // result.reason is e.g. 'card_expired' or a gateway decline code
|
|
1093
|
+
* console.error(`Falha na cobrança: ${result.reason}. ${result.message}`);
|
|
1094
|
+
* break;
|
|
1095
|
+
* case 'not_sent':
|
|
1096
|
+
* console.warn(`Não enviada (${result.reason}): ${result.message}`);
|
|
1097
|
+
* break;
|
|
1098
|
+
* }
|
|
1099
|
+
*/
|
|
1100
|
+
chargeNow(id: string): Promise<ChargeNowResult>;
|
|
1038
1101
|
/**
|
|
1039
1102
|
* Stop future cycles for a recurring series. The currently in-flight
|
|
1040
1103
|
* cycle (if any) remains active until paid, postponed, or marked-paid;
|
|
@@ -1289,4 +1352,4 @@ declare class GaruServerError extends GaruAPIError {
|
|
|
1289
1352
|
constructor(message: string, status: number, requestId: string | null, body: unknown);
|
|
1290
1353
|
}
|
|
1291
1354
|
|
|
1292
|
-
export { type CancelAtPeriodEndScheduledChargeParams, type CancelRecurrenceScheduledChargeParams, type CardInfo, type ChangePaymentMethodScheduledChargeParams, type Charge, type ChargeList, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type CreateScheduledChargeParams, type Customer, type CustomerList, type CustomerRecord, type FailurePayload, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, type GaruFailureCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type ListProductsParams, type ListScheduledChargeAttemptsParams, type ListScheduledChargesParams, type ListWebhookEventsParams, type MarkPaidScheduledChargeParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PauseScheduledChargeParams, type PaymentMethod, type PaymentMethodExpiredPayload, type PaymentMethodExpiringPayload, type PostponeScheduledChargeParams, type Product, type ProductList, type ProductPortalConfig, type RecurrenceConfig, type RecurrenceInterval, type RefundChargeParams, type ResendWebhookEventParams, type ScheduledChargeActor, type ScheduledChargeAttempt, type ScheduledChargeAttemptList, type ScheduledChargeAttemptSource, type ScheduledChargeAttemptStatus, type ScheduledChargeDetail, type ScheduledChargeEvent, type ScheduledChargeEventType, type ScheduledChargeLinkedTransaction, type ScheduledChargeList, type ScheduledChargeRecord, type ScheduledChargeStatus, type ScheduledChargeType, type ScheduledPaymentMethod, type SetProductPortalConfigParams, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WebhookEvent, type WebhookEventEndpoint, type WebhookEventList, type WebhookEventStatus, type WirePaymentMethodId, webhooks };
|
|
1355
|
+
export { type CancelAtPeriodEndScheduledChargeParams, type CancelRecurrenceScheduledChargeParams, type CardInfo, type ChangePaymentMethodScheduledChargeParams, type Charge, type ChargeList, type ChargeNowOutcome, type ChargeNowReason, type ChargeNowResult, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type CreateScheduledChargeParams, type Customer, type CustomerList, type CustomerRecord, type FailurePayload, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, type GaruFailureCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type ListProductsParams, type ListScheduledChargeAttemptsParams, type ListScheduledChargesParams, type ListWebhookEventsParams, type MarkPaidScheduledChargeParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PauseScheduledChargeParams, type PaymentMethod, type PaymentMethodExpiredPayload, type PaymentMethodExpiringPayload, type PostponeScheduledChargeParams, type Product, type ProductList, type ProductPortalConfig, type RecurrenceConfig, type RecurrenceInterval, type RefundChargeParams, type ResendWebhookEventParams, type ScheduledChargeActor, type ScheduledChargeAttempt, type ScheduledChargeAttemptList, type ScheduledChargeAttemptSource, type ScheduledChargeAttemptStatus, type ScheduledChargeDetail, type ScheduledChargeEvent, type ScheduledChargeEventType, type ScheduledChargeLinkedTransaction, type ScheduledChargeList, type ScheduledChargeRecord, type ScheduledChargeStatus, type ScheduledChargeType, type ScheduledPaymentMethod, type SetProductPortalConfigParams, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WebhookEvent, type WebhookEventEndpoint, type WebhookEventList, type WebhookEventStatus, type WirePaymentMethodId, webhooks };
|
package/dist/index.d.ts
CHANGED
|
@@ -312,6 +312,11 @@ interface ScheduledChargeRecord {
|
|
|
312
312
|
methods: ScheduledPaymentMethod[];
|
|
313
313
|
status: ScheduledChargeStatus;
|
|
314
314
|
externalReference: string | null;
|
|
315
|
+
/**
|
|
316
|
+
* Max days past `dueDate` the daily recovery sweep will still auto-bill a
|
|
317
|
+
* missed charge. `null` means the system default (14) applies.
|
|
318
|
+
*/
|
|
319
|
+
maxRecoveryDays: number | null;
|
|
315
320
|
metadata: Record<string, unknown> | null;
|
|
316
321
|
createdAt: string;
|
|
317
322
|
updatedAt: string;
|
|
@@ -407,6 +412,11 @@ interface CreateScheduledChargeParams {
|
|
|
407
412
|
trialDays?: number;
|
|
408
413
|
externalReference?: string;
|
|
409
414
|
metadata?: Record<string, unknown>;
|
|
415
|
+
/**
|
|
416
|
+
* Max days past `dueDate` the daily recovery sweep will still auto-bill a
|
|
417
|
+
* missed charge (integer 1..365). Omit for the system default (14).
|
|
418
|
+
*/
|
|
419
|
+
maxRecoveryDays?: number;
|
|
410
420
|
/**
|
|
411
421
|
* Optional idempotency key for safe retries. The SDK auto-generates a
|
|
412
422
|
* UUIDv4 when omitted and forwards it as `X-Idempotency-Key`.
|
|
@@ -456,6 +466,30 @@ interface ChangePaymentMethodScheduledChargeParams {
|
|
|
456
466
|
/** PaymentMethod id to bind. Must belong to the same customerId. */
|
|
457
467
|
paymentMethodId: number;
|
|
458
468
|
}
|
|
469
|
+
/**
|
|
470
|
+
* Result of `scheduledCharges.chargeNow(id)` — what the immediate dispatch did:
|
|
471
|
+
*
|
|
472
|
+
* - `dispatched` — sent now (customer email/notification + outbound webhook + timeline event).
|
|
473
|
+
* - `already_sent` — this cycle's d-day was already dispatched; no-op (the action is idempotent).
|
|
474
|
+
* - `not_sent` — couldn't send; see `reason` (e.g. `no_email`, `lock_lost`, `no_saved_payment_method`).
|
|
475
|
+
* - `failed` — card charge failed; see `reason` (e.g. `card_expired`, or a gateway decline code).
|
|
476
|
+
*/
|
|
477
|
+
type ChargeNowOutcome = 'dispatched' | 'already_sent' | 'not_sent' | 'failed';
|
|
478
|
+
/**
|
|
479
|
+
* Why a `not_sent` / `failed` charge-now didn't go through. The documented
|
|
480
|
+
* literals are stable; `failed` may also surface a raw gateway decline code,
|
|
481
|
+
* so the type stays open (`string & {}`) without losing autocomplete.
|
|
482
|
+
*/
|
|
483
|
+
type ChargeNowReason = 'no_email' | 'lock_lost' | 'no_saved_payment_method' | 'card_expired' | 'payment_method_missing' | 'customer_missing' | (string & {});
|
|
484
|
+
interface ChargeNowResult {
|
|
485
|
+
outcome: ChargeNowOutcome;
|
|
486
|
+
/** Cycle that was dispatched/attempted, or `null` for one-time charges. */
|
|
487
|
+
cycleNumber: number | null;
|
|
488
|
+
/** Present on `not_sent` / `failed`. See {@link ChargeNowReason}. */
|
|
489
|
+
reason?: ChargeNowReason;
|
|
490
|
+
/** Ready-to-show pt-BR message describing the outcome. */
|
|
491
|
+
message: string;
|
|
492
|
+
}
|
|
459
493
|
interface Product {
|
|
460
494
|
id: number;
|
|
461
495
|
uuid: string;
|
|
@@ -1035,6 +1069,35 @@ declare class ScheduledCharges {
|
|
|
1035
1069
|
* });
|
|
1036
1070
|
*/
|
|
1037
1071
|
markPaid(id: string, params: MarkPaidScheduledChargeParams): Promise<ScheduledChargeRecord>;
|
|
1072
|
+
/**
|
|
1073
|
+
* Force-bill the current cycle right now instead of waiting for its due
|
|
1074
|
+
* date. Runs the same dispatch the daily billing cron would (customer
|
|
1075
|
+
* email/notification + outbound webhook + timeline event). Allowed only
|
|
1076
|
+
* from a billable status (`scheduled` / `due_today`); a recurring series
|
|
1077
|
+
* must have an open cycle (else the backend returns 400).
|
|
1078
|
+
*
|
|
1079
|
+
* Idempotent: if this cycle's d-day was already dispatched it reports
|
|
1080
|
+
* `already_sent` and does not re-charge. Inspect `outcome` to branch.
|
|
1081
|
+
*
|
|
1082
|
+
* @example
|
|
1083
|
+
* const result = await garu.scheduledCharges.chargeNow('sch_abc123');
|
|
1084
|
+
* switch (result.outcome) {
|
|
1085
|
+
* case 'dispatched':
|
|
1086
|
+
* console.log(`Cobrança enviada (ciclo ${result.cycleNumber}).`);
|
|
1087
|
+
* break;
|
|
1088
|
+
* case 'already_sent':
|
|
1089
|
+
* console.log('Já havia sido enviada — nada a fazer.');
|
|
1090
|
+
* break;
|
|
1091
|
+
* case 'failed':
|
|
1092
|
+
* // result.reason is e.g. 'card_expired' or a gateway decline code
|
|
1093
|
+
* console.error(`Falha na cobrança: ${result.reason}. ${result.message}`);
|
|
1094
|
+
* break;
|
|
1095
|
+
* case 'not_sent':
|
|
1096
|
+
* console.warn(`Não enviada (${result.reason}): ${result.message}`);
|
|
1097
|
+
* break;
|
|
1098
|
+
* }
|
|
1099
|
+
*/
|
|
1100
|
+
chargeNow(id: string): Promise<ChargeNowResult>;
|
|
1038
1101
|
/**
|
|
1039
1102
|
* Stop future cycles for a recurring series. The currently in-flight
|
|
1040
1103
|
* cycle (if any) remains active until paid, postponed, or marked-paid;
|
|
@@ -1289,4 +1352,4 @@ declare class GaruServerError extends GaruAPIError {
|
|
|
1289
1352
|
constructor(message: string, status: number, requestId: string | null, body: unknown);
|
|
1290
1353
|
}
|
|
1291
1354
|
|
|
1292
|
-
export { type CancelAtPeriodEndScheduledChargeParams, type CancelRecurrenceScheduledChargeParams, type CardInfo, type ChangePaymentMethodScheduledChargeParams, type Charge, type ChargeList, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type CreateScheduledChargeParams, type Customer, type CustomerList, type CustomerRecord, type FailurePayload, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, type GaruFailureCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type ListProductsParams, type ListScheduledChargeAttemptsParams, type ListScheduledChargesParams, type ListWebhookEventsParams, type MarkPaidScheduledChargeParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PauseScheduledChargeParams, type PaymentMethod, type PaymentMethodExpiredPayload, type PaymentMethodExpiringPayload, type PostponeScheduledChargeParams, type Product, type ProductList, type ProductPortalConfig, type RecurrenceConfig, type RecurrenceInterval, type RefundChargeParams, type ResendWebhookEventParams, type ScheduledChargeActor, type ScheduledChargeAttempt, type ScheduledChargeAttemptList, type ScheduledChargeAttemptSource, type ScheduledChargeAttemptStatus, type ScheduledChargeDetail, type ScheduledChargeEvent, type ScheduledChargeEventType, type ScheduledChargeLinkedTransaction, type ScheduledChargeList, type ScheduledChargeRecord, type ScheduledChargeStatus, type ScheduledChargeType, type ScheduledPaymentMethod, type SetProductPortalConfigParams, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WebhookEvent, type WebhookEventEndpoint, type WebhookEventList, type WebhookEventStatus, type WirePaymentMethodId, webhooks };
|
|
1355
|
+
export { type CancelAtPeriodEndScheduledChargeParams, type CancelRecurrenceScheduledChargeParams, type CardInfo, type ChangePaymentMethodScheduledChargeParams, type Charge, type ChargeList, type ChargeNowOutcome, type ChargeNowReason, type ChargeNowResult, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type CreateScheduledChargeParams, type Customer, type CustomerList, type CustomerRecord, type FailurePayload, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, type GaruFailureCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type ListProductsParams, type ListScheduledChargeAttemptsParams, type ListScheduledChargesParams, type ListWebhookEventsParams, type MarkPaidScheduledChargeParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PauseScheduledChargeParams, type PaymentMethod, type PaymentMethodExpiredPayload, type PaymentMethodExpiringPayload, type PostponeScheduledChargeParams, type Product, type ProductList, type ProductPortalConfig, type RecurrenceConfig, type RecurrenceInterval, type RefundChargeParams, type ResendWebhookEventParams, type ScheduledChargeActor, type ScheduledChargeAttempt, type ScheduledChargeAttemptList, type ScheduledChargeAttemptSource, type ScheduledChargeAttemptStatus, type ScheduledChargeDetail, type ScheduledChargeEvent, type ScheduledChargeEventType, type ScheduledChargeLinkedTransaction, type ScheduledChargeList, type ScheduledChargeRecord, type ScheduledChargeStatus, type ScheduledChargeType, type ScheduledPaymentMethod, type SetProductPortalConfigParams, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WebhookEvent, type WebhookEventEndpoint, type WebhookEventList, type WebhookEventStatus, type WirePaymentMethodId, webhooks };
|
package/dist/index.js
CHANGED
|
@@ -647,9 +647,9 @@ var ScheduledCharges = class {
|
|
|
647
647
|
*/
|
|
648
648
|
async get(id) {
|
|
649
649
|
return this.http.call(
|
|
650
|
-
(signal) => this.http.client.GET(`/api/scheduled-charges/${id}`, {
|
|
651
|
-
|
|
652
|
-
)
|
|
650
|
+
(signal) => this.http.client.GET(`/api/scheduled-charges/${encodeURIComponent(id)}`, {
|
|
651
|
+
signal
|
|
652
|
+
}).then((r) => r)
|
|
653
653
|
);
|
|
654
654
|
}
|
|
655
655
|
/**
|
|
@@ -665,10 +665,13 @@ var ScheduledCharges = class {
|
|
|
665
665
|
*/
|
|
666
666
|
async postpone(id, params) {
|
|
667
667
|
return this.http.call(
|
|
668
|
-
(signal) => this.http.client.POST(
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
668
|
+
(signal) => this.http.client.POST(
|
|
669
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/postpone`,
|
|
670
|
+
{
|
|
671
|
+
body: params,
|
|
672
|
+
signal
|
|
673
|
+
}
|
|
674
|
+
).then((r) => r)
|
|
672
675
|
);
|
|
673
676
|
}
|
|
674
677
|
/**
|
|
@@ -681,10 +684,13 @@ var ScheduledCharges = class {
|
|
|
681
684
|
*/
|
|
682
685
|
async pause(id, params = {}) {
|
|
683
686
|
return this.http.call(
|
|
684
|
-
(signal) => this.http.client.POST(
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
687
|
+
(signal) => this.http.client.POST(
|
|
688
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/pause`,
|
|
689
|
+
{
|
|
690
|
+
body: params,
|
|
691
|
+
signal
|
|
692
|
+
}
|
|
693
|
+
).then((r) => r)
|
|
688
694
|
);
|
|
689
695
|
}
|
|
690
696
|
/**
|
|
@@ -695,10 +701,13 @@ var ScheduledCharges = class {
|
|
|
695
701
|
*/
|
|
696
702
|
async resume(id) {
|
|
697
703
|
return this.http.call(
|
|
698
|
-
(signal) => this.http.client.POST(
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
704
|
+
(signal) => this.http.client.POST(
|
|
705
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/resume`,
|
|
706
|
+
{
|
|
707
|
+
body: {},
|
|
708
|
+
signal
|
|
709
|
+
}
|
|
710
|
+
).then((r) => r)
|
|
702
711
|
);
|
|
703
712
|
}
|
|
704
713
|
/**
|
|
@@ -726,10 +735,52 @@ var ScheduledCharges = class {
|
|
|
726
735
|
*/
|
|
727
736
|
async markPaid(id, params) {
|
|
728
737
|
return this.http.call(
|
|
729
|
-
(signal) => this.http.client.POST(
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
738
|
+
(signal) => this.http.client.POST(
|
|
739
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/mark-paid`,
|
|
740
|
+
{
|
|
741
|
+
body: params,
|
|
742
|
+
signal
|
|
743
|
+
}
|
|
744
|
+
).then((r) => r)
|
|
745
|
+
);
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Force-bill the current cycle right now instead of waiting for its due
|
|
749
|
+
* date. Runs the same dispatch the daily billing cron would (customer
|
|
750
|
+
* email/notification + outbound webhook + timeline event). Allowed only
|
|
751
|
+
* from a billable status (`scheduled` / `due_today`); a recurring series
|
|
752
|
+
* must have an open cycle (else the backend returns 400).
|
|
753
|
+
*
|
|
754
|
+
* Idempotent: if this cycle's d-day was already dispatched it reports
|
|
755
|
+
* `already_sent` and does not re-charge. Inspect `outcome` to branch.
|
|
756
|
+
*
|
|
757
|
+
* @example
|
|
758
|
+
* const result = await garu.scheduledCharges.chargeNow('sch_abc123');
|
|
759
|
+
* switch (result.outcome) {
|
|
760
|
+
* case 'dispatched':
|
|
761
|
+
* console.log(`Cobrança enviada (ciclo ${result.cycleNumber}).`);
|
|
762
|
+
* break;
|
|
763
|
+
* case 'already_sent':
|
|
764
|
+
* console.log('Já havia sido enviada — nada a fazer.');
|
|
765
|
+
* break;
|
|
766
|
+
* case 'failed':
|
|
767
|
+
* // result.reason is e.g. 'card_expired' or a gateway decline code
|
|
768
|
+
* console.error(`Falha na cobrança: ${result.reason}. ${result.message}`);
|
|
769
|
+
* break;
|
|
770
|
+
* case 'not_sent':
|
|
771
|
+
* console.warn(`Não enviada (${result.reason}): ${result.message}`);
|
|
772
|
+
* break;
|
|
773
|
+
* }
|
|
774
|
+
*/
|
|
775
|
+
async chargeNow(id) {
|
|
776
|
+
return this.http.call(
|
|
777
|
+
(signal) => this.http.client.POST(
|
|
778
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/charge-now`,
|
|
779
|
+
{
|
|
780
|
+
body: {},
|
|
781
|
+
signal
|
|
782
|
+
}
|
|
783
|
+
).then((r) => r)
|
|
733
784
|
);
|
|
734
785
|
}
|
|
735
786
|
/**
|
|
@@ -745,10 +796,13 @@ var ScheduledCharges = class {
|
|
|
745
796
|
*/
|
|
746
797
|
async cancelRecurrence(id, params = {}) {
|
|
747
798
|
return this.http.call(
|
|
748
|
-
(signal) => this.http.client.POST(
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
799
|
+
(signal) => this.http.client.POST(
|
|
800
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/cancel-recurrence`,
|
|
801
|
+
{
|
|
802
|
+
body: params,
|
|
803
|
+
signal
|
|
804
|
+
}
|
|
805
|
+
).then((r) => r)
|
|
752
806
|
);
|
|
753
807
|
}
|
|
754
808
|
/**
|
|
@@ -762,10 +816,13 @@ var ScheduledCharges = class {
|
|
|
762
816
|
*/
|
|
763
817
|
async setCancelAtPeriodEnd(id, params) {
|
|
764
818
|
return this.http.call(
|
|
765
|
-
(signal) => this.http.client.POST(
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
819
|
+
(signal) => this.http.client.POST(
|
|
820
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/cancel-at-period-end`,
|
|
821
|
+
{
|
|
822
|
+
body: params,
|
|
823
|
+
signal
|
|
824
|
+
}
|
|
825
|
+
).then((r) => r)
|
|
769
826
|
);
|
|
770
827
|
}
|
|
771
828
|
/**
|
|
@@ -778,10 +835,13 @@ var ScheduledCharges = class {
|
|
|
778
835
|
*/
|
|
779
836
|
async changePaymentMethod(id, params) {
|
|
780
837
|
return this.http.call(
|
|
781
|
-
(signal) => this.http.client.POST(
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
838
|
+
(signal) => this.http.client.POST(
|
|
839
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/payment-method`,
|
|
840
|
+
{
|
|
841
|
+
body: params,
|
|
842
|
+
signal
|
|
843
|
+
}
|
|
844
|
+
).then((r) => r)
|
|
785
845
|
);
|
|
786
846
|
}
|
|
787
847
|
/**
|
|
@@ -794,10 +854,13 @@ var ScheduledCharges = class {
|
|
|
794
854
|
*/
|
|
795
855
|
async clearPaymentMethod(id) {
|
|
796
856
|
return this.http.call(
|
|
797
|
-
(signal) => this.http.client.DELETE(
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
857
|
+
(signal) => this.http.client.DELETE(
|
|
858
|
+
`/api/scheduled-charges/${encodeURIComponent(id)}/payment-method`,
|
|
859
|
+
{
|
|
860
|
+
body: {},
|
|
861
|
+
signal
|
|
862
|
+
}
|
|
863
|
+
).then((r) => r)
|
|
801
864
|
);
|
|
802
865
|
}
|
|
803
866
|
/**
|
|
@@ -819,7 +882,7 @@ var ScheduledCharges = class {
|
|
|
819
882
|
if (params.limit !== void 0) qs.set("limit", String(params.limit));
|
|
820
883
|
if (params.cycleNumber !== void 0) qs.set("cycleNumber", String(params.cycleNumber));
|
|
821
884
|
const query = qs.toString();
|
|
822
|
-
const url = `/api/scheduled-charges/${id}/attempts${query ? `?${query}` : ""}`;
|
|
885
|
+
const url = `/api/scheduled-charges/${encodeURIComponent(id)}/attempts${query ? `?${query}` : ""}`;
|
|
823
886
|
return this.http.call(
|
|
824
887
|
(signal) => this.http.client.GET(url, { signal }).then(
|
|
825
888
|
(r) => r
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@garuhq/node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Official Node.js / TypeScript SDK for the Garu payment gateway.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://garu.com.br",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"typecheck": "tsc --noEmit",
|
|
47
47
|
"test": "vitest run",
|
|
48
48
|
"test:watch": "vitest",
|
|
49
|
-
"generate:fetch": "curl -sf ${GARU_SPEC_URL:-https://garu.com.br/api/
|
|
49
|
+
"generate:fetch": "curl -sf ${GARU_SPEC_URL:-https://garu.com.br/api/openapi.json} -o src/generated/openapi.json",
|
|
50
50
|
"generate:filter": "node scripts/filter-spec.mjs",
|
|
51
51
|
"generate": "npm run generate:fetch && npm run generate:filter && openapi-typescript src/generated/openapi-sdk.json -o src/generated/schema.d.ts",
|
|
52
52
|
"prepublishOnly": "npm run typecheck && npm test && npm run build"
|