@garuhq/node 0.15.0 → 1.0.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 +101 -0
- package/README.md +15 -14
- package/dist/index.cjs +87 -95
- package/dist/index.d.cts +187 -100
- package/dist/index.d.ts +187 -100
- package/dist/index.js +87 -95
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -186,11 +186,6 @@ function generateIdempotencyKey() {
|
|
|
186
186
|
return randomUUID();
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
// src/types.ts
|
|
190
|
-
function toWirePaymentMethod(pm) {
|
|
191
|
-
return pm === "credit_card" ? "creditcard" : pm;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
189
|
// src/resources/charges.ts
|
|
195
190
|
var Charges = class {
|
|
196
191
|
constructor(http) {
|
|
@@ -198,16 +193,16 @@ var Charges = class {
|
|
|
198
193
|
}
|
|
199
194
|
http;
|
|
200
195
|
/**
|
|
201
|
-
* Create a charge (PIX,
|
|
196
|
+
* Create a charge (PIX, boleto, or credit card).
|
|
202
197
|
*
|
|
203
|
-
*
|
|
204
|
-
* `idempotencyKey`, the SDK generates a UUIDv4. Safe to retry: the
|
|
205
|
-
*
|
|
198
|
+
* Attaches an `X-Idempotency-Key` header automatically — if you don't pass
|
|
199
|
+
* `idempotencyKey`, the SDK generates a UUIDv4. Safe to retry: the same key
|
|
200
|
+
* returns the original charge for 24h.
|
|
206
201
|
*
|
|
207
202
|
* @example
|
|
208
|
-
* // PIX charge
|
|
203
|
+
* // PIX — render charge.pix.code as a QR in your own checkout
|
|
209
204
|
* const charge = await garu.charges.create({
|
|
210
|
-
* productId: '
|
|
205
|
+
* productId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
|
211
206
|
* paymentMethod: 'pix',
|
|
212
207
|
* customer: {
|
|
213
208
|
* name: 'Maria Silva',
|
|
@@ -216,111 +211,109 @@ var Charges = class {
|
|
|
216
211
|
* phone: '11987654321'
|
|
217
212
|
* }
|
|
218
213
|
* });
|
|
219
|
-
*
|
|
214
|
+
* console.log(charge.uuid, charge.pix?.code);
|
|
220
215
|
*
|
|
221
216
|
* @example
|
|
222
|
-
* // Credit card
|
|
217
|
+
* // Credit card, 2 installments. Server-to-server only (PCI scope).
|
|
223
218
|
* const charge = await garu.charges.create({
|
|
224
|
-
* productId: '
|
|
225
|
-
* paymentMethod: '
|
|
219
|
+
* productId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
|
220
|
+
* paymentMethod: 'creditCard',
|
|
226
221
|
* customer: { name: 'Maria Silva', email: 'maria@exemplo.com.br', document: '12345678909', phone: '11987654321' },
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
* cvv: '123',
|
|
230
|
-
* expirationDate: '2030-12',
|
|
222
|
+
* card: {
|
|
223
|
+
* number: '4111111111111111',
|
|
231
224
|
* holderName: 'MARIA SILVA',
|
|
232
|
-
*
|
|
225
|
+
* expirationDate: '2030-12',
|
|
226
|
+
* cvv: '123',
|
|
227
|
+
* installments: 2
|
|
233
228
|
* }
|
|
234
229
|
* });
|
|
230
|
+
* // charge.amount is the base price; charge.chargedTotal is what was charged.
|
|
235
231
|
*/
|
|
236
232
|
async create(params) {
|
|
237
233
|
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
238
|
-
const body =
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
);
|
|
234
|
+
const body = {
|
|
235
|
+
productId: params.productId,
|
|
236
|
+
paymentMethod: params.paymentMethod,
|
|
237
|
+
customer: params.customer
|
|
238
|
+
};
|
|
239
|
+
if (params.card) body.card = params.card;
|
|
240
|
+
if (params.checkoutSessionToken) body.checkoutSessionToken = params.checkoutSessionToken;
|
|
241
|
+
if (params.additionalInfo !== void 0) body.additionalInfo = params.additionalInfo;
|
|
242
|
+
return this.post("/api/v1/charges", body, { "X-Idempotency-Key": idempotencyKey });
|
|
246
243
|
}
|
|
247
244
|
/**
|
|
248
|
-
*
|
|
245
|
+
* Retrieve a charge by uuid.
|
|
249
246
|
*
|
|
250
247
|
* @example
|
|
251
|
-
* const
|
|
252
|
-
*
|
|
248
|
+
* const charge = await garu.charges.retrieve('6f1c9b2e-4a7d-4f0b-9a3e-1d2c3b4a5e6f');
|
|
249
|
+
* if (charge.status === 'paid') fulfil(charge);
|
|
250
|
+
*/
|
|
251
|
+
async retrieve(uuid) {
|
|
252
|
+
return this.get(`/api/v1/charges/${encodeURIComponent(uuid)}`);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* List charges for the authenticated account, newest first by default.
|
|
256
|
+
*
|
|
257
|
+
* @example
|
|
258
|
+
* const { data, totalCount } = await garu.charges.list({ status: 'paid', limit: 50 });
|
|
259
|
+
* console.log(`${data.length} of ${totalCount} paid charges`);
|
|
253
260
|
*/
|
|
254
261
|
async list(params = {}) {
|
|
255
262
|
const query = {};
|
|
256
263
|
if (params.page !== void 0) query.page = String(params.page);
|
|
257
264
|
if (params.limit !== void 0) query.limit = String(params.limit);
|
|
258
265
|
if (params.status) query.status = params.status;
|
|
259
|
-
if (params.search) query.search = params.search;
|
|
260
266
|
if (params.paymentMethod) query.paymentMethod = params.paymentMethod;
|
|
267
|
+
if (params.productId) query.productId = params.productId;
|
|
268
|
+
if (params.createdAfter) query.createdAfter = params.createdAfter;
|
|
269
|
+
if (params.createdBefore) query.createdBefore = params.createdBefore;
|
|
270
|
+
if (params.search) query.search = params.search;
|
|
271
|
+
if (params.sort) query.sort = params.sort;
|
|
261
272
|
const qs = new URLSearchParams(query).toString();
|
|
262
|
-
|
|
263
|
-
return this.http.call(
|
|
264
|
-
(signal) => this.http.client.GET(url, { signal }).then(
|
|
265
|
-
(r) => r
|
|
266
|
-
)
|
|
267
|
-
);
|
|
273
|
+
return this.get(`/api/v1/charges${qs ? `?${qs}` : ""}`);
|
|
268
274
|
}
|
|
269
275
|
/**
|
|
270
|
-
*
|
|
276
|
+
* Refund a charge, fully or partially. `amount` is in reais.
|
|
277
|
+
*
|
|
278
|
+
* For a Pix Automático charge the refund is a devolução: it returns with the
|
|
279
|
+
* charge in `refund_pending`, reaching `refunded` only once the transfer
|
|
280
|
+
* settles.
|
|
271
281
|
*
|
|
272
282
|
* @example
|
|
273
|
-
*
|
|
274
|
-
*
|
|
283
|
+
* await garu.charges.refund('6f1c9b2e-...'); // full
|
|
284
|
+
* await garu.charges.refund('6f1c9b2e-...', { amount: 10.0 }); // R$10,00
|
|
275
285
|
*/
|
|
276
|
-
async
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
})
|
|
282
|
-
);
|
|
286
|
+
async refund(uuid, params = {}) {
|
|
287
|
+
const body = {};
|
|
288
|
+
if (params.amount !== void 0) body.amount = params.amount;
|
|
289
|
+
if (params.reason !== void 0) body.reason = params.reason;
|
|
290
|
+
return this.post(`/api/v1/charges/${encodeURIComponent(uuid)}/refund`, body);
|
|
283
291
|
}
|
|
284
292
|
/**
|
|
285
|
-
*
|
|
293
|
+
* Cancel an unpaid charge.
|
|
286
294
|
*
|
|
287
295
|
* @example
|
|
288
|
-
*
|
|
289
|
-
* await garu.charges.refund(4472);
|
|
290
|
-
*
|
|
291
|
-
* @example
|
|
292
|
-
* // Partial refund of R$ 10,00
|
|
293
|
-
* await garu.charges.refund(4472, { amount: 1000, reason: 'customer_request' });
|
|
296
|
+
* const { canceled } = await garu.charges.cancel('6f1c9b2e-...');
|
|
294
297
|
*/
|
|
295
|
-
async
|
|
296
|
-
const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
|
|
297
|
-
const body = {};
|
|
298
|
-
if (params.amount !== void 0) body.amount = params.amount;
|
|
299
|
-
if (params.reason !== void 0) body.reason = params.reason;
|
|
298
|
+
async cancel(uuid) {
|
|
300
299
|
return this.http.call(
|
|
301
|
-
(signal) => this.http.client.
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
signal
|
|
306
|
-
})
|
|
300
|
+
(signal) => this.http.client.DELETE(
|
|
301
|
+
`/api/v1/charges/${encodeURIComponent(uuid)}`,
|
|
302
|
+
{ signal }
|
|
303
|
+
)
|
|
307
304
|
);
|
|
308
305
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
body.checkoutSessionToken = params.checkoutSessionToken;
|
|
321
|
-
}
|
|
322
|
-
if (params.cardInfo) body.CardInfo = params.cardInfo;
|
|
323
|
-
return body;
|
|
306
|
+
// v1 charge routes are not in the generated OpenAPI schema (it is regenerated
|
|
307
|
+
// from a live deploy), so these use the client's untyped path.
|
|
308
|
+
get(url) {
|
|
309
|
+
return this.http.call(
|
|
310
|
+
(signal) => this.http.client.GET(url, { signal })
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
post(url, body, headers) {
|
|
314
|
+
return this.http.call(
|
|
315
|
+
(signal) => this.http.client.POST(url, { body, headers, signal })
|
|
316
|
+
);
|
|
324
317
|
}
|
|
325
318
|
};
|
|
326
319
|
|
|
@@ -475,7 +468,7 @@ var ProductPortalConfigResource = class {
|
|
|
475
468
|
async get(productId) {
|
|
476
469
|
return this.http.call(
|
|
477
470
|
(signal) => this.http.client.GET(
|
|
478
|
-
`/api/products/${encodeURIComponent(String(productId))}/portal-config`,
|
|
471
|
+
`/api/v1/products/${encodeURIComponent(String(productId))}/portal-config`,
|
|
479
472
|
{
|
|
480
473
|
signal
|
|
481
474
|
}
|
|
@@ -498,7 +491,7 @@ var ProductPortalConfigResource = class {
|
|
|
498
491
|
async set(productId, params) {
|
|
499
492
|
return this.http.call(
|
|
500
493
|
(signal) => this.http.client.POST(
|
|
501
|
-
`/api/products/${encodeURIComponent(String(productId))}/portal-config`,
|
|
494
|
+
`/api/v1/products/${encodeURIComponent(String(productId))}/portal-config`,
|
|
502
495
|
{
|
|
503
496
|
body: params,
|
|
504
497
|
signal
|
|
@@ -510,7 +503,7 @@ var ProductPortalConfigResource = class {
|
|
|
510
503
|
async patch(productId, params) {
|
|
511
504
|
return this.http.call(
|
|
512
505
|
(signal) => this.http.client.PATCH(
|
|
513
|
-
`/api/products/${encodeURIComponent(String(productId))}/portal-config`,
|
|
506
|
+
`/api/v1/products/${encodeURIComponent(String(productId))}/portal-config`,
|
|
514
507
|
{
|
|
515
508
|
body: params,
|
|
516
509
|
signal
|
|
@@ -529,7 +522,7 @@ var ProductPortalConfigResource = class {
|
|
|
529
522
|
async clear(productId) {
|
|
530
523
|
return this.http.call(
|
|
531
524
|
(signal) => this.http.client.DELETE(
|
|
532
|
-
`/api/products/${encodeURIComponent(String(productId))}/portal-config`,
|
|
525
|
+
`/api/v1/products/${encodeURIComponent(String(productId))}/portal-config`,
|
|
533
526
|
{
|
|
534
527
|
body: {},
|
|
535
528
|
signal
|
|
@@ -550,16 +543,15 @@ var Products = class {
|
|
|
550
543
|
* List products for the authenticated seller, with pagination and search.
|
|
551
544
|
*
|
|
552
545
|
* @example
|
|
553
|
-
* const { data,
|
|
546
|
+
* const { data, totalCount } = await garu.products.list({ search: 'curso', limit: 10 });
|
|
554
547
|
*/
|
|
555
548
|
async list(params = {}) {
|
|
556
549
|
const query = {};
|
|
557
550
|
if (params.page !== void 0) query.page = String(params.page);
|
|
558
551
|
if (params.limit !== void 0) query.limit = String(params.limit);
|
|
559
552
|
if (params.search) query.search = params.search;
|
|
560
|
-
if (params.tab) query.tab = params.tab;
|
|
561
553
|
const qs = new URLSearchParams(query).toString();
|
|
562
|
-
const url = `/api/products
|
|
554
|
+
const url = `/api/v1/products${qs ? `?${qs}` : ""}`;
|
|
563
555
|
return this.http.call(
|
|
564
556
|
(signal) => this.http.client.GET(url, { signal }).then(
|
|
565
557
|
(r) => r
|
|
@@ -575,7 +567,7 @@ var Products = class {
|
|
|
575
567
|
*/
|
|
576
568
|
async get(uuid) {
|
|
577
569
|
return this.http.call(
|
|
578
|
-
(signal) => this.http.client.GET(`/api/products
|
|
570
|
+
(signal) => this.http.client.GET(`/api/v1/products/${uuid}`, { signal }).then(
|
|
579
571
|
(r) => r
|
|
580
572
|
)
|
|
581
573
|
);
|
|
@@ -593,7 +585,7 @@ var Products = class {
|
|
|
593
585
|
* @example
|
|
594
586
|
* const product = await garu.products.create({
|
|
595
587
|
* name: 'Plano Mensal',
|
|
596
|
-
* value:
|
|
588
|
+
* value: 49.90, // R$ 49,90 in reais (decimal BRL), NOT centavos
|
|
597
589
|
* description: 'Acesso completo à plataforma',
|
|
598
590
|
* pix: true,
|
|
599
591
|
* creditCard: true,
|
|
@@ -606,7 +598,7 @@ var Products = class {
|
|
|
606
598
|
const { idempotencyKey, ...body } = params;
|
|
607
599
|
const key = idempotencyKey ?? generateIdempotencyKey();
|
|
608
600
|
return this.http.call(
|
|
609
|
-
(signal) => this.http.client.POST("/api/products", {
|
|
601
|
+
(signal) => this.http.client.POST("/api/v1/products", {
|
|
610
602
|
body,
|
|
611
603
|
headers: { "X-Idempotency-Key": key },
|
|
612
604
|
signal
|
|
@@ -617,19 +609,19 @@ var Products = class {
|
|
|
617
609
|
* Update a product (partial PATCH — only the fields you pass are changed).
|
|
618
610
|
* Returns the updated product.
|
|
619
611
|
*
|
|
620
|
-
* `id` accepts the
|
|
621
|
-
*
|
|
612
|
+
* `id` accepts the product UUID (recommended) or the legacy numeric id —
|
|
613
|
+
* both resolve on the `/api/v1/products/:id` path (see
|
|
622
614
|
* {@link ProductPortalConfigResource}).
|
|
623
615
|
*
|
|
624
616
|
* @example
|
|
625
617
|
* const updated = await garu.products.update('b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f', {
|
|
626
|
-
* value:
|
|
618
|
+
* value: 59.90, // reais (decimal BRL), NOT centavos
|
|
627
619
|
* pixAutomatic: true // turn on Pix Automático for this product
|
|
628
620
|
* });
|
|
629
621
|
*/
|
|
630
622
|
async update(id, params) {
|
|
631
623
|
return this.http.call(
|
|
632
|
-
(signal) => this.http.client.PATCH(`/api/products/${encodeURIComponent(String(id))}`, {
|
|
624
|
+
(signal) => this.http.client.PATCH(`/api/v1/products/${encodeURIComponent(String(id))}`, {
|
|
633
625
|
body: params,
|
|
634
626
|
signal
|
|
635
627
|
}).then((r) => r)
|