@garuhq/cli 0.8.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 +56 -0
- package/README.md +130 -19
- package/dist/index.cjs +773 -180
- package/package.json +2 -2
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;
|
|
@@ -233,6 +233,192 @@ function createGaruClient(opts) {
|
|
|
233
233
|
});
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
+
// src/lib/parse.ts
|
|
237
|
+
function parsePositiveIntId(raw, label) {
|
|
238
|
+
const id = Number.parseInt(raw, 10);
|
|
239
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
240
|
+
throw new CliError("invalid_input", `${label} must be a positive integer (got '${raw}')`);
|
|
241
|
+
}
|
|
242
|
+
return id;
|
|
243
|
+
}
|
|
244
|
+
function parsePaymentMethod(raw) {
|
|
245
|
+
if (raw === "pix" || raw === "credit_card" || raw === "boleto") return raw;
|
|
246
|
+
throw new CliError(
|
|
247
|
+
"invalid_input",
|
|
248
|
+
`--type must be 'pix', 'credit_card', or 'boleto' (got '${raw}')`
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
function toChargePaymentMethod(type) {
|
|
252
|
+
return type === "credit_card" ? "creditCard" : type;
|
|
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
|
+
}
|
|
261
|
+
function parseChargePaymentMethodFilter(raw) {
|
|
262
|
+
return toChargePaymentMethod(parsePaymentMethod(raw));
|
|
263
|
+
}
|
|
264
|
+
var CHARGE_STATUSES = [
|
|
265
|
+
"pending",
|
|
266
|
+
"authorized",
|
|
267
|
+
"paid",
|
|
268
|
+
"failed",
|
|
269
|
+
"expired",
|
|
270
|
+
"canceled",
|
|
271
|
+
"refund_pending",
|
|
272
|
+
"refunded",
|
|
273
|
+
"chargeback"
|
|
274
|
+
];
|
|
275
|
+
function parseChargeStatus(raw) {
|
|
276
|
+
if (CHARGE_STATUSES.includes(raw)) return raw;
|
|
277
|
+
throw new CliError(
|
|
278
|
+
"invalid_input",
|
|
279
|
+
`--status must be one of ${CHARGE_STATUSES.join(", ")} (got '${raw}')`
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
var INSTALLMENT_PLAN_STATUSES = [
|
|
283
|
+
"pending_activation",
|
|
284
|
+
"active",
|
|
285
|
+
"completed",
|
|
286
|
+
"defaulted",
|
|
287
|
+
"canceled",
|
|
288
|
+
"refunded"
|
|
289
|
+
];
|
|
290
|
+
function parseInstallmentPlanStatus(raw) {
|
|
291
|
+
if (INSTALLMENT_PLAN_STATUSES.includes(raw)) return raw;
|
|
292
|
+
throw new CliError(
|
|
293
|
+
"invalid_input",
|
|
294
|
+
`--status must be one of ${INSTALLMENT_PLAN_STATUSES.join(", ")} (got '${raw}')`
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
var REFUND_REQUEST_STATUSES = ["pending", "confirmed", "rejected"];
|
|
298
|
+
function parseRefundRequestStatus(raw) {
|
|
299
|
+
if (REFUND_REQUEST_STATUSES.includes(raw)) return raw;
|
|
300
|
+
throw new CliError(
|
|
301
|
+
"invalid_input",
|
|
302
|
+
`--status must be one of ${REFUND_REQUEST_STATUSES.join(", ")} (got '${raw}')`
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
function parseWebhookEventStatus(raw) {
|
|
306
|
+
if (raw === "pending" || raw === "success" || raw === "failed") return raw;
|
|
307
|
+
throw new CliError(
|
|
308
|
+
"invalid_input",
|
|
309
|
+
`--status must be 'pending', 'success', or 'failed' (got '${raw}')`
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
function parseScheduledChargeType(raw) {
|
|
313
|
+
if (raw === "one_time" || raw === "recurring") return raw;
|
|
314
|
+
throw new CliError("invalid_input", `--type must be 'one_time' or 'recurring' (got '${raw}')`);
|
|
315
|
+
}
|
|
316
|
+
var SCHEDULED_PAYMENT_METHODS = [
|
|
317
|
+
"pix",
|
|
318
|
+
"boleto",
|
|
319
|
+
"card",
|
|
320
|
+
"pix_automatic"
|
|
321
|
+
];
|
|
322
|
+
function parseCsvList(raw) {
|
|
323
|
+
return raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
324
|
+
}
|
|
325
|
+
function parseScheduledPaymentMethods(raw) {
|
|
326
|
+
const parts = parseCsvList(raw);
|
|
327
|
+
if (parts.length === 0) {
|
|
328
|
+
throw new CliError(
|
|
329
|
+
"invalid_input",
|
|
330
|
+
`--methods must list at least one of: ${SCHEDULED_PAYMENT_METHODS.join(", ")}`
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
for (const p of parts) {
|
|
334
|
+
if (!SCHEDULED_PAYMENT_METHODS.includes(p)) {
|
|
335
|
+
throw new CliError(
|
|
336
|
+
"invalid_input",
|
|
337
|
+
`--methods entries must be one of ${SCHEDULED_PAYMENT_METHODS.join(", ")} (got '${p}')`
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return parts;
|
|
342
|
+
}
|
|
343
|
+
var RECURRENCE_INTERVALS = [
|
|
344
|
+
"weekly",
|
|
345
|
+
"biweekly",
|
|
346
|
+
"monthly",
|
|
347
|
+
"bimonthly",
|
|
348
|
+
"quarterly",
|
|
349
|
+
"biannual",
|
|
350
|
+
"yearly"
|
|
351
|
+
];
|
|
352
|
+
function parseRecurrenceInterval(raw) {
|
|
353
|
+
if (RECURRENCE_INTERVALS.includes(raw)) return raw;
|
|
354
|
+
throw new CliError(
|
|
355
|
+
"invalid_input",
|
|
356
|
+
`--recurrence-interval must be one of ${RECURRENCE_INTERVALS.join(", ")} (got '${raw}')`
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
var SCHEDULED_CHARGE_STATUSES = [
|
|
360
|
+
"scheduled",
|
|
361
|
+
"due_today",
|
|
362
|
+
"overdue",
|
|
363
|
+
"paid",
|
|
364
|
+
"paused",
|
|
365
|
+
"canceled",
|
|
366
|
+
"trial",
|
|
367
|
+
"pending_tokenization",
|
|
368
|
+
"recurrence_canceled"
|
|
369
|
+
];
|
|
370
|
+
function parseScheduledChargeStatus(raw) {
|
|
371
|
+
if (SCHEDULED_CHARGE_STATUSES.includes(raw)) return raw;
|
|
372
|
+
throw new CliError(
|
|
373
|
+
"invalid_input",
|
|
374
|
+
`--status must be one of ${SCHEDULED_CHARGE_STATUSES.join(", ")} (got '${raw}')`
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
function parseIntInRange(raw, label, min, max) {
|
|
378
|
+
const trimmed = raw.trim();
|
|
379
|
+
const n = Number.parseInt(trimmed, 10);
|
|
380
|
+
if (!Number.isFinite(n) || String(n) !== trimmed || n < min || n > max) {
|
|
381
|
+
throw new CliError(
|
|
382
|
+
"invalid_input",
|
|
383
|
+
`${label} must be an integer between ${min} and ${max} (got '${raw}')`
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
return n;
|
|
387
|
+
}
|
|
388
|
+
function parseNonNegativeBrl(raw, label) {
|
|
389
|
+
const trimmed = raw.trim();
|
|
390
|
+
const n = Number(trimmed);
|
|
391
|
+
if (trimmed === "" || !Number.isFinite(n) || n < 0) {
|
|
392
|
+
throw new CliError(
|
|
393
|
+
"invalid_input",
|
|
394
|
+
`${label} must be a non-negative amount in BRL/reais, e.g. 49.90 (got '${raw}')`
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
return n;
|
|
398
|
+
}
|
|
399
|
+
function parseAmountBrl(raw) {
|
|
400
|
+
const n = Number(raw);
|
|
401
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
402
|
+
throw new CliError(
|
|
403
|
+
"invalid_input",
|
|
404
|
+
`--amount must be a positive decimal in BRL, e.g. 297.50 (got '${raw}')`
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
return n;
|
|
408
|
+
}
|
|
409
|
+
function parseMetadata(raw) {
|
|
410
|
+
let parsed;
|
|
411
|
+
try {
|
|
412
|
+
parsed = JSON.parse(raw);
|
|
413
|
+
} catch {
|
|
414
|
+
throw new CliError("invalid_input", `--metadata must be valid JSON (got '${raw}')`);
|
|
415
|
+
}
|
|
416
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
417
|
+
throw new CliError("invalid_input", `--metadata must be a JSON object`);
|
|
418
|
+
}
|
|
419
|
+
return parsed;
|
|
420
|
+
}
|
|
421
|
+
|
|
236
422
|
// src/commands/charges.ts
|
|
237
423
|
async function getClient(opts) {
|
|
238
424
|
if (opts.garu) return opts.garu;
|
|
@@ -275,8 +461,9 @@ async function chargesCreateCommand(opts) {
|
|
|
275
461
|
assertCardFieldsPresent(opts);
|
|
276
462
|
charge = await garu.charges.create({
|
|
277
463
|
...base,
|
|
278
|
-
|
|
279
|
-
|
|
464
|
+
paymentMethod: toChargePaymentMethod(opts.type),
|
|
465
|
+
card: {
|
|
466
|
+
number: opts.cardNumber,
|
|
280
467
|
cvv: opts.cardCvv,
|
|
281
468
|
expirationDate: opts.cardExpiration,
|
|
282
469
|
holderName: opts.cardHolder,
|
|
@@ -284,14 +471,17 @@ async function chargesCreateCommand(opts) {
|
|
|
284
471
|
}
|
|
285
472
|
});
|
|
286
473
|
} else {
|
|
287
|
-
charge = await garu.charges.create(
|
|
474
|
+
charge = await garu.charges.create({
|
|
475
|
+
...base,
|
|
476
|
+
paymentMethod: toChargePaymentMethod(opts.type)
|
|
477
|
+
});
|
|
288
478
|
}
|
|
289
479
|
printResult(charge, { ...opts, prettyPrint: prettyCharge });
|
|
290
480
|
return charge;
|
|
291
481
|
}
|
|
292
482
|
async function chargesGetCommand(opts) {
|
|
293
483
|
const garu = await getClient(opts);
|
|
294
|
-
const charge = await garu.charges.
|
|
484
|
+
const charge = await garu.charges.retrieve(opts.id);
|
|
295
485
|
printResult(charge, { ...opts, prettyPrint: prettyCharge });
|
|
296
486
|
return charge;
|
|
297
487
|
}
|
|
@@ -300,7 +490,6 @@ async function chargesRefundCommand(opts) {
|
|
|
300
490
|
const params = {};
|
|
301
491
|
if (opts.amount !== void 0) params.amount = opts.amount;
|
|
302
492
|
if (opts.reason !== void 0) params.reason = opts.reason;
|
|
303
|
-
if (opts.idempotencyKey !== void 0) params.idempotencyKey = opts.idempotencyKey;
|
|
304
493
|
const charge = await garu.charges.refund(opts.id, params);
|
|
305
494
|
printResult(charge, { ...opts, prettyPrint: prettyCharge });
|
|
306
495
|
return charge;
|
|
@@ -319,23 +508,128 @@ async function chargesListCommand(opts) {
|
|
|
319
508
|
}
|
|
320
509
|
function prettyChargeList(list) {
|
|
321
510
|
if (list.data.length === 0) {
|
|
322
|
-
return
|
|
511
|
+
return "No charges found";
|
|
323
512
|
}
|
|
324
|
-
const header = `Charges (
|
|
513
|
+
const header = `Charges (${list.count} of ${list.totalCount} total, ${list.totalPages} page(s))`;
|
|
325
514
|
const rows = list.data.map(
|
|
326
|
-
(c) => ` ${
|
|
515
|
+
(c) => ` ${c.uuid} ${String(c.status).padEnd(14)} ${c.paymentMethod.padEnd(10)} ${c.createdAt}`
|
|
327
516
|
);
|
|
328
517
|
return [header, ...rows].join("\n");
|
|
329
518
|
}
|
|
330
519
|
function prettyCharge(charge) {
|
|
331
520
|
const lines = [
|
|
332
|
-
`Charge ${charge.
|
|
333
|
-
` status:
|
|
334
|
-
` amount:
|
|
335
|
-
`
|
|
336
|
-
`
|
|
521
|
+
`Charge ${charge.uuid}`,
|
|
522
|
+
` status: ${charge.status}`,
|
|
523
|
+
` amount: ${charge.amount}`,
|
|
524
|
+
` chargedTotal: ${charge.chargedTotal}`,
|
|
525
|
+
` method: ${charge.paymentMethod}`,
|
|
526
|
+
` createdAt: ${charge.createdAt}`
|
|
527
|
+
];
|
|
528
|
+
if (charge.expiresAt) lines.push(` expiresAt: ${charge.expiresAt}`);
|
|
529
|
+
if (charge.refund)
|
|
530
|
+
lines.push(` refund: ${charge.refund.amount} (${charge.refund.reason ?? "no reason"})`);
|
|
531
|
+
return lines.join("\n");
|
|
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)" : ""}`
|
|
337
632
|
];
|
|
338
|
-
if (charge.deadline) lines.push(` deadline: ${charge.deadline}`);
|
|
339
633
|
return lines.join("\n");
|
|
340
634
|
}
|
|
341
635
|
async function doctorCommand(opts = {}) {
|
|
@@ -430,6 +724,152 @@ function prettyDoctor(r) {
|
|
|
430
724
|
].filter((l) => l !== void 0);
|
|
431
725
|
return lines.join("\n");
|
|
432
726
|
}
|
|
727
|
+
|
|
728
|
+
// src/commands/installment-plans.ts
|
|
729
|
+
async function getClient3(opts) {
|
|
730
|
+
if (opts.garu) return opts.garu;
|
|
731
|
+
const auth = await resolveAuth({
|
|
732
|
+
...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
|
|
733
|
+
...opts.profile !== void 0 ? { profile: opts.profile } : {}
|
|
734
|
+
});
|
|
735
|
+
return createGaruClient({
|
|
736
|
+
auth,
|
|
737
|
+
...opts.baseUrl !== void 0 ? { baseUrl: opts.baseUrl } : {}
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
async function installmentPlansCreateCommand(opts) {
|
|
741
|
+
const garu = await getClient3(opts);
|
|
742
|
+
const params = {
|
|
743
|
+
productId: opts.productId,
|
|
744
|
+
customerId: opts.customerId,
|
|
745
|
+
installments: opts.installments
|
|
746
|
+
};
|
|
747
|
+
if (opts.firstDueDate !== void 0) params.firstDueDate = opts.firstDueDate;
|
|
748
|
+
if (opts.affiliateId !== void 0) params.affiliateId = opts.affiliateId;
|
|
749
|
+
if (opts.idempotencyKey !== void 0) params.idempotencyKey = opts.idempotencyKey;
|
|
750
|
+
const plan = await garu.installmentPlans.create(params);
|
|
751
|
+
printResult(plan, { ...opts, prettyPrint: prettyInstallmentPlan });
|
|
752
|
+
return plan;
|
|
753
|
+
}
|
|
754
|
+
async function installmentPlansListCommand(opts) {
|
|
755
|
+
const garu = await getClient3(opts);
|
|
756
|
+
const params = {};
|
|
757
|
+
if (opts.page !== void 0) params.page = opts.page;
|
|
758
|
+
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
759
|
+
if (opts.customerId !== void 0) params.customerId = opts.customerId;
|
|
760
|
+
if (opts.productId !== void 0) params.productId = opts.productId;
|
|
761
|
+
if (opts.dueFrom !== void 0) params.dueFrom = opts.dueFrom;
|
|
762
|
+
if (opts.dueTo !== void 0) params.dueTo = opts.dueTo;
|
|
763
|
+
if (opts.status !== void 0 && opts.status.length > 0) {
|
|
764
|
+
params.status = opts.status.length === 1 ? opts.status[0] : opts.status;
|
|
765
|
+
}
|
|
766
|
+
const result = await garu.installmentPlans.list(params);
|
|
767
|
+
printResult(result, { ...opts, prettyPrint: prettyInstallmentPlanList });
|
|
768
|
+
return result;
|
|
769
|
+
}
|
|
770
|
+
async function installmentPlansGetCommand(opts) {
|
|
771
|
+
const garu = await getClient3(opts);
|
|
772
|
+
const plan = await garu.installmentPlans.get(opts.uuid);
|
|
773
|
+
printResult(plan, { ...opts, prettyPrint: prettyInstallmentPlanDetail });
|
|
774
|
+
return plan;
|
|
775
|
+
}
|
|
776
|
+
async function installmentPlansReissueCommand(opts) {
|
|
777
|
+
const garu = await getClient3(opts);
|
|
778
|
+
const result = await garu.installmentPlans.reissueInstallment(opts.uuid, opts.number);
|
|
779
|
+
printResult(result, { ...opts, prettyPrint: prettyReissueResult });
|
|
780
|
+
return result;
|
|
781
|
+
}
|
|
782
|
+
async function installmentPlansPostponeCommand(opts) {
|
|
783
|
+
const garu = await getClient3(opts);
|
|
784
|
+
const params = { newDueDate: opts.newDueDate };
|
|
785
|
+
const installment = await garu.installmentPlans.postponeInstallment(
|
|
786
|
+
opts.uuid,
|
|
787
|
+
opts.number,
|
|
788
|
+
params
|
|
789
|
+
);
|
|
790
|
+
printResult(installment, { ...opts, prettyPrint: prettyInstallment });
|
|
791
|
+
return installment;
|
|
792
|
+
}
|
|
793
|
+
async function installmentPlansMarkPaidCommand(opts) {
|
|
794
|
+
const garu = await getClient3(opts);
|
|
795
|
+
const installment = await garu.installmentPlans.markInstallmentPaid(opts.uuid, opts.number);
|
|
796
|
+
printResult(installment, { ...opts, prettyPrint: prettyInstallment });
|
|
797
|
+
return installment;
|
|
798
|
+
}
|
|
799
|
+
async function installmentPlansCancelCommand(opts) {
|
|
800
|
+
const garu = await getClient3(opts);
|
|
801
|
+
const params = {};
|
|
802
|
+
if (opts.note !== void 0) params.note = opts.note;
|
|
803
|
+
const plan = await garu.installmentPlans.cancel(opts.uuid, params);
|
|
804
|
+
printResult(plan, { ...opts, prettyPrint: prettyInstallmentPlan });
|
|
805
|
+
return plan;
|
|
806
|
+
}
|
|
807
|
+
async function installmentPlansRequestRefundCommand(opts) {
|
|
808
|
+
const garu = await getClient3(opts);
|
|
809
|
+
const params = {};
|
|
810
|
+
if (opts.amount !== void 0) params.amount = opts.amount;
|
|
811
|
+
if (opts.reason !== void 0) params.reason = opts.reason;
|
|
812
|
+
const request = await garu.installmentPlans.requestRefund(opts.uuid, params);
|
|
813
|
+
printResult(request, { ...opts, prettyPrint: prettyRefundRequest });
|
|
814
|
+
return request;
|
|
815
|
+
}
|
|
816
|
+
function prettyInstallmentPlan(p) {
|
|
817
|
+
const lines = [
|
|
818
|
+
`Installment plan ${p.uuid}`,
|
|
819
|
+
` status: ${p.status}`,
|
|
820
|
+
` installments: ${p.installmentsPaid}/${p.installments} paid`,
|
|
821
|
+
` baseValue: ${p.baseValue}`,
|
|
822
|
+
` installmentAmount: ${p.installmentAmount}`,
|
|
823
|
+
` totalScheduled: ${p.totalScheduled}`,
|
|
824
|
+
` totalCollected: ${p.totalCollected}`,
|
|
825
|
+
` firstDueDate: ${p.firstDueDate}`
|
|
826
|
+
];
|
|
827
|
+
if (p.product) lines.push(` product: ${p.product.name} (${p.product.uuid})`);
|
|
828
|
+
if (p.customer) lines.push(` customer: ${p.customer.name} <${p.customer.email}>`);
|
|
829
|
+
return lines.join("\n");
|
|
830
|
+
}
|
|
831
|
+
function prettyInstallmentPlanDetail(p) {
|
|
832
|
+
const lines = [prettyInstallmentPlan(p)];
|
|
833
|
+
if (p.installmentsDetail && p.installmentsDetail.length > 0) {
|
|
834
|
+
lines.push(" installments:");
|
|
835
|
+
for (const i of p.installmentsDetail) {
|
|
836
|
+
lines.push(
|
|
837
|
+
` #${i.number} ${i.status.padEnd(10)} ${String(i.amount).padStart(10)} due ${i.dueDate}${i.paidAt ? ` paid ${i.paidAt}` : ""}`
|
|
838
|
+
);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
return lines.join("\n");
|
|
842
|
+
}
|
|
843
|
+
function prettyInstallmentPlanList(list) {
|
|
844
|
+
if (list.data.length === 0) return "No installment plans found";
|
|
845
|
+
const header = `Installment plans (${list.count} of ${list.totalCount} total, ${list.totalPages} page(s))`;
|
|
846
|
+
const rows = list.data.map(
|
|
847
|
+
(p) => ` ${p.uuid} ${p.status.padEnd(18)} ${p.installmentsPaid}/${p.installments} paid ${p.firstDueDate}`
|
|
848
|
+
);
|
|
849
|
+
return [header, ...rows].join("\n");
|
|
850
|
+
}
|
|
851
|
+
function prettyInstallment(i) {
|
|
852
|
+
const lines = [
|
|
853
|
+
`Installment #${i.number}`,
|
|
854
|
+
` status: ${i.status}`,
|
|
855
|
+
` amount: ${i.amount}`,
|
|
856
|
+
` dueDate: ${i.dueDate}`
|
|
857
|
+
];
|
|
858
|
+
if (i.paidAt) lines.push(` paidAt: ${i.paidAt}`);
|
|
859
|
+
if (i.boleto) lines.push(` boleto: ${i.boleto.barcodeLine}`);
|
|
860
|
+
return lines.join("\n");
|
|
861
|
+
}
|
|
862
|
+
function prettyReissueResult(result) {
|
|
863
|
+
const lines = [`Reissue: ${result.status}`];
|
|
864
|
+
if (result.reason) lines.push(` reason: ${result.reason}`);
|
|
865
|
+
if (result.installment) lines.push(prettyInstallment(result.installment));
|
|
866
|
+
return lines.join("\n");
|
|
867
|
+
}
|
|
868
|
+
function prettyRefundRequest(r) {
|
|
869
|
+
const lines = [`Refund request ${r.uuid}`, ` status: ${r.status}`, ` amount: ${r.amount}`];
|
|
870
|
+
if (r.reason) lines.push(` reason: ${r.reason}`);
|
|
871
|
+
return lines.join("\n");
|
|
872
|
+
}
|
|
433
873
|
async function loginCommand(opts = {}) {
|
|
434
874
|
const profile = opts.profile ?? "default";
|
|
435
875
|
const apiKey = opts.apiKey ?? await import('@inquirer/prompts').then(
|
|
@@ -477,7 +917,7 @@ async function logoutCommand(opts = {}) {
|
|
|
477
917
|
}
|
|
478
918
|
|
|
479
919
|
// src/commands/products.ts
|
|
480
|
-
async function
|
|
920
|
+
async function getClient4(opts) {
|
|
481
921
|
if (opts.garu) return opts.garu;
|
|
482
922
|
const auth = await resolveAuth({
|
|
483
923
|
...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
|
|
@@ -508,7 +948,7 @@ function buildProductBody(opts) {
|
|
|
508
948
|
return body;
|
|
509
949
|
}
|
|
510
950
|
async function productsCreateCommand(opts) {
|
|
511
|
-
const garu = await
|
|
951
|
+
const garu = await getClient4(opts);
|
|
512
952
|
const params = { ...buildProductBody(opts), name: opts.name };
|
|
513
953
|
const product = await garu.products.create(params);
|
|
514
954
|
printSuccess(`Created product ${product.uuid ?? product.id}`, opts);
|
|
@@ -520,7 +960,7 @@ async function productsUpdateCommand(opts) {
|
|
|
520
960
|
if (Object.keys(body).length === 0) {
|
|
521
961
|
throw new CliError("invalid_input", "Nothing to update \u2014 pass at least one field to change.");
|
|
522
962
|
}
|
|
523
|
-
const garu = await
|
|
963
|
+
const garu = await getClient4(opts);
|
|
524
964
|
const product = await garu.products.update(opts.id, body);
|
|
525
965
|
printSuccess(`Updated product ${product.uuid ?? product.id}`, opts);
|
|
526
966
|
printResult(product, { ...opts, prettyPrint: prettyProduct });
|
|
@@ -543,8 +983,74 @@ function prettyProduct(p) {
|
|
|
543
983
|
return lines.join("\n");
|
|
544
984
|
}
|
|
545
985
|
|
|
986
|
+
// src/commands/refund-requests.ts
|
|
987
|
+
async function getClient5(opts) {
|
|
988
|
+
if (opts.garu) return opts.garu;
|
|
989
|
+
const auth = await resolveAuth({
|
|
990
|
+
...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
|
|
991
|
+
...opts.profile !== void 0 ? { profile: opts.profile } : {}
|
|
992
|
+
});
|
|
993
|
+
return createGaruClient({
|
|
994
|
+
auth,
|
|
995
|
+
...opts.baseUrl !== void 0 ? { baseUrl: opts.baseUrl } : {}
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
async function refundRequestsListCommand(opts) {
|
|
999
|
+
const garu = await getClient5(opts);
|
|
1000
|
+
const params = {};
|
|
1001
|
+
if (opts.page !== void 0) params.page = opts.page;
|
|
1002
|
+
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
1003
|
+
if (opts.planId !== void 0) params.planId = opts.planId;
|
|
1004
|
+
if (opts.chargeId !== void 0) params.chargeId = opts.chargeId;
|
|
1005
|
+
if (opts.status !== void 0 && opts.status.length > 0) {
|
|
1006
|
+
params.status = opts.status.length === 1 ? opts.status[0] : opts.status;
|
|
1007
|
+
}
|
|
1008
|
+
const result = await garu.refundRequests.list(params);
|
|
1009
|
+
printResult(result, { ...opts, prettyPrint: prettyRefundRequestList });
|
|
1010
|
+
return result;
|
|
1011
|
+
}
|
|
1012
|
+
async function refundRequestsGetCommand(opts) {
|
|
1013
|
+
const garu = await getClient5(opts);
|
|
1014
|
+
const request = await garu.refundRequests.get(opts.uuid);
|
|
1015
|
+
printResult(request, { ...opts, prettyPrint: prettyRefundRequest2 });
|
|
1016
|
+
return request;
|
|
1017
|
+
}
|
|
1018
|
+
async function refundRequestsConfirmCommand(opts) {
|
|
1019
|
+
const garu = await getClient5(opts);
|
|
1020
|
+
const params = {};
|
|
1021
|
+
if (opts.note !== void 0) params.note = opts.note;
|
|
1022
|
+
const request = await garu.refundRequests.confirm(opts.uuid, params);
|
|
1023
|
+
printResult(request, { ...opts, prettyPrint: prettyRefundRequest2 });
|
|
1024
|
+
return request;
|
|
1025
|
+
}
|
|
1026
|
+
async function refundRequestsRejectCommand(opts) {
|
|
1027
|
+
const garu = await getClient5(opts);
|
|
1028
|
+
const params = {};
|
|
1029
|
+
if (opts.note !== void 0) params.note = opts.note;
|
|
1030
|
+
const request = await garu.refundRequests.reject(opts.uuid, params);
|
|
1031
|
+
printResult(request, { ...opts, prettyPrint: prettyRefundRequest2 });
|
|
1032
|
+
return request;
|
|
1033
|
+
}
|
|
1034
|
+
function prettyRefundRequestList(list) {
|
|
1035
|
+
if (list.data.length === 0) return "No refund requests found";
|
|
1036
|
+
const header = `Refund requests (${list.count} of ${list.totalCount} total, ${list.totalPages} page(s))`;
|
|
1037
|
+
const rows = list.data.map(
|
|
1038
|
+
(r) => ` ${r.uuid} ${r.status.padEnd(10)} ${String(r.amount).padStart(10)} ${r.installmentPlanId ?? r.chargeId ?? ""}`
|
|
1039
|
+
);
|
|
1040
|
+
return [header, ...rows].join("\n");
|
|
1041
|
+
}
|
|
1042
|
+
function prettyRefundRequest2(r) {
|
|
1043
|
+
const lines = [`Refund request ${r.uuid}`, ` status: ${r.status}`, ` amount: ${r.amount}`];
|
|
1044
|
+
if (r.reason) lines.push(` reason: ${r.reason}`);
|
|
1045
|
+
if (r.installmentPlanId) lines.push(` installmentPlan: ${r.installmentPlanId}`);
|
|
1046
|
+
if (r.chargeId) lines.push(` charge: ${r.chargeId}`);
|
|
1047
|
+
if (r.resolvedAt) lines.push(` resolvedAt: ${r.resolvedAt}`);
|
|
1048
|
+
if (r.sellerNote) lines.push(` sellerNote: ${r.sellerNote}`);
|
|
1049
|
+
return lines.join("\n");
|
|
1050
|
+
}
|
|
1051
|
+
|
|
546
1052
|
// src/commands/scheduled-charges.ts
|
|
547
|
-
async function
|
|
1053
|
+
async function getClient6(opts) {
|
|
548
1054
|
if (opts.garu) return opts.garu;
|
|
549
1055
|
const auth = await resolveAuth({
|
|
550
1056
|
...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
|
|
@@ -581,7 +1087,7 @@ function assertPixAutomaticRequirements(opts) {
|
|
|
581
1087
|
}
|
|
582
1088
|
async function scheduledChargesCreateCommand(opts) {
|
|
583
1089
|
assertPixAutomaticRequirements(opts);
|
|
584
|
-
const garu = await
|
|
1090
|
+
const garu = await getClient6(opts);
|
|
585
1091
|
const params = {
|
|
586
1092
|
customerId: opts.customerId,
|
|
587
1093
|
amount: opts.amount,
|
|
@@ -603,7 +1109,7 @@ async function scheduledChargesCreateCommand(opts) {
|
|
|
603
1109
|
return charge;
|
|
604
1110
|
}
|
|
605
1111
|
async function scheduledChargesListCommand(opts) {
|
|
606
|
-
const garu = await
|
|
1112
|
+
const garu = await getClient6(opts);
|
|
607
1113
|
const params = {};
|
|
608
1114
|
if (opts.page !== void 0) params.page = opts.page;
|
|
609
1115
|
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
@@ -620,13 +1126,13 @@ async function scheduledChargesListCommand(opts) {
|
|
|
620
1126
|
return result;
|
|
621
1127
|
}
|
|
622
1128
|
async function scheduledChargesGetCommand(opts) {
|
|
623
|
-
const garu = await
|
|
1129
|
+
const garu = await getClient6(opts);
|
|
624
1130
|
const detail = await garu.scheduledCharges.get(opts.id);
|
|
625
1131
|
printResult(detail, { ...opts, prettyPrint: prettyScheduledChargeDetail });
|
|
626
1132
|
return detail;
|
|
627
1133
|
}
|
|
628
1134
|
async function scheduledChargesPostponeCommand(opts) {
|
|
629
|
-
const garu = await
|
|
1135
|
+
const garu = await getClient6(opts);
|
|
630
1136
|
const params = { newDueDate: opts.newDueDate };
|
|
631
1137
|
if (opts.reason !== void 0) params.reason = opts.reason;
|
|
632
1138
|
const charge = await garu.scheduledCharges.postpone(opts.id, params);
|
|
@@ -634,7 +1140,7 @@ async function scheduledChargesPostponeCommand(opts) {
|
|
|
634
1140
|
return charge;
|
|
635
1141
|
}
|
|
636
1142
|
async function scheduledChargesPauseCommand(opts) {
|
|
637
|
-
const garu = await
|
|
1143
|
+
const garu = await getClient6(opts);
|
|
638
1144
|
const params = {};
|
|
639
1145
|
if (opts.reason !== void 0) params.reason = opts.reason;
|
|
640
1146
|
const charge = await garu.scheduledCharges.pause(opts.id, params);
|
|
@@ -642,13 +1148,13 @@ async function scheduledChargesPauseCommand(opts) {
|
|
|
642
1148
|
return charge;
|
|
643
1149
|
}
|
|
644
1150
|
async function scheduledChargesResumeCommand(opts) {
|
|
645
|
-
const garu = await
|
|
1151
|
+
const garu = await getClient6(opts);
|
|
646
1152
|
const charge = await garu.scheduledCharges.resume(opts.id);
|
|
647
1153
|
printResult(charge, { ...opts, prettyPrint: prettyScheduledCharge });
|
|
648
1154
|
return charge;
|
|
649
1155
|
}
|
|
650
1156
|
async function scheduledChargesMarkPaidCommand(opts) {
|
|
651
|
-
const garu = await
|
|
1157
|
+
const garu = await getClient6(opts);
|
|
652
1158
|
const params = { paymentDate: opts.paymentDate };
|
|
653
1159
|
if (opts.externalReference !== void 0) params.externalReference = opts.externalReference;
|
|
654
1160
|
if (opts.cycleNumber !== void 0) params.cycleNumber = opts.cycleNumber;
|
|
@@ -657,7 +1163,7 @@ async function scheduledChargesMarkPaidCommand(opts) {
|
|
|
657
1163
|
return charge;
|
|
658
1164
|
}
|
|
659
1165
|
async function scheduledChargesCancelRecurrenceCommand(opts) {
|
|
660
|
-
const garu = await
|
|
1166
|
+
const garu = await getClient6(opts);
|
|
661
1167
|
const params = {};
|
|
662
1168
|
if (opts.reason !== void 0) params.reason = opts.reason;
|
|
663
1169
|
const charge = await garu.scheduledCharges.cancelRecurrence(opts.id, params);
|
|
@@ -665,14 +1171,14 @@ async function scheduledChargesCancelRecurrenceCommand(opts) {
|
|
|
665
1171
|
return charge;
|
|
666
1172
|
}
|
|
667
1173
|
async function scheduledChargesCancelAtPeriodEndCommand(opts) {
|
|
668
|
-
const garu = await
|
|
1174
|
+
const garu = await getClient6(opts);
|
|
669
1175
|
const params = { enabled: opts.enabled };
|
|
670
1176
|
const charge = await garu.scheduledCharges.setCancelAtPeriodEnd(opts.id, params);
|
|
671
1177
|
printResult(charge, { ...opts, prettyPrint: prettyScheduledCharge });
|
|
672
1178
|
return charge;
|
|
673
1179
|
}
|
|
674
1180
|
async function scheduledChargesChangePaymentMethodCommand(opts) {
|
|
675
|
-
const garu = await
|
|
1181
|
+
const garu = await getClient6(opts);
|
|
676
1182
|
const params = {
|
|
677
1183
|
paymentMethodId: opts.paymentMethodId
|
|
678
1184
|
};
|
|
@@ -681,13 +1187,13 @@ async function scheduledChargesChangePaymentMethodCommand(opts) {
|
|
|
681
1187
|
return charge;
|
|
682
1188
|
}
|
|
683
1189
|
async function scheduledChargesClearPaymentMethodCommand(opts) {
|
|
684
|
-
const garu = await
|
|
1190
|
+
const garu = await getClient6(opts);
|
|
685
1191
|
const charge = await garu.scheduledCharges.clearPaymentMethod(opts.id);
|
|
686
1192
|
printResult(charge, { ...opts, prettyPrint: prettyScheduledCharge });
|
|
687
1193
|
return charge;
|
|
688
1194
|
}
|
|
689
1195
|
async function scheduledChargesAttemptsCommand(opts) {
|
|
690
|
-
const garu = await
|
|
1196
|
+
const garu = await getClient6(opts);
|
|
691
1197
|
const params = {};
|
|
692
1198
|
if (opts.page !== void 0) params.page = opts.page;
|
|
693
1199
|
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
@@ -697,7 +1203,7 @@ async function scheduledChargesAttemptsCommand(opts) {
|
|
|
697
1203
|
return result;
|
|
698
1204
|
}
|
|
699
1205
|
async function scheduledChargesChargeNowCommand(opts) {
|
|
700
|
-
const garu = await
|
|
1206
|
+
const garu = await getClient6(opts);
|
|
701
1207
|
const result = await garu.scheduledCharges.chargeNow(opts.id);
|
|
702
1208
|
printResult(result, { ...opts, prettyPrint: prettyChargeNow });
|
|
703
1209
|
if (result.outcome === "failed" || result.outcome === "not_sent") {
|
|
@@ -761,7 +1267,7 @@ function prettyChargeNow(result) {
|
|
|
761
1267
|
if (result.reason) lines.push(` reason: ${result.reason}`);
|
|
762
1268
|
return lines.join("\n");
|
|
763
1269
|
}
|
|
764
|
-
async function
|
|
1270
|
+
async function getClient7(opts) {
|
|
765
1271
|
if (opts.garu) return opts.garu;
|
|
766
1272
|
const auth = await resolveAuth({
|
|
767
1273
|
...opts.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
|
|
@@ -773,7 +1279,7 @@ async function getClient4(opts) {
|
|
|
773
1279
|
});
|
|
774
1280
|
}
|
|
775
1281
|
async function webhooksEventsListCommand(opts) {
|
|
776
|
-
const garu = await
|
|
1282
|
+
const garu = await getClient7(opts);
|
|
777
1283
|
const params = {};
|
|
778
1284
|
if (opts.page !== void 0) params.page = opts.page;
|
|
779
1285
|
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
@@ -785,19 +1291,19 @@ async function webhooksEventsListCommand(opts) {
|
|
|
785
1291
|
return result;
|
|
786
1292
|
}
|
|
787
1293
|
async function webhooksEventsGetCommand(opts) {
|
|
788
|
-
const garu = await
|
|
1294
|
+
const garu = await getClient7(opts);
|
|
789
1295
|
const event = await garu.webhookEvents.get(opts.id);
|
|
790
1296
|
printResult(event, { ...opts, prettyPrint: prettyWebhookEvent });
|
|
791
1297
|
return event;
|
|
792
1298
|
}
|
|
793
1299
|
async function webhooksEventsRetryCommand(opts) {
|
|
794
|
-
const garu = await
|
|
1300
|
+
const garu = await getClient7(opts);
|
|
795
1301
|
const event = await garu.webhookEvents.retry(opts.id);
|
|
796
1302
|
printResult(event, { ...opts, prettyPrint: prettyWebhookEvent });
|
|
797
1303
|
return event;
|
|
798
1304
|
}
|
|
799
1305
|
async function webhooksEventsResendCommand(opts) {
|
|
800
|
-
const garu = await
|
|
1306
|
+
const garu = await getClient7(opts);
|
|
801
1307
|
const clone = await garu.webhookEvents.resend(opts.id);
|
|
802
1308
|
printSuccess(`Resent event ${opts.id} \u2192 new event ${clone.id}`, opts);
|
|
803
1309
|
printResult(clone, { ...opts, prettyPrint: prettyWebhookEvent });
|
|
@@ -839,138 +1345,6 @@ function prettyWebhookEvent(event) {
|
|
|
839
1345
|
return lines.join("\n");
|
|
840
1346
|
}
|
|
841
1347
|
|
|
842
|
-
// src/lib/parse.ts
|
|
843
|
-
function parsePositiveIntId(raw, label) {
|
|
844
|
-
const id = Number.parseInt(raw, 10);
|
|
845
|
-
if (!Number.isFinite(id) || id <= 0) {
|
|
846
|
-
throw new CliError("invalid_input", `${label} must be a positive integer (got '${raw}')`);
|
|
847
|
-
}
|
|
848
|
-
return id;
|
|
849
|
-
}
|
|
850
|
-
function parsePaymentMethod(raw) {
|
|
851
|
-
if (raw === "pix" || raw === "credit_card" || raw === "boleto") return raw;
|
|
852
|
-
throw new CliError(
|
|
853
|
-
"invalid_input",
|
|
854
|
-
`--type must be 'pix', 'credit_card', or 'boleto' (got '${raw}')`
|
|
855
|
-
);
|
|
856
|
-
}
|
|
857
|
-
function parseWebhookEventStatus(raw) {
|
|
858
|
-
if (raw === "pending" || raw === "success" || raw === "failed") return raw;
|
|
859
|
-
throw new CliError(
|
|
860
|
-
"invalid_input",
|
|
861
|
-
`--status must be 'pending', 'success', or 'failed' (got '${raw}')`
|
|
862
|
-
);
|
|
863
|
-
}
|
|
864
|
-
function parseScheduledChargeType(raw) {
|
|
865
|
-
if (raw === "one_time" || raw === "recurring") return raw;
|
|
866
|
-
throw new CliError("invalid_input", `--type must be 'one_time' or 'recurring' (got '${raw}')`);
|
|
867
|
-
}
|
|
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
|
-
}
|
|
877
|
-
function parseScheduledPaymentMethods(raw) {
|
|
878
|
-
const parts = parseCsvList(raw);
|
|
879
|
-
if (parts.length === 0) {
|
|
880
|
-
throw new CliError(
|
|
881
|
-
"invalid_input",
|
|
882
|
-
`--methods must list at least one of: ${SCHEDULED_PAYMENT_METHODS.join(", ")}`
|
|
883
|
-
);
|
|
884
|
-
}
|
|
885
|
-
for (const p of parts) {
|
|
886
|
-
if (!SCHEDULED_PAYMENT_METHODS.includes(p)) {
|
|
887
|
-
throw new CliError(
|
|
888
|
-
"invalid_input",
|
|
889
|
-
`--methods entries must be one of ${SCHEDULED_PAYMENT_METHODS.join(", ")} (got '${p}')`
|
|
890
|
-
);
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
return parts;
|
|
894
|
-
}
|
|
895
|
-
var RECURRENCE_INTERVALS = [
|
|
896
|
-
"weekly",
|
|
897
|
-
"biweekly",
|
|
898
|
-
"monthly",
|
|
899
|
-
"bimonthly",
|
|
900
|
-
"quarterly",
|
|
901
|
-
"biannual",
|
|
902
|
-
"yearly"
|
|
903
|
-
];
|
|
904
|
-
function parseRecurrenceInterval(raw) {
|
|
905
|
-
if (RECURRENCE_INTERVALS.includes(raw)) return raw;
|
|
906
|
-
throw new CliError(
|
|
907
|
-
"invalid_input",
|
|
908
|
-
`--recurrence-interval must be one of ${RECURRENCE_INTERVALS.join(", ")} (got '${raw}')`
|
|
909
|
-
);
|
|
910
|
-
}
|
|
911
|
-
var SCHEDULED_CHARGE_STATUSES = [
|
|
912
|
-
"scheduled",
|
|
913
|
-
"due_today",
|
|
914
|
-
"overdue",
|
|
915
|
-
"paid",
|
|
916
|
-
"paused",
|
|
917
|
-
"canceled",
|
|
918
|
-
"trial",
|
|
919
|
-
"pending_tokenization",
|
|
920
|
-
"recurrence_canceled"
|
|
921
|
-
];
|
|
922
|
-
function parseScheduledChargeStatus(raw) {
|
|
923
|
-
if (SCHEDULED_CHARGE_STATUSES.includes(raw)) return raw;
|
|
924
|
-
throw new CliError(
|
|
925
|
-
"invalid_input",
|
|
926
|
-
`--status must be one of ${SCHEDULED_CHARGE_STATUSES.join(", ")} (got '${raw}')`
|
|
927
|
-
);
|
|
928
|
-
}
|
|
929
|
-
function parseIntInRange(raw, label, min, max) {
|
|
930
|
-
const trimmed = raw.trim();
|
|
931
|
-
const n = Number.parseInt(trimmed, 10);
|
|
932
|
-
if (!Number.isFinite(n) || String(n) !== trimmed || n < min || n > max) {
|
|
933
|
-
throw new CliError(
|
|
934
|
-
"invalid_input",
|
|
935
|
-
`${label} must be an integer between ${min} and ${max} (got '${raw}')`
|
|
936
|
-
);
|
|
937
|
-
}
|
|
938
|
-
return n;
|
|
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
|
-
}
|
|
951
|
-
function parseAmountBrl(raw) {
|
|
952
|
-
const n = Number(raw);
|
|
953
|
-
if (!Number.isFinite(n) || n <= 0) {
|
|
954
|
-
throw new CliError(
|
|
955
|
-
"invalid_input",
|
|
956
|
-
`--amount must be a positive decimal in BRL, e.g. 297.50 (got '${raw}')`
|
|
957
|
-
);
|
|
958
|
-
}
|
|
959
|
-
return n;
|
|
960
|
-
}
|
|
961
|
-
function parseMetadata(raw) {
|
|
962
|
-
let parsed;
|
|
963
|
-
try {
|
|
964
|
-
parsed = JSON.parse(raw);
|
|
965
|
-
} catch {
|
|
966
|
-
throw new CliError("invalid_input", `--metadata must be valid JSON (got '${raw}')`);
|
|
967
|
-
}
|
|
968
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
969
|
-
throw new CliError("invalid_input", `--metadata must be a JSON object`);
|
|
970
|
-
}
|
|
971
|
-
return parsed;
|
|
972
|
-
}
|
|
973
|
-
|
|
974
1348
|
// src/index.ts
|
|
975
1349
|
function buildCli() {
|
|
976
1350
|
const program = new commander.Command();
|
|
@@ -1021,16 +1395,19 @@ Recipes:
|
|
|
1021
1395
|
);
|
|
1022
1396
|
});
|
|
1023
1397
|
const charges = program.command("charges").description("Create, fetch, and refund charges");
|
|
1024
|
-
charges.command("list").description("List charges with pagination and filters").option("--page <n>", "page number (1-based)", (v) => parseInt(v, 10)).option("--limit <n>", "items per page (1-100)", (v) => parseInt(v, 10)).option(
|
|
1398
|
+
charges.command("list").description("List charges with pagination and filters").option("--page <n>", "page number (1-based)", (v) => parseInt(v, 10)).option("--limit <n>", "items per page (1-100)", (v) => parseInt(v, 10)).option(
|
|
1399
|
+
"--status <status>",
|
|
1400
|
+
"filter by status: pending, authorized, paid, failed, expired, canceled, refund_pending, refunded, chargeback"
|
|
1401
|
+
).option("--search <query>", "search by customer name, email, or document").option("--payment-method <method>", "filter: pix, credit_card, boleto").action(
|
|
1025
1402
|
async (cmdOpts) => {
|
|
1026
1403
|
const base = toCommandOptions(program);
|
|
1027
1404
|
await chargesListCommand({
|
|
1028
1405
|
...base,
|
|
1029
1406
|
page: cmdOpts.page,
|
|
1030
1407
|
limit: cmdOpts.limit,
|
|
1031
|
-
status: cmdOpts.status,
|
|
1408
|
+
status: cmdOpts.status ? parseChargeStatus(cmdOpts.status) : void 0,
|
|
1032
1409
|
search: cmdOpts.search,
|
|
1033
|
-
paymentMethod: cmdOpts.paymentMethod
|
|
1410
|
+
paymentMethod: cmdOpts.paymentMethod ? parseChargePaymentMethodFilter(cmdOpts.paymentMethod) : void 0
|
|
1034
1411
|
}).catch((err) => printErrorAndExit(err, base));
|
|
1035
1412
|
}
|
|
1036
1413
|
);
|
|
@@ -1056,20 +1433,21 @@ Recipes:
|
|
|
1056
1433
|
idempotencyKey: cmdOpts.idempotencyKey
|
|
1057
1434
|
}).catch((err) => printErrorAndExit(err, base));
|
|
1058
1435
|
});
|
|
1059
|
-
charges.command("get <id>").description("Fetch a single charge by
|
|
1436
|
+
charges.command("get <id>").description("Fetch a single charge by its uuid").action(async (id) => {
|
|
1060
1437
|
const base = toCommandOptions(program);
|
|
1061
|
-
await chargesGetCommand({ ...base, id
|
|
1062
|
-
(err) => printErrorAndExit(err, base)
|
|
1063
|
-
);
|
|
1438
|
+
await chargesGetCommand({ ...base, id }).catch((err) => printErrorAndExit(err, base));
|
|
1064
1439
|
});
|
|
1065
|
-
charges.command("refund <id>").description("Refund a charge (full or partial)").option(
|
|
1440
|
+
charges.command("refund <id>").description("Refund a charge by its uuid (full or partial)").option(
|
|
1441
|
+
"--amount <reais>",
|
|
1442
|
+
"partial refund amount in decimal BRL, e.g. 10.00",
|
|
1443
|
+
(v) => parseNonNegativeBrl(v, "--amount")
|
|
1444
|
+
).option("--reason <text>", "optional refund reason").action(async (id, cmdOpts) => {
|
|
1066
1445
|
const base = toCommandOptions(program);
|
|
1067
1446
|
await chargesRefundCommand({
|
|
1068
1447
|
...base,
|
|
1069
|
-
id
|
|
1448
|
+
id,
|
|
1070
1449
|
amount: cmdOpts.amount,
|
|
1071
|
-
reason: cmdOpts.reason
|
|
1072
|
-
idempotencyKey: cmdOpts.idempotencyKey
|
|
1450
|
+
reason: cmdOpts.reason
|
|
1073
1451
|
}).catch((err) => printErrorAndExit(err, base));
|
|
1074
1452
|
});
|
|
1075
1453
|
const scheduled = program.command("scheduled-charges").description("Schedule, inspect, and act on future-dated charges");
|
|
@@ -1286,6 +1664,221 @@ Recipes:
|
|
|
1286
1664
|
id: parsePositiveIntId(id, "Webhook event ID")
|
|
1287
1665
|
}).catch((err) => printErrorAndExit(err, base));
|
|
1288
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
|
+
});
|
|
1744
|
+
const installmentPlans = program.command("installment-plans").description("Sell a product as boleto parcelado (carn\xEA) and manage its installments");
|
|
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(
|
|
1746
|
+
"--customer-id <n>",
|
|
1747
|
+
"customer id",
|
|
1748
|
+
(v) => parsePositiveIntId(v, "--customer-id")
|
|
1749
|
+
).requiredOption(
|
|
1750
|
+
"--installments <n>",
|
|
1751
|
+
"2-12 installments",
|
|
1752
|
+
(v) => parseIntInRange(v, "--installments", 2, 12)
|
|
1753
|
+
).option("--first-due-date <yyyy-mm-dd>", "first installment due date (default: today)").option(
|
|
1754
|
+
"--affiliate-id <n>",
|
|
1755
|
+
"attribute the sale to this affiliate (fixed for the whole plan)",
|
|
1756
|
+
(v) => parsePositiveIntId(v, "--affiliate-id")
|
|
1757
|
+
).option("--idempotency-key <key>", "idempotency key (auto-generated if omitted)").action(async (cmdOpts) => {
|
|
1758
|
+
const base = toCommandOptions(program);
|
|
1759
|
+
await installmentPlansCreateCommand({
|
|
1760
|
+
...base,
|
|
1761
|
+
productId: cmdOpts.productId,
|
|
1762
|
+
customerId: cmdOpts.customerId,
|
|
1763
|
+
installments: cmdOpts.installments,
|
|
1764
|
+
firstDueDate: cmdOpts.firstDueDate,
|
|
1765
|
+
affiliateId: cmdOpts.affiliateId,
|
|
1766
|
+
idempotencyKey: cmdOpts.idempotencyKey
|
|
1767
|
+
}).catch((err) => printErrorAndExit(err, base));
|
|
1768
|
+
});
|
|
1769
|
+
installmentPlans.command("list").description("List installment plans (carn\xEAs) with pagination and filters").option("--page <n>", "page number (1-based)", (v) => parseInt(v, 10)).option("--limit <n>", "items per page (1-100)", (v) => parseInt(v, 10)).option(
|
|
1770
|
+
"--customer-id <n>",
|
|
1771
|
+
"filter by customer id",
|
|
1772
|
+
(v) => parsePositiveIntId(v, "--customer-id")
|
|
1773
|
+
).option("--product-id <uuid>", "filter by product uuid").option(
|
|
1774
|
+
"--status <status>",
|
|
1775
|
+
"filter by status (repeatable)",
|
|
1776
|
+
(val, acc) => acc.concat(val),
|
|
1777
|
+
[]
|
|
1778
|
+
).option("--due-from <yyyy-mm-dd>", "lower bound for the first installment due date").option("--due-to <yyyy-mm-dd>", "upper bound for the first installment due date").action(
|
|
1779
|
+
async (cmdOpts) => {
|
|
1780
|
+
const base = toCommandOptions(program);
|
|
1781
|
+
await installmentPlansListCommand({
|
|
1782
|
+
...base,
|
|
1783
|
+
page: cmdOpts.page,
|
|
1784
|
+
limit: cmdOpts.limit,
|
|
1785
|
+
customerId: cmdOpts.customerId,
|
|
1786
|
+
productId: cmdOpts.productId,
|
|
1787
|
+
status: cmdOpts.status.length > 0 ? cmdOpts.status.map(parseInstallmentPlanStatus) : void 0,
|
|
1788
|
+
dueFrom: cmdOpts.dueFrom,
|
|
1789
|
+
dueTo: cmdOpts.dueTo
|
|
1790
|
+
}).catch((err) => printErrorAndExit(err, base));
|
|
1791
|
+
}
|
|
1792
|
+
);
|
|
1793
|
+
installmentPlans.command("get <uuid>").description("Fetch a carn\xEA with every installment: due date, status, barcode and PDF").action(async (uuid) => {
|
|
1794
|
+
const base = toCommandOptions(program);
|
|
1795
|
+
await installmentPlansGetCommand({ ...base, uuid }).catch(
|
|
1796
|
+
(err) => printErrorAndExit(err, base)
|
|
1797
|
+
);
|
|
1798
|
+
});
|
|
1799
|
+
installmentPlans.command("reissue <uuid> <number>").description("Issue a segunda via for one installment once its slip has expired").action(async (uuid, number) => {
|
|
1800
|
+
const base = toCommandOptions(program);
|
|
1801
|
+
await installmentPlansReissueCommand({
|
|
1802
|
+
...base,
|
|
1803
|
+
uuid,
|
|
1804
|
+
number: parsePositiveIntId(number, "installment number")
|
|
1805
|
+
}).catch((err) => printErrorAndExit(err, base));
|
|
1806
|
+
});
|
|
1807
|
+
installmentPlans.command("postpone <uuid> <number>").description("Move one installment to a later due date (its siblings keep theirs)").requiredOption("--new-due-date <yyyy-mm-dd>", "new due date for this installment").action(async (uuid, number, cmdOpts) => {
|
|
1808
|
+
const base = toCommandOptions(program);
|
|
1809
|
+
await installmentPlansPostponeCommand({
|
|
1810
|
+
...base,
|
|
1811
|
+
uuid,
|
|
1812
|
+
number: parsePositiveIntId(number, "installment number"),
|
|
1813
|
+
newDueDate: cmdOpts.newDueDate
|
|
1814
|
+
}).catch((err) => printErrorAndExit(err, base));
|
|
1815
|
+
});
|
|
1816
|
+
installmentPlans.command("mark-paid <uuid> <number>").description("Record an installment as paid when the buyer paid but the webhook never arrived").action(async (uuid, number) => {
|
|
1817
|
+
const base = toCommandOptions(program);
|
|
1818
|
+
await installmentPlansMarkPaidCommand({
|
|
1819
|
+
...base,
|
|
1820
|
+
uuid,
|
|
1821
|
+
number: parsePositiveIntId(number, "installment number")
|
|
1822
|
+
}).catch((err) => printErrorAndExit(err, base));
|
|
1823
|
+
});
|
|
1824
|
+
installmentPlans.command("cancel <uuid>").description("Cancel a carn\xEA \u2014 stops emission/reminders and cancels open provider slips").option("--note <text>", "optional note recorded on the plan").action(async (uuid, cmdOpts) => {
|
|
1825
|
+
const base = toCommandOptions(program);
|
|
1826
|
+
await installmentPlansCancelCommand({ ...base, uuid, note: cmdOpts.note }).catch(
|
|
1827
|
+
(err) => printErrorAndExit(err, base)
|
|
1828
|
+
);
|
|
1829
|
+
});
|
|
1830
|
+
installmentPlans.command("request-refund <uuid>").description(
|
|
1831
|
+
"Ask for a carn\xEA to be refunded (Garu records the request; transfer the money yourself, then confirm with `garu refund-requests confirm`)"
|
|
1832
|
+
).option(
|
|
1833
|
+
"--amount <reais>",
|
|
1834
|
+
"defaults to everything the carn\xEA has collected",
|
|
1835
|
+
(v) => parseNonNegativeBrl(v, "--amount")
|
|
1836
|
+
).option("--reason <text>", "optional reason").action(async (uuid, cmdOpts) => {
|
|
1837
|
+
const base = toCommandOptions(program);
|
|
1838
|
+
await installmentPlansRequestRefundCommand({
|
|
1839
|
+
...base,
|
|
1840
|
+
uuid,
|
|
1841
|
+
amount: cmdOpts.amount,
|
|
1842
|
+
reason: cmdOpts.reason
|
|
1843
|
+
}).catch((err) => printErrorAndExit(err, base));
|
|
1844
|
+
});
|
|
1845
|
+
const refundRequests = program.command("refund-requests").description("Inspect and resolve refund requests (carn\xEA and Pix/boleto)");
|
|
1846
|
+
refundRequests.command("list").description("List refund requests with pagination and filters").option("--page <n>", "page number (1-based)", (v) => parseInt(v, 10)).option("--limit <n>", "items per page (1-100)", (v) => parseInt(v, 10)).option("--plan-id <uuid>", "filter by carn\xEA uuid").option("--charge-id <uuid>", "filter by charge uuid (Pix/boleto)").option(
|
|
1847
|
+
"--status <status>",
|
|
1848
|
+
"filter by status (repeatable): pending, confirmed, rejected",
|
|
1849
|
+
(val, acc) => acc.concat(val),
|
|
1850
|
+
[]
|
|
1851
|
+
).action(
|
|
1852
|
+
async (cmdOpts) => {
|
|
1853
|
+
const base = toCommandOptions(program);
|
|
1854
|
+
await refundRequestsListCommand({
|
|
1855
|
+
...base,
|
|
1856
|
+
page: cmdOpts.page,
|
|
1857
|
+
limit: cmdOpts.limit,
|
|
1858
|
+
planId: cmdOpts.planId,
|
|
1859
|
+
chargeId: cmdOpts.chargeId,
|
|
1860
|
+
status: cmdOpts.status.length > 0 ? cmdOpts.status.map(parseRefundRequestStatus) : void 0
|
|
1861
|
+
}).catch((err) => printErrorAndExit(err, base));
|
|
1862
|
+
}
|
|
1863
|
+
);
|
|
1864
|
+
refundRequests.command("get <uuid>").description("Fetch a single refund request").action(async (uuid) => {
|
|
1865
|
+
const base = toCommandOptions(program);
|
|
1866
|
+
await refundRequestsGetCommand({ ...base, uuid }).catch(
|
|
1867
|
+
(err) => printErrorAndExit(err, base)
|
|
1868
|
+
);
|
|
1869
|
+
});
|
|
1870
|
+
refundRequests.command("confirm <uuid>").description("Record that you transferred the money back \u2014 call this AFTER the transfer").option("--note <text>", "optional note, e.g. a bank reference").action(async (uuid, cmdOpts) => {
|
|
1871
|
+
const base = toCommandOptions(program);
|
|
1872
|
+
await refundRequestsConfirmCommand({ ...base, uuid, note: cmdOpts.note }).catch(
|
|
1873
|
+
(err) => printErrorAndExit(err, base)
|
|
1874
|
+
);
|
|
1875
|
+
});
|
|
1876
|
+
refundRequests.command("reject <uuid>").description("Decline the request \u2014 the carn\xEA or charge is left untouched").option("--note <text>", "optional note explaining the rejection").action(async (uuid, cmdOpts) => {
|
|
1877
|
+
const base = toCommandOptions(program);
|
|
1878
|
+
await refundRequestsRejectCommand({ ...base, uuid, note: cmdOpts.note }).catch(
|
|
1879
|
+
(err) => printErrorAndExit(err, base)
|
|
1880
|
+
);
|
|
1881
|
+
});
|
|
1289
1882
|
const products = program.command("products").description("Create and update products");
|
|
1290
1883
|
products.command("create").description("Create a product").requiredOption("--name <name>", "product name").option(
|
|
1291
1884
|
"--value <reais>",
|