@garuhq/node 0.1.1 → 0.2.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/dist/index.cjs +113 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +142 -2
- package/dist/index.d.ts +142 -2
- package/dist/index.js +113 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -222,7 +222,7 @@ var Charges = class {
|
|
|
222
222
|
* phone: '11987654321'
|
|
223
223
|
* }
|
|
224
224
|
* });
|
|
225
|
-
*
|
|
225
|
+
* // charge.id, charge.status
|
|
226
226
|
*
|
|
227
227
|
* @example
|
|
228
228
|
* // Credit card charge, 3 installments
|
|
@@ -250,6 +250,28 @@ var Charges = class {
|
|
|
250
250
|
})
|
|
251
251
|
);
|
|
252
252
|
}
|
|
253
|
+
/**
|
|
254
|
+
* List charges for the authenticated seller, with pagination and filters.
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* const { data, meta } = await garu.charges.list({ status: 'paid', limit: 10 });
|
|
258
|
+
* // meta.total paid charges
|
|
259
|
+
*/
|
|
260
|
+
async list(params = {}) {
|
|
261
|
+
const query = {};
|
|
262
|
+
if (params.page !== void 0) query.page = String(params.page);
|
|
263
|
+
if (params.limit !== void 0) query.limit = String(params.limit);
|
|
264
|
+
if (params.status) query.status = params.status;
|
|
265
|
+
if (params.search) query.search = params.search;
|
|
266
|
+
if (params.paymentMethod) query.paymentMethod = params.paymentMethod;
|
|
267
|
+
const qs = new URLSearchParams(query).toString();
|
|
268
|
+
const url = `/api/transactions${qs ? `?${qs}` : ""}`;
|
|
269
|
+
return this.http.call(
|
|
270
|
+
(signal) => this.http.client.GET(url, { signal }).then(
|
|
271
|
+
(r) => r
|
|
272
|
+
)
|
|
273
|
+
);
|
|
274
|
+
}
|
|
253
275
|
/**
|
|
254
276
|
* Fetch a single charge by numeric ID.
|
|
255
277
|
*
|
|
@@ -308,6 +330,93 @@ var Charges = class {
|
|
|
308
330
|
}
|
|
309
331
|
};
|
|
310
332
|
|
|
333
|
+
// src/resources/customers.ts
|
|
334
|
+
var Customers = class {
|
|
335
|
+
constructor(http) {
|
|
336
|
+
this.http = http;
|
|
337
|
+
}
|
|
338
|
+
http;
|
|
339
|
+
/**
|
|
340
|
+
* Create a customer and link it to the current seller.
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* const customer = await garu.customers.create({
|
|
344
|
+
* name: 'Maria Silva',
|
|
345
|
+
* email: 'maria@exemplo.com.br',
|
|
346
|
+
* document: '12345678909',
|
|
347
|
+
* phone: '11987654321',
|
|
348
|
+
* personType: 'fisica'
|
|
349
|
+
* });
|
|
350
|
+
*/
|
|
351
|
+
async create(params) {
|
|
352
|
+
return this.http.call(
|
|
353
|
+
(signal) => this.http.client.POST("/api/customers", {
|
|
354
|
+
body: params,
|
|
355
|
+
signal
|
|
356
|
+
}).then((r) => r)
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* List customers for the authenticated seller, with pagination and search.
|
|
361
|
+
*
|
|
362
|
+
* @example
|
|
363
|
+
* const { data, meta } = await garu.customers.list({ search: 'maria', limit: 10 });
|
|
364
|
+
*/
|
|
365
|
+
async list(params = {}) {
|
|
366
|
+
const query = {};
|
|
367
|
+
if (params.page !== void 0) query.page = String(params.page);
|
|
368
|
+
if (params.limit !== void 0) query.limit = String(params.limit);
|
|
369
|
+
if (params.search) query.search = params.search;
|
|
370
|
+
const qs = new URLSearchParams(query).toString();
|
|
371
|
+
const url = `/api/customers${qs ? `?${qs}` : ""}`;
|
|
372
|
+
return this.http.call(
|
|
373
|
+
(signal) => this.http.client.GET(url, { signal }).then(
|
|
374
|
+
(r) => r
|
|
375
|
+
)
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Fetch a single customer by numeric ID.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* const customer = await garu.customers.get(42);
|
|
383
|
+
*/
|
|
384
|
+
async get(id) {
|
|
385
|
+
return this.http.call(
|
|
386
|
+
(signal) => this.http.client.GET(`/api/customers/${id}`, { signal }).then(
|
|
387
|
+
(r) => r
|
|
388
|
+
)
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Update a customer's profile for the current seller.
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* const updated = await garu.customers.update(42, { name: 'Maria Santos' });
|
|
396
|
+
*/
|
|
397
|
+
async update(id, params) {
|
|
398
|
+
return this.http.call(
|
|
399
|
+
(signal) => this.http.client.PUT(`/api/customers/${id}`, {
|
|
400
|
+
body: params,
|
|
401
|
+
signal
|
|
402
|
+
}).then((r) => r)
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Remove a customer from the current seller.
|
|
407
|
+
*
|
|
408
|
+
* @example
|
|
409
|
+
* await garu.customers.delete(42);
|
|
410
|
+
*/
|
|
411
|
+
async delete(id) {
|
|
412
|
+
await this.http.call(
|
|
413
|
+
(signal) => this.http.client.DELETE(`/api/customers/${id}`, { signal }).then(
|
|
414
|
+
(r) => r
|
|
415
|
+
)
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
|
|
311
420
|
// src/resources/meta.ts
|
|
312
421
|
var Meta = class {
|
|
313
422
|
constructor(http) {
|
|
@@ -387,9 +496,10 @@ function parseSignatureHeader(header) {
|
|
|
387
496
|
var DEFAULT_BASE_URL = "https://garu.com.br";
|
|
388
497
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
389
498
|
var DEFAULT_MAX_RETRIES = 2;
|
|
390
|
-
var SDK_VERSION = "0.
|
|
499
|
+
var SDK_VERSION = "0.2.0";
|
|
391
500
|
var Garu = class {
|
|
392
501
|
charges;
|
|
502
|
+
customers;
|
|
393
503
|
meta;
|
|
394
504
|
/**
|
|
395
505
|
* Webhook helpers. Available both as an instance member and as a static —
|
|
@@ -407,6 +517,7 @@ var Garu = class {
|
|
|
407
517
|
fetch: options.fetch
|
|
408
518
|
});
|
|
409
519
|
this.charges = new Charges(http);
|
|
520
|
+
this.customers = new Customers(http);
|
|
410
521
|
this.meta = new Meta(http);
|
|
411
522
|
}
|
|
412
523
|
};
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/idempotency.ts","../src/types.ts","../src/resources/charges.ts","../src/resources/meta.ts","../src/webhooks.ts","../src/client.ts"],"names":["createClient","randomUUID","createHmac","timingSafeEqual"],"mappings":";;;;;;;;;;;;AAmBO,IAAM,SAAA,GAAN,cAAwB,KAAA,CAAM;AAAA,EACnB,IAAA;AAAA,EAEhB,WAAA,CAAY,MAAqB,OAAA,EAAiB;AAChD,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,WAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,SAAA,CAAU;AAAA,EACjC,eAAA;AAAA,EAChB,WAAA,CAAY,SAAiB,eAAA,EAA2B;AACtD,IAAA,KAAA,CAAM,oBAAoB,OAAO,CAAA;AACjC,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AACZ,IAAA,IAAA,CAAK,eAAA,GAAkB,eAAA;AAAA,EACzB;AACF;AAEO,IAAM,8BAAA,GAAN,cAA6C,SAAA,CAAU;AAAA,EAC5D,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,iCAAiC,OAAO,CAAA;AAC9C,IAAA,IAAA,CAAK,IAAA,GAAO,gCAAA;AAAA,EACd;AACF;AAEO,IAAM,YAAA,GAAN,cAA2B,SAAA,CAAU;AAAA,EAC1B,MAAA;AAAA,EACA,SAAA;AAAA,EACA,IAAA;AAAA,EAEhB,WAAA,CACE,IAAA,EACA,OAAA,EACA,MAAA,EACA,WACA,IAAA,EACA;AACA,IAAA,KAAA,CAAM,MAAM,OAAO,CAAA;AACnB,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AACF;AAEO,IAAM,uBAAA,GAAN,cAAsC,YAAA,CAAa;AAAA,EACxD,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,SAAA,EAA0B,IAAA,EAAe;AACpF,IAAA,KAAA,CAAM,sBAAA,EAAwB,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAI,CAAA;AAC9D,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EACd;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,YAAA,CAAa;AAAA,EACpD,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,SAAA,EAA0B,IAAA,EAAe;AACpF,IAAA,KAAA,CAAM,kBAAA,EAAoB,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAI,CAAA;AAC1D,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAEO,IAAM,iBAAA,GAAN,cAAgC,YAAA,CAAa;AAAA,EAClD,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,SAAA,EAA0B,IAAA,EAAe;AACpF,IAAA,KAAA,CAAM,WAAA,EAAa,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAI,CAAA;AACnD,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,YAAA,CAAa;AAAA,EACpD,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,SAAA,EAA0B,IAAA,EAAe;AACpF,IAAA,KAAA,CAAM,kBAAA,EAAoB,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAI,CAAA;AAC1D,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAEO,IAAM,kBAAA,GAAN,cAAiC,YAAA,CAAa;AAAA,EACnC,aAAA;AAAA,EAChB,WAAA,CACE,OAAA,EACA,MAAA,EACA,SAAA,EACA,MACA,aAAA,EACA;AACA,IAAA,KAAA,CAAM,cAAA,EAAgB,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAI,CAAA;AACtD,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AACZ,IAAA,IAAA,CAAK,aAAA,GAAgB,aAAA;AAAA,EACvB;AACF;AAEO,IAAM,eAAA,GAAN,cAA8B,YAAA,CAAa;AAAA,EAChD,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,SAAA,EAA0B,IAAA,EAAe;AACpF,IAAA,KAAA,CAAM,cAAA,EAAgB,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAI,CAAA;AACtD,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAKO,SAAS,WAAA,CACd,MAAA,EACA,IAAA,EACA,SAAA,EACA,aAAA,EACc;AACd,EAAA,MAAM,OAAA,GAAU,cAAA,CAAe,IAAI,CAAA,IAAK,0BAA0B,MAAM,CAAA,CAAA;AAExE,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,IAAI,wBAAwB,OAAA,EAAS,MAAA,EAAQ,WAAW,IAAI,CAAA;AACvF,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,IAAI,oBAAoB,OAAA,EAAS,MAAA,EAAQ,WAAW,IAAI,CAAA;AACnF,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,IAAI,kBAAkB,OAAA,EAAS,MAAA,EAAQ,WAAW,IAAI,CAAA;AACjF,EAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,GAAA,EAAK;AACpC,IAAA,OAAO,IAAI,mBAAA,CAAoB,OAAA,EAAS,MAAA,EAAQ,WAAW,IAAI,CAAA;AAAA,EACjE;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,IAAI,kBAAA,CAAmB,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,MAAM,aAAa,CAAA;AAAA,EAC/E;AACA,EAAA,IAAI,MAAA,IAAU,KAAK,OAAO,IAAI,gBAAgB,OAAA,EAAS,MAAA,EAAQ,WAAW,IAAI,CAAA;AAC9E,EAAA,OAAO,IAAI,YAAA,CAAa,WAAA,EAAa,OAAA,EAAS,MAAA,EAAQ,WAAW,IAAI,CAAA;AACvE;AAEA,SAAS,eAAe,IAAA,EAA8B;AACpD,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AACrC,EAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACpC,IAAA,MAAM,IAAK,IAAA,CAA+B,OAAA;AAC1C,IAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,CAAA;AAClC,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,IAAK,EAAE,KAAA,CAAM,CAAC,CAAA,KAAM,OAAO,MAAM,QAAQ,CAAA,EAAG,OAAO,CAAA,CAAE,KAAK,IAAI,CAAA;AAAA,EACnF;AACA,EAAA,OAAO,IAAA;AACT;;;ACpIA,IAAM,kBAAA,mBAAqB,IAAI,GAAA,CAAI,CAAC,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAG,CAAC,CAAA;AAuB1D,IAAM,aAAN,MAAiB;AAAA,EACN,MAAA;AAAA,EACC,GAAA;AAAA,EAEjB,YAAY,GAAA,EAAuB;AACjC,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AACX,IAAA,MAAM,SAAA,GAAY,GAAA,CAAI,KAAA,IAAS,UAAA,CAAW,KAAA;AAC1C,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,mBAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,MAAA,EAAQ,kBAAA;AAAA,MACR,cAAc,GAAA,CAAI;AAAA,KACpB;AACA,IAAA,IAAI,IAAI,MAAA,EAAQ,OAAA,CAAQ,aAAA,GAAgB,CAAA,OAAA,EAAU,IAAI,MAAM,CAAA,CAAA;AAE5D,IAAA,IAAA,CAAK,SAASA,6BAAA,CAAoB;AAAA,MAChC,OAAA,EAAS,GAAA,CAAI,OAAA,CAAQ,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAAA,MACvC,KAAA,EAAO,SAAA;AAAA,MACP;AAAA,KACD,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAQ,EAAA,EAA+D;AAC3E,IAAA,IAAI,SAAA,GAAuD,IAAA;AAE3D,IAAA,KAAA,IAAS,UAAU,CAAA,EAAG,OAAA,IAAW,IAAA,CAAK,GAAA,CAAI,YAAY,OAAA,EAAA,EAAW;AAC/D,MAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,MAAA,MAAM,KAAA,GAAQ,WAAW,MAAM,UAAA,CAAW,OAAM,EAAG,IAAA,CAAK,IAAI,SAAS,CAAA;AAErE,MAAA,IAAI;AACF,QAAA,MAAM,EAAE,MAAM,KAAA,EAAO,QAAA,KAAa,MAAM,EAAA,CAAG,WAAW,MAAM,CAAA;AAC5D,QAAA,YAAA,CAAa,KAAK,CAAA;AAElB,QAAA,IAAI,SAAS,EAAA,EAAI;AACf,UAAA,OAAO,IAAA;AAAA,QACT;AAEA,QAAA,MAAM,SAAA,GAAY,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA;AACrD,QAAA,MAAM,gBAAgB,eAAA,CAAgB,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAC,CAAA;AACzE,QAAA,MAAM,WAAW,WAAA,CAAY,QAAA,CAAS,QAAQ,KAAA,IAAS,IAAA,EAAM,WAAW,aAAa,CAAA;AACrF,QAAA,SAAA,GAAY,QAAA;AAEZ,QAAA,IAAI,CAAC,mBAAmB,GAAA,CAAI,QAAA,CAAS,MAAM,CAAA,IAAK,OAAA,KAAY,IAAA,CAAK,GAAA,CAAI,UAAA,EAAY;AAC/E,UAAA,MAAM,QAAA;AAAA,QACR;AAEA,QAAA,MAAM,KAAA,CAAM,YAAA,CAAa,OAAA,EAAS,aAAa,CAAC,CAAA;AAChD,QAAA;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,YAAA,CAAa,KAAK,CAAA;AAElB,QAAA,IAAI,cAAA,CAAe,GAAG,CAAA,EAAG,MAAM,GAAA;AAE/B,QAAA,MAAM,OAAA,GACJ,eAAe,KAAA,IAAS,GAAA,CAAI,SAAS,YAAA,GACjC,IAAI,mBAAA,CAAoB,CAAA,wBAAA,EAA2B,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA,EAAA,CAAA,EAAM,GAAG,IAC9E,IAAI,mBAAA,CAAoB,eAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,eAAA,EAAiB,GAAG,CAAA;AACvF,QAAA,SAAA,GAAY,OAAA;AAEZ,QAAA,IAAI,OAAA,KAAY,IAAA,CAAK,GAAA,CAAI,UAAA,EAAY,MAAM,OAAA;AAC3C,QAAA,MAAM,KAAA,CAAM,YAAA,CAAa,OAAA,EAAS,IAAI,CAAC,CAAA;AACvC,QAAA;AAAA,MACF;AAAA,IACF;AAGA,IAAA,MAAM,SAAA,IAAa,IAAI,mBAAA,CAAoB,uCAAuC,CAAA;AAAA,EACpF;AACF,CAAA;AAEA,SAAS,eAAe,GAAA,EAAuB;AAC7C,EAAA,OAAO,GAAA,YAAe,KAAA,IAAS,GAAA,CAAI,IAAA,CAAK,UAAA,CAAW,MAAM,CAAA,IAAK,GAAA,CAAI,IAAA,CAAK,QAAA,CAAS,OAAO,CAAA;AACzF;AAEA,SAAS,gBAAgB,KAAA,EAAqC;AAC5D,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,MAAM,CAAA,GAAI,OAAO,KAAK,CAAA;AACtB,EAAA,OAAO,OAAO,QAAA,CAAS,CAAC,CAAA,IAAK,CAAA,IAAK,IAAI,CAAA,GAAI,IAAA;AAC5C;AAMA,SAAS,YAAA,CAAa,SAAiB,aAAA,EAAsC;AAC3E,EAAA,IAAI,kBAAkB,IAAA,EAAM;AAC1B,IAAA,OAAO,aAAA,GAAgB,GAAA,GAAO,IAAA,CAAK,MAAA,EAAO,GAAI,GAAA;AAAA,EAChD;AACA,EAAA,MAAM,IAAA,GAAO,MAAM,CAAA,IAAK,OAAA;AACxB,EAAA,MAAM,GAAA,GAAM,GAAA;AACZ,EAAA,OAAO,KAAK,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA,GAAI,KAAK,MAAA,EAAO;AAC3C;AAEA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD;ACrIO,SAAS,sBAAA,GAAiC;AAC/C,EAAA,OAAOC,iBAAA,EAAW;AACpB;;;AC8HO,SAAS,oBAAoB,EAAA,EAAwC;AAC1E,EAAA,OAAO,EAAA,KAAO,gBAAgB,YAAA,GAAe,EAAA;AAC/C;;;ACvHO,IAAM,UAAN,MAAc;AAAA,EACnB,YAA6B,IAAA,EAAkB;AAAlB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAmB;AAAA,EAAnB,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsC7B,MAAM,OAAO,MAAA,EAA6C;AACxD,IAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,cAAA,IAAkB,sBAAA,EAAuB;AACvE,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,eAAA,CAAgB,MAAM,CAAA;AAExC,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MACf,CAAC,MAAA,KACC,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,KAAK,mBAAA,EAAqB;AAAA,QACzC,IAAA;AAAA,QACA,OAAA,EAAS,EAAE,mBAAA,EAAqB,cAAA,EAAe;AAAA,QAC/C;AAAA,OACD;AAAA,KACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAI,EAAA,EAA6B;AACrC,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MACf,CAAC,MAAA,KACC,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,IAAI,wBAAA,EAA0B;AAAA,QAC7C,MAAA,EAAQ,EAAE,IAAA,EAAM,EAAE,IAAG,EAAE;AAAA,QACvB;AAAA,OACD;AAAA,KACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,MAAA,CAAO,EAAA,EAAY,MAAA,GAA6B,EAAC,EAAoB;AACzE,IAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,cAAA,IAAkB,sBAAA,EAAuB;AACvE,IAAA,MAAM,OAAgC,EAAC;AACvC,IAAA,IAAI,MAAA,CAAO,MAAA,KAAW,MAAA,EAAW,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AACtD,IAAA,IAAI,MAAA,CAAO,MAAA,KAAW,MAAA,EAAW,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AAEtD,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MACf,CAAC,MAAA,KACC,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,KAAK,+BAAA,EAAiC;AAAA,QACrD,MAAA,EAAQ,EAAE,IAAA,EAAM,EAAE,IAAG,EAAE;AAAA,QACvB,IAAA;AAAA,QACA,OAAA,EAAS,EAAE,mBAAA,EAAqB,cAAA,EAAe;AAAA,QAC/C;AAAA,OACD;AAAA,KACL;AAAA,EACF;AAAA,EAEQ,gBAAgB,MAAA,EAAmD;AACzE,IAAA,MAAM,IAAA,GAAgC;AAAA,MACpC,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,WAAW,MAAA,CAAO,SAAA;AAAA,MAClB,eAAA,EAAiB,mBAAA,CAAoB,MAAA,CAAO,aAAa,CAAA;AAAA,MACzD,IAAA,EAAM,OAAO,IAAA,IAAQ,IAAA;AAAA,MACrB,WAAA,EAAa,OAAO,WAAA,IAAe;AAAA,KACrC;AACA,IAAA,IAAI,MAAA,CAAO,cAAA,KAAmB,MAAA,EAAW,IAAA,CAAK,iBAAiB,MAAA,CAAO,cAAA;AACtE,IAAA,IAAI,MAAA,CAAO,OAAA,KAAY,MAAA,EAAW,IAAA,CAAK,UAAU,MAAA,CAAO,OAAA;AACxD,IAAA,IAAI,MAAA,CAAO,yBAAyB,MAAA,EAAW;AAC7C,MAAA,IAAA,CAAK,uBAAuB,MAAA,CAAO,oBAAA;AAAA,IACrC;AACA,IAAA,IAAI,MAAA,CAAO,QAAA,EAAU,IAAA,CAAK,QAAA,GAAW,MAAA,CAAO,QAAA;AAC5C,IAAA,OAAO,IAAA;AAAA,EACT;AACF,CAAA;;;AC5HO,IAAM,OAAN,MAAW;AAAA,EAChB,YAA6B,IAAA,EAAkB;AAAlB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAmB;AAAA,EAAnB,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU7B,MAAM,GAAA,GAA6B;AACjC,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MACf,CAAC,WACC,IAAA,CAAK,IAAA,CAAK,OAAO,GAAA,CAAI,WAAA,EAAa,EAAE,MAAA,EAAQ;AAAA,KAKhD;AAAA,EACF;AACF,CAAA;ACgBO,IAAM,QAAA,GAAW;AAAA,EACtB,OAAO,MAAA,EAA8C;AACnD,IAAA,MAAM,EAAE,SAAA,EAAW,MAAA,EAAQ,OAAA,EAAQ,GAAI,MAAA;AACvC,IAAA,MAAM,YAAA,GAAe,OAAO,YAAA,IAAgB,GAAA;AAC5C,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,GAAA,IAAO,IAAA,CAAK,GAAA;AAE/B,IAAA,IAAI,CAAC,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,EAAU;AAC/C,MAAA,MAAM,IAAI,+BAA+B,8CAA8C,CAAA;AAAA,IACzF;AAEA,IAAA,MAAM,KAAA,GAAQ,qBAAqB,SAAS,CAAA;AAC5C,IAAA,IAAI,UAAU,IAAA,EAAM;AAClB,MAAA,MAAM,IAAI,8BAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,aAAa,OAAO,OAAA,KAAY,WAAW,OAAA,GAAU,OAAA,CAAQ,SAAS,MAAM,CAAA;AAClF,IAAA,MAAM,aAAA,GAAgB,CAAA,EAAG,KAAA,CAAM,SAAS,IAAI,UAAU,CAAA,CAAA;AACtD,IAAA,MAAM,QAAA,GAAWC,kBAAW,QAAA,EAAU,MAAM,EAAE,MAAA,CAAO,aAAa,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA;AAEhF,IAAA,MAAM,WAAA,GAAc,MAAA,CAAO,IAAA,CAAK,QAAA,EAAU,KAAK,CAAA;AAC/C,IAAA,MAAM,WAAA,GAAc,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,IAAI,KAAK,CAAA;AAC/C,IAAA,IAAI,WAAA,CAAY,WAAW,WAAA,CAAY,MAAA,IAAU,CAACC,sBAAA,CAAgB,WAAA,EAAa,WAAW,CAAA,EAAG;AAC3F,MAAA,MAAM,IAAI,+BAA+B,wCAAwC,CAAA;AAAA,IACnF;AAEA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAA,KAAQ,GAAI,CAAA;AACtC,IAAA,IAAI,KAAK,GAAA,CAAI,MAAA,GAAS,KAAA,CAAM,SAAS,IAAI,YAAA,EAAc;AACrD,MAAA,MAAM,IAAI,8BAAA;AAAA,QACR,iDAAiD,YAAY,CAAA,EAAA;AAAA,OAC/D;AAAA,IACF;AAEA,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,KAAA,GAAQ,IAAA,CAAK,MAAM,UAAU,CAAA;AAAA,IAC/B,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,+BAA+B,mCAAmC,CAAA;AAAA,IAC9E;AAEA,IAAA,OAAO,EAAE,SAAA,EAAW,KAAA,CAAM,SAAA,EAAW,KAAA,EAAM;AAAA,EAC7C;AACF;AAEA,SAAS,qBAAqB,MAAA,EAA0D;AACtF,EAAA,MAAM,SAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG;AACpC,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AAC5B,IAAA,IAAI,GAAA,KAAQ,IAAI,OAAO,IAAA;AACvB,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,GAAG,EAAE,IAAA,EAAK;AACpC,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,GAAM,CAAC,EAAE,IAAA,EAAK;AACvC,IAAA,IAAI,CAAC,GAAA,IAAO,CAAC,KAAA,EAAO,OAAO,IAAA;AAC3B,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,EAChB;AACA,EAAA,MAAM,IAAI,MAAA,CAAO,CAAA;AACjB,EAAA,MAAM,KAAK,MAAA,CAAO,EAAA;AAClB,EAAA,IAAI,CAAC,CAAA,IAAK,CAAC,EAAA,EAAI,OAAO,IAAA;AACtB,EAAA,MAAM,SAAA,GAAY,OAAO,CAAC,CAAA;AAC1B,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA,IAAK,CAAC,cAAA,CAAe,IAAA,CAAK,EAAE,CAAA,EAAG,OAAO,IAAA;AACpE,EAAA,OAAO,EAAE,WAAW,EAAA,EAAG;AACzB;;;ACvFA,IAAM,gBAAA,GAAmB,qBAAA;AACzB,IAAM,kBAAA,GAAqB,GAAA;AAC3B,IAAM,mBAAA,GAAsB,CAAA;AAC5B,IAAM,WAAA,GAAc,OAAA;AAqBb,IAAM,OAAN,MAAW;AAAA,EACA,OAAA;AAAA,EACA,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhB,OAAuB,QAAA,GAAW,QAAA;AAAA,EAClB,QAAA,GAAW,QAAA;AAAA,EAE3B,WAAA,CAAY,OAAA,GAAuB,EAAC,EAAG;AACrC,IAAA,MAAM,IAAA,GAAO,IAAI,UAAA,CAAW;AAAA,MAC1B,OAAA,EAAS,QAAQ,OAAA,IAAW,gBAAA;AAAA,MAC5B,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,SAAA,EAAW,QAAQ,SAAA,IAAa,kBAAA;AAAA,MAChC,UAAA,EAAY,QAAQ,UAAA,IAAc,mBAAA;AAAA,MAClC,SAAA,EAAW,aAAa,WAAW,CAAA,CAAA;AAAA,MACnC,OAAO,OAAA,CAAQ;AAAA,KAChB,CAAA;AACD,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,OAAA,CAAQ,IAAI,CAAA;AAC/B,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,IAAA,CAAK,IAAI,CAAA;AAAA,EAC3B;AACF","file":"index.cjs","sourcesContent":["/**\n * Error hierarchy for the Garu SDK.\n *\n * Every error has a stable `code` string so agents and typed clients can switch on it\n * without parsing messages. Non-2xx API responses are mapped to the most specific\n * subclass of `GaruAPIError` by {@link mapApiError}.\n */\n\nexport type GaruErrorCode =\n | 'authentication_error'\n | 'permission_error'\n | 'not_found'\n | 'validation_error'\n | 'rate_limited'\n | 'server_error'\n | 'api_error'\n | 'connection_error'\n | 'signature_verification_failed';\n\nexport class GaruError extends Error {\n public readonly code: GaruErrorCode;\n\n constructor(code: GaruErrorCode, message: string) {\n super(message);\n this.name = 'GaruError';\n this.code = code;\n }\n}\n\nexport class GaruConnectionError extends GaruError {\n public readonly connectionCause: unknown;\n constructor(message: string, connectionCause?: unknown) {\n super('connection_error', message);\n this.name = 'GaruConnectionError';\n this.connectionCause = connectionCause;\n }\n}\n\nexport class GaruSignatureVerificationError extends GaruError {\n constructor(message: string) {\n super('signature_verification_failed', message);\n this.name = 'GaruSignatureVerificationError';\n }\n}\n\nexport class GaruAPIError extends GaruError {\n public readonly status: number;\n public readonly requestId: string | null;\n public readonly body: unknown;\n\n constructor(\n code: GaruErrorCode,\n message: string,\n status: number,\n requestId: string | null,\n body: unknown\n ) {\n super(code, message);\n this.name = 'GaruAPIError';\n this.status = status;\n this.requestId = requestId;\n this.body = body;\n }\n}\n\nexport class GaruAuthenticationError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('authentication_error', message, status, requestId, body);\n this.name = 'GaruAuthenticationError';\n }\n}\n\nexport class GaruPermissionError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('permission_error', message, status, requestId, body);\n this.name = 'GaruPermissionError';\n }\n}\n\nexport class GaruNotFoundError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('not_found', message, status, requestId, body);\n this.name = 'GaruNotFoundError';\n }\n}\n\nexport class GaruValidationError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('validation_error', message, status, requestId, body);\n this.name = 'GaruValidationError';\n }\n}\n\nexport class GaruRateLimitError extends GaruAPIError {\n public readonly retryAfterSec: number | null;\n constructor(\n message: string,\n status: number,\n requestId: string | null,\n body: unknown,\n retryAfterSec: number | null\n ) {\n super('rate_limited', message, status, requestId, body);\n this.name = 'GaruRateLimitError';\n this.retryAfterSec = retryAfterSec;\n }\n}\n\nexport class GaruServerError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('server_error', message, status, requestId, body);\n this.name = 'GaruServerError';\n }\n}\n\n/**\n * Map a non-2xx HTTP response to the most specific {@link GaruAPIError} subclass.\n */\nexport function mapApiError(\n status: number,\n body: unknown,\n requestId: string | null,\n retryAfterSec: number | null\n): GaruAPIError {\n const message = extractMessage(body) ?? `Garu API returned HTTP ${status}`;\n\n if (status === 401) return new GaruAuthenticationError(message, status, requestId, body);\n if (status === 403) return new GaruPermissionError(message, status, requestId, body);\n if (status === 404) return new GaruNotFoundError(message, status, requestId, body);\n if (status === 400 || status === 422) {\n return new GaruValidationError(message, status, requestId, body);\n }\n if (status === 429) {\n return new GaruRateLimitError(message, status, requestId, body, retryAfterSec);\n }\n if (status >= 500) return new GaruServerError(message, status, requestId, body);\n return new GaruAPIError('api_error', message, status, requestId, body);\n}\n\nfunction extractMessage(body: unknown): string | null {\n if (typeof body === 'string') return body;\n if (body && typeof body === 'object') {\n const m = (body as { message?: unknown }).message;\n if (typeof m === 'string') return m;\n if (Array.isArray(m) && m.every((x) => typeof x === 'string')) return m.join('; ');\n }\n return null;\n}\n","import createClient from 'openapi-fetch';\n\nimport { GaruConnectionError, mapApiError, type GaruAPIError } from './errors.js';\nimport type { paths } from './generated/schema.js';\n\nexport interface HttpClientConfig {\n baseUrl: string;\n apiKey?: string;\n timeoutMs: number;\n maxRetries: number;\n userAgent: string;\n /** Injectable for tests. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n}\n\nconst RETRYABLE_STATUSES = new Set([408, 429, 500, 502, 503, 504]);\n\n/** Typed openapi-fetch client keyed to the backend's OpenAPI paths. */\nexport type GaruOpenapiClient = ReturnType<typeof createClient<paths>>;\n\n/** Arg type for `HttpClient.call` — a thunk that issues one openapi-fetch request. */\nexport type OpenapiCallResult<T> = Promise<{\n data?: T;\n error?: unknown;\n response: Response;\n}>;\n\n/**\n * HttpClient wraps the generated `openapi-fetch` client with:\n * - retries (exponential backoff, full jitter, honors `Retry-After`)\n * - typed error mapping (non-2xx → {@link GaruAPIError} subclass)\n * - connection error wrapping\n * - Authorization + User-Agent injection\n *\n * Resources call {@link call} with a thunk that returns an openapi-fetch\n * `{ data, error, response }` tuple; the wrapper either returns `data` or\n * throws the mapped error.\n */\nexport class HttpClient {\n public readonly client: GaruOpenapiClient;\n private readonly cfg: HttpClientConfig;\n\n constructor(cfg: HttpClientConfig) {\n this.cfg = cfg;\n const fetchImpl = cfg.fetch ?? globalThis.fetch;\n if (!fetchImpl) {\n throw new GaruConnectionError(\n 'No fetch implementation available. Node.js >= 18 is required.'\n );\n }\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'User-Agent': cfg.userAgent\n };\n if (cfg.apiKey) headers.Authorization = `Bearer ${cfg.apiKey}`;\n\n this.client = createClient<paths>({\n baseUrl: cfg.baseUrl.replace(/\\/+$/, ''),\n fetch: fetchImpl,\n headers\n });\n }\n\n /**\n * Issue one HTTP call against the typed client, with retries + error mapping.\n *\n * `fn` is invoked up to `maxRetries + 1` times. The timeout in `cfg.timeoutMs`\n * is enforced via `AbortController`.\n */\n async call<T>(fn: (signal: AbortSignal) => OpenapiCallResult<T>): Promise<T> {\n let lastError: GaruAPIError | GaruConnectionError | null = null;\n\n for (let attempt = 0; attempt <= this.cfg.maxRetries; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.cfg.timeoutMs);\n\n try {\n const { data, error, response } = await fn(controller.signal);\n clearTimeout(timer);\n\n if (response.ok) {\n return data as T;\n }\n\n const requestId = response.headers.get('x-request-id');\n const retryAfterSec = parseRetryAfter(response.headers.get('retry-after'));\n const apiError = mapApiError(response.status, error ?? null, requestId, retryAfterSec);\n lastError = apiError;\n\n if (!RETRYABLE_STATUSES.has(response.status) || attempt === this.cfg.maxRetries) {\n throw apiError;\n }\n\n await sleep(backoffDelay(attempt, retryAfterSec));\n continue;\n } catch (err) {\n clearTimeout(timer);\n\n if (isGaruApiError(err)) throw err;\n\n const connErr =\n err instanceof Error && err.name === 'AbortError'\n ? new GaruConnectionError(`Request timed out after ${this.cfg.timeoutMs}ms`, err)\n : new GaruConnectionError(err instanceof Error ? err.message : 'Network error', err);\n lastError = connErr;\n\n if (attempt === this.cfg.maxRetries) throw connErr;\n await sleep(backoffDelay(attempt, null));\n continue;\n }\n }\n\n // Unreachable — the loop always throws or returns on the final attempt.\n throw lastError ?? new GaruConnectionError('Request failed with no error captured');\n }\n}\n\nfunction isGaruApiError(err: unknown): boolean {\n return err instanceof Error && err.name.startsWith('Garu') && err.name.endsWith('Error');\n}\n\nfunction parseRetryAfter(value: string | null): number | null {\n if (!value) return null;\n const n = Number(value);\n return Number.isFinite(n) && n >= 0 ? n : null;\n}\n\n/**\n * Exponential backoff with full jitter. If the server returned `Retry-After`,\n * we honor it (with a small jitter).\n */\nfunction backoffDelay(attempt: number, retryAfterSec: number | null): number {\n if (retryAfterSec !== null) {\n return retryAfterSec * 1000 + Math.random() * 250;\n }\n const base = 500 * 2 ** attempt;\n const cap = 8000;\n return Math.min(cap, base) * Math.random();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { randomUUID } from 'node:crypto';\n\n/**\n * Generate a UUIDv4 suitable for use as an `X-Idempotency-Key` header value.\n *\n * @example\n * const key = generateIdempotencyKey();\n * // '3b241101-e2bb-4255-8caf-4136c566a962'\n */\nexport function generateIdempotencyKey(): string {\n return randomUUID();\n}\n","/**\n * Public types for the Garu SDK.\n *\n * The wire-level types (`WireCreateTransactionRequest`, `WireMetaResponse`, ...)\n * are generated from the backend's OpenAPI spec and live in\n * `src/generated/schema.d.ts`. The friendly types in this file\n * (`CreateChargeParams`, `Customer`, `Charge`, ...) are hand-curated for\n * ergonomics — they rename `transactions` to `charges`, collapse wire enums\n * into readable unions, and mark only truly required fields as required.\n * The resource layer maps friendly → wire at the edge.\n */\n\nimport type { components } from './generated/schema.js';\n\nexport type WireCreateTransactionRequest = components['schemas']['CreateTransactionRequest'];\nexport type WireCustomerDto = components['schemas']['CustomerDto'];\nexport type WireCardInfoDto = components['schemas']['CardInfoDto'];\nexport type WireMetaResponse = components['schemas']['MetaResponse'];\n\nexport type PaymentMethod = 'pix' | 'credit_card' | 'boleto';\n\n/** Payment-method identifier as sent to the backend over the wire. */\nexport type WirePaymentMethodId = 'pix' | 'creditcard' | 'boleto';\n\nexport type ChargeStatus =\n | 'pending'\n | 'authorized'\n | 'paid'\n | 'failed'\n | 'refunded'\n | 'cancelled'\n | 'expired';\n\nexport interface Customer {\n /** Full legal name. 3–255 chars. */\n name: string;\n email: string;\n /** CPF (11 digits) or CNPJ (14 digits), digits only. */\n document: string;\n /** 10 or 11 digits with area code, no formatting. */\n phone: string;\n /** 8 digits, no hyphen. Optional. */\n zipCode?: string;\n street?: string;\n number?: string;\n complement?: string;\n neighborhood?: string;\n city?: string;\n /** 2-letter uppercase state code, e.g. `SP`. */\n state?: string;\n}\n\nexport interface CardInfo {\n /** 13–19 digits, no spaces or hyphens. */\n cardNumber: string;\n /** 3 or 4 digits. */\n cvv: string;\n /** `YYYY-MM`. */\n expirationDate: string;\n /** As printed on the card. */\n holderName: string;\n /** 1–12. */\n installments: number;\n}\n\nexport interface CreateChargeParams {\n /** Customer buying the product. */\n customer: Customer;\n /** UUID of the product being charged. */\n productId: string;\n /** Payment method. */\n paymentMethod: PaymentMethod;\n /** Required when `paymentMethod` is `credit_card`. */\n cardInfo?: CardInfo;\n /** Free-form metadata attached to the charge. */\n additionalInfo?: string;\n /** Original checkout link, if any. */\n link?: string | null;\n /** Associated affiliate ID, if any. */\n affiliateId?: number | null;\n /** Subscription price ID (`price_*`), for subscription charges only. */\n priceId?: string | null;\n /** Optional pre-created checkout session token. */\n checkoutSessionToken?: string;\n /**\n * Idempotency key. If omitted, the SDK generates a UUIDv4.\n * Keys are valid for 24h on the backend.\n */\n idempotencyKey?: string;\n}\n\nexport interface Charge {\n id: number;\n status: ChargeStatus;\n amount: number;\n paymentMethodId: WirePaymentMethodId;\n /** ISO-8601. */\n date: string;\n /** ISO-8601. */\n deadline?: string;\n /** Product this charge belongs to. */\n product?: { id: number; uuid?: string; name?: string };\n [key: string]: unknown;\n}\n\nexport interface RefundChargeParams {\n /** Partial refund in centavos. Omit for full refund. */\n amount?: number;\n /** Free-form reason stored on the refund. */\n reason?: string;\n idempotencyKey?: string;\n}\n\nexport interface MetaFeatures {\n subscriptions: boolean;\n checkout_sessions: boolean;\n idempotency_keys: boolean;\n test_mode: boolean;\n webhooks: boolean;\n}\n\nexport interface MetaResponse {\n name: string;\n version: string;\n environment: 'production' | 'staging' | 'development' | string;\n api_version: string;\n payment_methods: string[];\n currencies: string[];\n billing_intervals: string[];\n webhook_events: string[];\n features: MetaFeatures;\n docs_url: string;\n dashboard_url: string;\n support_email: string;\n}\n\n/** Map the SDK's friendly `PaymentMethod` to the backend's wire value. */\nexport function toWirePaymentMethod(pm: PaymentMethod): WirePaymentMethodId {\n return pm === 'credit_card' ? 'creditcard' : pm;\n}\n","import type { HttpClient } from '../http.js';\nimport type { components } from '../generated/schema.js';\nimport { generateIdempotencyKey } from '../idempotency.js';\nimport {\n toWirePaymentMethod,\n type Charge,\n type CreateChargeParams,\n type RefundChargeParams\n} from '../types.js';\n\ntype CreateTransactionBody = components['schemas']['CreateTransactionRequest'];\n\n/**\n * Charges — the core of the Garu API.\n *\n * A charge represents a single payment attempt against a product. The SDK\n * surfaces charges under `garu.charges` even though the backend route is\n * `/api/transactions` — this matches Stripe convention and is the name every\n * other Garu surface (MCP, CLI, docs) uses.\n */\nexport class Charges {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a charge (PIX, credit card, or boleto).\n *\n * Automatically attaches an `X-Idempotency-Key` header — if you don't pass\n * `idempotencyKey`, the SDK generates a UUIDv4. Safe to retry: the backend\n * caches the first response for 24h.\n *\n * @example\n * // PIX charge\n * const charge = await garu.charges.create({\n * productId: 'b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f',\n * paymentMethod: 'pix',\n * customer: {\n * name: 'Maria Silva',\n * email: 'maria@exemplo.com.br',\n * document: '12345678909',\n * phone: '11987654321'\n * }\n * });\n * console.log(charge.id, charge.status);\n *\n * @example\n * // Credit card charge, 3 installments\n * const charge = await garu.charges.create({\n * productId: 'b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f',\n * paymentMethod: 'credit_card',\n * customer: { name: 'Maria Silva', email: 'maria@exemplo.com.br', document: '12345678909', phone: '11987654321' },\n * cardInfo: {\n * cardNumber: '4111111111111111',\n * cvv: '123',\n * expirationDate: '2030-12',\n * holderName: 'MARIA SILVA',\n * installments: 3\n * }\n * });\n */\n async create(params: CreateChargeParams): Promise<Charge> {\n const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();\n const body = this.buildCreateBody(params);\n\n return this.http.call<Charge>(\n (signal) =>\n this.http.client.POST('/api/transactions', {\n body,\n headers: { 'X-Idempotency-Key': idempotencyKey },\n signal\n }) as Promise<{ data?: Charge; error?: unknown; response: Response }>\n );\n }\n\n /**\n * Fetch a single charge by numeric ID.\n *\n * @example\n * const charge = await garu.charges.get(4472);\n * if (charge.status === 'paid') { ... }\n */\n async get(id: number): Promise<Charge> {\n return this.http.call<Charge>(\n (signal) =>\n this.http.client.GET('/api/transactions/{id}', {\n params: { path: { id } },\n signal\n }) as Promise<{ data?: Charge; error?: unknown; response: Response }>\n );\n }\n\n /**\n * Refund a charge — fully, or partially by passing `amount` in centavos.\n *\n * @example\n * // Full refund\n * await garu.charges.refund(4472);\n *\n * @example\n * // Partial refund of R$ 10,00\n * await garu.charges.refund(4472, { amount: 1000, reason: 'customer_request' });\n */\n async refund(id: number, params: RefundChargeParams = {}): Promise<Charge> {\n const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();\n const body: Record<string, unknown> = {};\n if (params.amount !== undefined) body.amount = params.amount;\n if (params.reason !== undefined) body.reason = params.reason;\n\n return this.http.call<Charge>(\n (signal) =>\n this.http.client.POST('/api/transactions/{id}/refund', {\n params: { path: { id } },\n body: body as never,\n headers: { 'X-Idempotency-Key': idempotencyKey },\n signal\n }) as Promise<{ data?: Charge; error?: unknown; response: Response }>\n );\n }\n\n private buildCreateBody(params: CreateChargeParams): CreateTransactionBody {\n const body: Record<string, unknown> = {\n customer: params.customer,\n productId: params.productId,\n paymentMethodId: toWirePaymentMethod(params.paymentMethod),\n link: params.link ?? null,\n affiliateId: params.affiliateId ?? null\n };\n if (params.additionalInfo !== undefined) body.additionalInfo = params.additionalInfo;\n if (params.priceId !== undefined) body.priceId = params.priceId;\n if (params.checkoutSessionToken !== undefined) {\n body.checkoutSessionToken = params.checkoutSessionToken;\n }\n if (params.cardInfo) body.CardInfo = params.cardInfo;\n return body as unknown as CreateTransactionBody;\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { MetaResponse } from '../types.js';\n\n/**\n * Meta — capability introspection.\n *\n * Unauthenticated. Used by `garu doctor`, MCP tool `doctor`, and by SDK\n * consumers that want to know which payment methods and webhook events are\n * currently supported.\n */\nexport class Meta {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Fetch the API's current capability payload.\n *\n * @example\n * const meta = await garu.meta.get();\n * console.log(meta.version, meta.payment_methods);\n * if (meta.features.subscriptions) { ... }\n */\n async get(): Promise<MetaResponse> {\n return this.http.call<MetaResponse>(\n (signal) =>\n this.http.client.GET('/api/meta', { signal }) as Promise<{\n data?: MetaResponse;\n error?: unknown;\n response: Response;\n }>\n );\n }\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto';\n\nimport { GaruSignatureVerificationError } from './errors.js';\n\nexport interface VerifyWebhookParams {\n /** Raw request body as received — do NOT re-serialize parsed JSON. */\n payload: string | Buffer;\n /** Value of the `X-Garu-Signature` header. Format: `t=<ts>,v1=<hex>`. */\n signature: string;\n /** The webhook endpoint's signing secret. */\n secret: string;\n /** Reject signatures older than this many seconds. Default: 300 (5 min). */\n toleranceSec?: number;\n /** Injectable for tests. Defaults to `Date.now()`. */\n now?: () => number;\n}\n\nexport interface VerifiedWebhook {\n /** Timestamp from the signature header, in seconds since epoch. */\n timestamp: number;\n /** Parsed JSON body. Throws {@link GaruSignatureVerificationError} if invalid JSON. */\n event: unknown;\n}\n\n/**\n * Webhook helpers.\n *\n * Garu signs outgoing webhooks with HMAC-SHA256 over `${timestamp}.${payload}`\n * and delivers the signature in the `X-Garu-Signature` header as `t=<ts>,v1=<hex>`.\n * This matches the format in the backend's `webhook-delivery.service.ts`.\n *\n * @example\n * // Express example\n * app.post('/webhooks/garu', express.raw({ type: 'application/json' }), (req, res) => {\n * try {\n * const { event } = Garu.webhooks.verify({\n * payload: req.body,\n * signature: req.header('x-garu-signature') ?? '',\n * secret: process.env.GARU_WEBHOOK_SECRET!\n * });\n * // handle event\n * res.sendStatus(200);\n * } catch (err) {\n * res.sendStatus(400);\n * }\n * });\n */\nexport const webhooks = {\n verify(params: VerifyWebhookParams): VerifiedWebhook {\n const { signature, secret, payload } = params;\n const toleranceSec = params.toleranceSec ?? 300;\n const now = params.now ?? Date.now;\n\n if (!signature || typeof signature !== 'string') {\n throw new GaruSignatureVerificationError('Missing or malformed X-Garu-Signature header');\n }\n\n const parts = parseSignatureHeader(signature);\n if (parts === null) {\n throw new GaruSignatureVerificationError(\n 'X-Garu-Signature header does not match expected format t=<ts>,v1=<hex>'\n );\n }\n\n const payloadStr = typeof payload === 'string' ? payload : payload.toString('utf8');\n const signedPayload = `${parts.timestamp}.${payloadStr}`;\n const expected = createHmac('sha256', secret).update(signedPayload).digest('hex');\n\n const expectedBuf = Buffer.from(expected, 'hex');\n const providedBuf = Buffer.from(parts.v1, 'hex');\n if (expectedBuf.length !== providedBuf.length || !timingSafeEqual(expectedBuf, providedBuf)) {\n throw new GaruSignatureVerificationError('Signature does not match computed HMAC');\n }\n\n const nowSec = Math.floor(now() / 1000);\n if (Math.abs(nowSec - parts.timestamp) > toleranceSec) {\n throw new GaruSignatureVerificationError(\n `Signature timestamp outside tolerance window (${toleranceSec}s)`\n );\n }\n\n let event: unknown;\n try {\n event = JSON.parse(payloadStr);\n } catch {\n throw new GaruSignatureVerificationError('Webhook payload is not valid JSON');\n }\n\n return { timestamp: parts.timestamp, event };\n }\n};\n\nfunction parseSignatureHeader(header: string): { timestamp: number; v1: string } | null {\n const fields: Record<string, string> = {};\n for (const part of header.split(',')) {\n const idx = part.indexOf('=');\n if (idx === -1) return null;\n const key = part.slice(0, idx).trim();\n const value = part.slice(idx + 1).trim();\n if (!key || !value) return null;\n fields[key] = value;\n }\n const t = fields.t;\n const v1 = fields.v1;\n if (!t || !v1) return null;\n const timestamp = Number(t);\n if (!Number.isFinite(timestamp) || !/^[a-f0-9]+$/i.test(v1)) return null;\n return { timestamp, v1 };\n}\n","import { HttpClient } from './http.js';\nimport { Charges } from './resources/charges.js';\nimport { Meta } from './resources/meta.js';\nimport { webhooks } from './webhooks.js';\n\nexport interface GaruOptions {\n /**\n * Your Garu API key. `sk_live_…` for production, `sk_test_…` for test mode.\n * Optional — public endpoints (`meta.get`, public charge creation) work without one.\n */\n apiKey?: string;\n /** Override the API base URL. Default: `https://garu.com.br/api`. */\n baseUrl?: string;\n /** Per-request timeout in ms. Default: 30000. */\n timeoutMs?: number;\n /** Max retries on retryable errors (connection, 408, 429, 5xx). Default: 2. */\n maxRetries?: number;\n /** Injectable for tests. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n}\n\nconst DEFAULT_BASE_URL = 'https://garu.com.br';\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst SDK_VERSION = '0.1.0';\n\n/**\n * The Garu SDK client.\n *\n * @example\n * import { Garu } from '@garuhq/node';\n *\n * const garu = new Garu({ apiKey: process.env.GARU_API_KEY });\n *\n * const charge = await garu.charges.create({\n * productId: 'b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f',\n * paymentMethod: 'pix',\n * customer: {\n * name: 'Maria Silva',\n * email: 'maria@exemplo.com.br',\n * document: '12345678909',\n * phone: '11987654321'\n * }\n * });\n */\nexport class Garu {\n public readonly charges: Charges;\n public readonly meta: Meta;\n\n /**\n * Webhook helpers. Available both as an instance member and as a static —\n * `Garu.webhooks.verify(...)` works without constructing a client.\n */\n public static readonly webhooks = webhooks;\n public readonly webhooks = webhooks;\n\n constructor(options: GaruOptions = {}) {\n const http = new HttpClient({\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n apiKey: options.apiKey,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxRetries: options.maxRetries ?? DEFAULT_MAX_RETRIES,\n userAgent: `garu-node/${SDK_VERSION}`,\n fetch: options.fetch\n });\n this.charges = new Charges(http);\n this.meta = new Meta(http);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/idempotency.ts","../src/types.ts","../src/resources/charges.ts","../src/resources/customers.ts","../src/resources/meta.ts","../src/webhooks.ts","../src/client.ts"],"names":["createClient","randomUUID","createHmac","timingSafeEqual"],"mappings":";;;;;;;;;;;;AAmBO,IAAM,SAAA,GAAN,cAAwB,KAAA,CAAM;AAAA,EACnB,IAAA;AAAA,EAEhB,WAAA,CAAY,MAAqB,OAAA,EAAiB;AAChD,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,WAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,SAAA,CAAU;AAAA,EACjC,eAAA;AAAA,EAChB,WAAA,CAAY,SAAiB,eAAA,EAA2B;AACtD,IAAA,KAAA,CAAM,oBAAoB,OAAO,CAAA;AACjC,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AACZ,IAAA,IAAA,CAAK,eAAA,GAAkB,eAAA;AAAA,EACzB;AACF;AAEO,IAAM,8BAAA,GAAN,cAA6C,SAAA,CAAU;AAAA,EAC5D,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,iCAAiC,OAAO,CAAA;AAC9C,IAAA,IAAA,CAAK,IAAA,GAAO,gCAAA;AAAA,EACd;AACF;AAEO,IAAM,YAAA,GAAN,cAA2B,SAAA,CAAU;AAAA,EAC1B,MAAA;AAAA,EACA,SAAA;AAAA,EACA,IAAA;AAAA,EAEhB,WAAA,CACE,IAAA,EACA,OAAA,EACA,MAAA,EACA,WACA,IAAA,EACA;AACA,IAAA,KAAA,CAAM,MAAM,OAAO,CAAA;AACnB,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AACF;AAEO,IAAM,uBAAA,GAAN,cAAsC,YAAA,CAAa;AAAA,EACxD,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,SAAA,EAA0B,IAAA,EAAe;AACpF,IAAA,KAAA,CAAM,sBAAA,EAAwB,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAI,CAAA;AAC9D,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EACd;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,YAAA,CAAa;AAAA,EACpD,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,SAAA,EAA0B,IAAA,EAAe;AACpF,IAAA,KAAA,CAAM,kBAAA,EAAoB,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAI,CAAA;AAC1D,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAEO,IAAM,iBAAA,GAAN,cAAgC,YAAA,CAAa;AAAA,EAClD,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,SAAA,EAA0B,IAAA,EAAe;AACpF,IAAA,KAAA,CAAM,WAAA,EAAa,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAI,CAAA;AACnD,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,YAAA,CAAa;AAAA,EACpD,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,SAAA,EAA0B,IAAA,EAAe;AACpF,IAAA,KAAA,CAAM,kBAAA,EAAoB,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAI,CAAA;AAC1D,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAEO,IAAM,kBAAA,GAAN,cAAiC,YAAA,CAAa;AAAA,EACnC,aAAA;AAAA,EAChB,WAAA,CACE,OAAA,EACA,MAAA,EACA,SAAA,EACA,MACA,aAAA,EACA;AACA,IAAA,KAAA,CAAM,cAAA,EAAgB,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAI,CAAA;AACtD,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AACZ,IAAA,IAAA,CAAK,aAAA,GAAgB,aAAA;AAAA,EACvB;AACF;AAEO,IAAM,eAAA,GAAN,cAA8B,YAAA,CAAa;AAAA,EAChD,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,SAAA,EAA0B,IAAA,EAAe;AACpF,IAAA,KAAA,CAAM,cAAA,EAAgB,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,IAAI,CAAA;AACtD,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAKO,SAAS,WAAA,CACd,MAAA,EACA,IAAA,EACA,SAAA,EACA,aAAA,EACc;AACd,EAAA,MAAM,OAAA,GAAU,cAAA,CAAe,IAAI,CAAA,IAAK,0BAA0B,MAAM,CAAA,CAAA;AAExE,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,IAAI,wBAAwB,OAAA,EAAS,MAAA,EAAQ,WAAW,IAAI,CAAA;AACvF,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,IAAI,oBAAoB,OAAA,EAAS,MAAA,EAAQ,WAAW,IAAI,CAAA;AACnF,EAAA,IAAI,MAAA,KAAW,KAAK,OAAO,IAAI,kBAAkB,OAAA,EAAS,MAAA,EAAQ,WAAW,IAAI,CAAA;AACjF,EAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,GAAA,EAAK;AACpC,IAAA,OAAO,IAAI,mBAAA,CAAoB,OAAA,EAAS,MAAA,EAAQ,WAAW,IAAI,CAAA;AAAA,EACjE;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,IAAI,kBAAA,CAAmB,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,MAAM,aAAa,CAAA;AAAA,EAC/E;AACA,EAAA,IAAI,MAAA,IAAU,KAAK,OAAO,IAAI,gBAAgB,OAAA,EAAS,MAAA,EAAQ,WAAW,IAAI,CAAA;AAC9E,EAAA,OAAO,IAAI,YAAA,CAAa,WAAA,EAAa,OAAA,EAAS,MAAA,EAAQ,WAAW,IAAI,CAAA;AACvE;AAEA,SAAS,eAAe,IAAA,EAA8B;AACpD,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AACrC,EAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACpC,IAAA,MAAM,IAAK,IAAA,CAA+B,OAAA;AAC1C,IAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,CAAA;AAClC,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,IAAK,EAAE,KAAA,CAAM,CAAC,CAAA,KAAM,OAAO,MAAM,QAAQ,CAAA,EAAG,OAAO,CAAA,CAAE,KAAK,IAAI,CAAA;AAAA,EACnF;AACA,EAAA,OAAO,IAAA;AACT;;;ACpIA,IAAM,kBAAA,mBAAqB,IAAI,GAAA,CAAI,CAAC,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAG,CAAC,CAAA;AAuB1D,IAAM,aAAN,MAAiB;AAAA,EACN,MAAA;AAAA,EACC,GAAA;AAAA,EAEjB,YAAY,GAAA,EAAuB;AACjC,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AACX,IAAA,MAAM,SAAA,GAAY,GAAA,CAAI,KAAA,IAAS,UAAA,CAAW,KAAA;AAC1C,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,mBAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,MAAA,EAAQ,kBAAA;AAAA,MACR,cAAc,GAAA,CAAI;AAAA,KACpB;AACA,IAAA,IAAI,IAAI,MAAA,EAAQ,OAAA,CAAQ,aAAA,GAAgB,CAAA,OAAA,EAAU,IAAI,MAAM,CAAA,CAAA;AAE5D,IAAA,IAAA,CAAK,SAASA,6BAAA,CAAoB;AAAA,MAChC,OAAA,EAAS,GAAA,CAAI,OAAA,CAAQ,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAAA,MACvC,KAAA,EAAO,SAAA;AAAA,MACP;AAAA,KACD,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAQ,EAAA,EAA+D;AAC3E,IAAA,IAAI,SAAA,GAAuD,IAAA;AAE3D,IAAA,KAAA,IAAS,UAAU,CAAA,EAAG,OAAA,IAAW,IAAA,CAAK,GAAA,CAAI,YAAY,OAAA,EAAA,EAAW;AAC/D,MAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,MAAA,MAAM,KAAA,GAAQ,WAAW,MAAM,UAAA,CAAW,OAAM,EAAG,IAAA,CAAK,IAAI,SAAS,CAAA;AAErE,MAAA,IAAI;AACF,QAAA,MAAM,EAAE,MAAM,KAAA,EAAO,QAAA,KAAa,MAAM,EAAA,CAAG,WAAW,MAAM,CAAA;AAC5D,QAAA,YAAA,CAAa,KAAK,CAAA;AAElB,QAAA,IAAI,SAAS,EAAA,EAAI;AACf,UAAA,OAAO,IAAA;AAAA,QACT;AAEA,QAAA,MAAM,SAAA,GAAY,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA;AACrD,QAAA,MAAM,gBAAgB,eAAA,CAAgB,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAC,CAAA;AACzE,QAAA,MAAM,WAAW,WAAA,CAAY,QAAA,CAAS,QAAQ,KAAA,IAAS,IAAA,EAAM,WAAW,aAAa,CAAA;AACrF,QAAA,SAAA,GAAY,QAAA;AAEZ,QAAA,IAAI,CAAC,mBAAmB,GAAA,CAAI,QAAA,CAAS,MAAM,CAAA,IAAK,OAAA,KAAY,IAAA,CAAK,GAAA,CAAI,UAAA,EAAY;AAC/E,UAAA,MAAM,QAAA;AAAA,QACR;AAEA,QAAA,MAAM,KAAA,CAAM,YAAA,CAAa,OAAA,EAAS,aAAa,CAAC,CAAA;AAChD,QAAA;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,YAAA,CAAa,KAAK,CAAA;AAElB,QAAA,IAAI,cAAA,CAAe,GAAG,CAAA,EAAG,MAAM,GAAA;AAE/B,QAAA,MAAM,OAAA,GACJ,eAAe,KAAA,IAAS,GAAA,CAAI,SAAS,YAAA,GACjC,IAAI,mBAAA,CAAoB,CAAA,wBAAA,EAA2B,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA,EAAA,CAAA,EAAM,GAAG,IAC9E,IAAI,mBAAA,CAAoB,eAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,eAAA,EAAiB,GAAG,CAAA;AACvF,QAAA,SAAA,GAAY,OAAA;AAEZ,QAAA,IAAI,OAAA,KAAY,IAAA,CAAK,GAAA,CAAI,UAAA,EAAY,MAAM,OAAA;AAC3C,QAAA,MAAM,KAAA,CAAM,YAAA,CAAa,OAAA,EAAS,IAAI,CAAC,CAAA;AACvC,QAAA;AAAA,MACF;AAAA,IACF;AAGA,IAAA,MAAM,SAAA,IAAa,IAAI,mBAAA,CAAoB,uCAAuC,CAAA;AAAA,EACpF;AACF,CAAA;AAEA,SAAS,eAAe,GAAA,EAAuB;AAC7C,EAAA,OAAO,GAAA,YAAe,KAAA,IAAS,GAAA,CAAI,IAAA,CAAK,UAAA,CAAW,MAAM,CAAA,IAAK,GAAA,CAAI,IAAA,CAAK,QAAA,CAAS,OAAO,CAAA;AACzF;AAEA,SAAS,gBAAgB,KAAA,EAAqC;AAC5D,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,MAAM,CAAA,GAAI,OAAO,KAAK,CAAA;AACtB,EAAA,OAAO,OAAO,QAAA,CAAS,CAAC,CAAA,IAAK,CAAA,IAAK,IAAI,CAAA,GAAI,IAAA;AAC5C;AAMA,SAAS,YAAA,CAAa,SAAiB,aAAA,EAAsC;AAC3E,EAAA,IAAI,kBAAkB,IAAA,EAAM;AAC1B,IAAA,OAAO,aAAA,GAAgB,GAAA,GAAO,IAAA,CAAK,MAAA,EAAO,GAAI,GAAA;AAAA,EAChD;AACA,EAAA,MAAM,IAAA,GAAO,MAAM,CAAA,IAAK,OAAA;AACxB,EAAA,MAAM,GAAA,GAAM,GAAA;AACZ,EAAA,OAAO,KAAK,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA,GAAI,KAAK,MAAA,EAAO;AAC3C;AAEA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD;ACrIO,SAAS,sBAAA,GAAiC;AAC/C,EAAA,OAAOC,iBAAA,EAAW;AACpB;;;ACoNO,SAAS,oBAAoB,EAAA,EAAwC;AAC1E,EAAA,OAAO,EAAA,KAAO,gBAAgB,YAAA,GAAe,EAAA;AAC/C;;;AC3MO,IAAM,UAAN,MAAc;AAAA,EACnB,YAA6B,IAAA,EAAkB;AAAlB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAmB;AAAA,EAAnB,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsC7B,MAAM,OAAO,MAAA,EAA6C;AACxD,IAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,cAAA,IAAkB,sBAAA,EAAuB;AACvE,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,eAAA,CAAgB,MAAM,CAAA;AAExC,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MACf,CAAC,MAAA,KACC,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,KAAK,mBAAA,EAAqB;AAAA,QACzC,IAAA;AAAA,QACA,OAAA,EAAS,EAAE,mBAAA,EAAqB,cAAA,EAAe;AAAA,QAC/C;AAAA,OACD;AAAA,KACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAA,CAAK,MAAA,GAA4B,EAAC,EAAwB;AAC9D,IAAA,MAAM,QAAgC,EAAC;AACvC,IAAA,IAAI,OAAO,IAAA,KAAS,MAAA,QAAiB,IAAA,GAAO,MAAA,CAAO,OAAO,IAAI,CAAA;AAC9D,IAAA,IAAI,OAAO,KAAA,KAAU,MAAA,QAAiB,KAAA,GAAQ,MAAA,CAAO,OAAO,KAAK,CAAA;AACjE,IAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,KAAA,CAAM,MAAA,GAAS,MAAA,CAAO,MAAA;AACzC,IAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,KAAA,CAAM,MAAA,GAAS,MAAA,CAAO,MAAA;AACzC,IAAA,IAAI,MAAA,CAAO,aAAA,EAAe,KAAA,CAAM,aAAA,GAAgB,MAAA,CAAO,aAAA;AAEvD,IAAA,MAAM,EAAA,GAAK,IAAI,eAAA,CAAgB,KAAK,EAAE,QAAA,EAAS;AAC/C,IAAA,MAAM,MAAM,CAAA,iBAAA,EAAoB,EAAA,GAAK,CAAA,CAAA,EAAI,EAAE,KAAK,EAAE,CAAA,CAAA;AAElD,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MAAiB,CAAC,MAAA,KAChC,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,IAAiB,GAAA,EAAK,EAAE,MAAA,EAAQ,CAAA,CAAE,IAAA;AAAA,QAClD,CAAC,CAAA,KAAkE;AAAA;AACrE,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAI,EAAA,EAA6B;AACrC,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MACf,CAAC,MAAA,KACC,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,IAAI,wBAAA,EAA0B;AAAA,QAC7C,MAAA,EAAQ,EAAE,IAAA,EAAM,EAAE,IAAG,EAAE;AAAA,QACvB;AAAA,OACD;AAAA,KACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,MAAA,CAAO,EAAA,EAAY,MAAA,GAA6B,EAAC,EAAoB;AACzE,IAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,cAAA,IAAkB,sBAAA,EAAuB;AACvE,IAAA,MAAM,OAAgC,EAAC;AACvC,IAAA,IAAI,MAAA,CAAO,MAAA,KAAW,MAAA,EAAW,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AACtD,IAAA,IAAI,MAAA,CAAO,MAAA,KAAW,MAAA,EAAW,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AAEtD,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MACf,CAAC,MAAA,KACC,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,KAAK,+BAAA,EAAiC;AAAA,QACrD,MAAA,EAAQ,EAAE,IAAA,EAAM,EAAE,IAAG,EAAE;AAAA,QACvB,IAAA;AAAA,QACA,OAAA,EAAS,EAAE,mBAAA,EAAqB,cAAA,EAAe;AAAA,QAC/C;AAAA,OACD;AAAA,KACL;AAAA,EACF;AAAA,EAEQ,gBAAgB,MAAA,EAAmD;AACzE,IAAA,MAAM,IAAA,GAAgC;AAAA,MACpC,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,WAAW,MAAA,CAAO,SAAA;AAAA,MAClB,eAAA,EAAiB,mBAAA,CAAoB,MAAA,CAAO,aAAa,CAAA;AAAA,MACzD,IAAA,EAAM,OAAO,IAAA,IAAQ,IAAA;AAAA,MACrB,WAAA,EAAa,OAAO,WAAA,IAAe;AAAA,KACrC;AACA,IAAA,IAAI,MAAA,CAAO,cAAA,KAAmB,MAAA,EAAW,IAAA,CAAK,iBAAiB,MAAA,CAAO,cAAA;AACtE,IAAA,IAAI,MAAA,CAAO,OAAA,KAAY,MAAA,EAAW,IAAA,CAAK,UAAU,MAAA,CAAO,OAAA;AACxD,IAAA,IAAI,MAAA,CAAO,yBAAyB,MAAA,EAAW;AAC7C,MAAA,IAAA,CAAK,uBAAuB,MAAA,CAAO,oBAAA;AAAA,IACrC;AACA,IAAA,IAAI,MAAA,CAAO,QAAA,EAAU,IAAA,CAAK,QAAA,GAAW,MAAA,CAAO,QAAA;AAC5C,IAAA,OAAO,IAAA;AAAA,EACT;AACF,CAAA;;;ACjJO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAA6B,IAAA,EAAkB;AAAlB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAmB;AAAA,EAAnB,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAc7B,MAAM,OAAO,MAAA,EAAuD;AAClE,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MAAqB,CAAC,MAAA,KACpC,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,KAAkB,gBAAA,EAAkB;AAAA,QACpD,IAAA,EAAM,MAAA;AAAA,QACN;AAAA,OACD,CAAA,CAAE,IAAA,CAAK,CAAC,MAAsE,CAAC;AAAA,KAClF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAA,CAAK,MAAA,GAA8B,EAAC,EAA0B;AAClE,IAAA,MAAM,QAAgC,EAAC;AACvC,IAAA,IAAI,OAAO,IAAA,KAAS,MAAA,QAAiB,IAAA,GAAO,MAAA,CAAO,OAAO,IAAI,CAAA;AAC9D,IAAA,IAAI,OAAO,KAAA,KAAU,MAAA,QAAiB,KAAA,GAAQ,MAAA,CAAO,OAAO,KAAK,CAAA;AACjE,IAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,KAAA,CAAM,MAAA,GAAS,MAAA,CAAO,MAAA;AAEzC,IAAA,MAAM,EAAA,GAAK,IAAI,eAAA,CAAgB,KAAK,EAAE,QAAA,EAAS;AAC/C,IAAA,MAAM,MAAM,CAAA,cAAA,EAAiB,EAAA,GAAK,CAAA,CAAA,EAAI,EAAE,KAAK,EAAE,CAAA,CAAA;AAE/C,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MAAmB,CAAC,MAAA,KAClC,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,IAAiB,GAAA,EAAK,EAAE,MAAA,EAAQ,CAAA,CAAE,IAAA;AAAA,QAClD,CAAC,CAAA,KAAoE;AAAA;AACvE,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAI,EAAA,EAAqC;AAC7C,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MAAqB,CAAC,MAAA,KACpC,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,GAAA,CAAiB,CAAA,eAAA,EAAkB,EAAE,CAAA,CAAA,EAAI,EAAE,MAAA,EAAQ,CAAA,CAAE,IAAA;AAAA,QACrE,CAAC,CAAA,KAAsE;AAAA;AACzE,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MAAA,CAAO,EAAA,EAAY,MAAA,EAAuD;AAC9E,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MAAqB,CAAC,WACpC,IAAA,CAAK,IAAA,CAAK,OAAO,GAAA,CAAiB,CAAA,eAAA,EAAkB,EAAE,CAAA,CAAA,EAAI;AAAA,QACzD,IAAA,EAAM,MAAA;AAAA,QACN;AAAA,OACD,CAAA,CAAE,IAAA,CAAK,CAAC,MAAsE,CAAC;AAAA,KAClF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO,EAAA,EAA2B;AACtC,IAAA,MAAM,KAAK,IAAA,CAAK,IAAA;AAAA,MAAc,CAAC,MAAA,KAC5B,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,MAAA,CAAoB,CAAA,eAAA,EAAkB,EAAE,CAAA,CAAA,EAAI,EAAE,MAAA,EAAQ,CAAA,CAAE,IAAA;AAAA,QACxE,CAAC,CAAA,KAA+D;AAAA;AAClE,KACF;AAAA,EACF;AACF,CAAA;;;AC9FO,IAAM,OAAN,MAAW;AAAA,EAChB,YAA6B,IAAA,EAAkB;AAAlB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAmB;AAAA,EAAnB,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU7B,MAAM,GAAA,GAA6B;AACjC,IAAA,OAAO,KAAK,IAAA,CAAK,IAAA;AAAA,MACf,CAAC,WACC,IAAA,CAAK,IAAA,CAAK,OAAO,GAAA,CAAI,WAAA,EAAa,EAAE,MAAA,EAAQ;AAAA,KAKhD;AAAA,EACF;AACF,CAAA;ACgBO,IAAM,QAAA,GAAW;AAAA,EACtB,OAAO,MAAA,EAA8C;AACnD,IAAA,MAAM,EAAE,SAAA,EAAW,MAAA,EAAQ,OAAA,EAAQ,GAAI,MAAA;AACvC,IAAA,MAAM,YAAA,GAAe,OAAO,YAAA,IAAgB,GAAA;AAC5C,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,GAAA,IAAO,IAAA,CAAK,GAAA;AAE/B,IAAA,IAAI,CAAC,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,EAAU;AAC/C,MAAA,MAAM,IAAI,+BAA+B,8CAA8C,CAAA;AAAA,IACzF;AAEA,IAAA,MAAM,KAAA,GAAQ,qBAAqB,SAAS,CAAA;AAC5C,IAAA,IAAI,UAAU,IAAA,EAAM;AAClB,MAAA,MAAM,IAAI,8BAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,aAAa,OAAO,OAAA,KAAY,WAAW,OAAA,GAAU,OAAA,CAAQ,SAAS,MAAM,CAAA;AAClF,IAAA,MAAM,aAAA,GAAgB,CAAA,EAAG,KAAA,CAAM,SAAS,IAAI,UAAU,CAAA,CAAA;AACtD,IAAA,MAAM,QAAA,GAAWC,kBAAW,QAAA,EAAU,MAAM,EAAE,MAAA,CAAO,aAAa,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA;AAEhF,IAAA,MAAM,WAAA,GAAc,MAAA,CAAO,IAAA,CAAK,QAAA,EAAU,KAAK,CAAA;AAC/C,IAAA,MAAM,WAAA,GAAc,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,IAAI,KAAK,CAAA;AAC/C,IAAA,IAAI,WAAA,CAAY,WAAW,WAAA,CAAY,MAAA,IAAU,CAACC,sBAAA,CAAgB,WAAA,EAAa,WAAW,CAAA,EAAG;AAC3F,MAAA,MAAM,IAAI,+BAA+B,wCAAwC,CAAA;AAAA,IACnF;AAEA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAA,KAAQ,GAAI,CAAA;AACtC,IAAA,IAAI,KAAK,GAAA,CAAI,MAAA,GAAS,KAAA,CAAM,SAAS,IAAI,YAAA,EAAc;AACrD,MAAA,MAAM,IAAI,8BAAA;AAAA,QACR,iDAAiD,YAAY,CAAA,EAAA;AAAA,OAC/D;AAAA,IACF;AAEA,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,KAAA,GAAQ,IAAA,CAAK,MAAM,UAAU,CAAA;AAAA,IAC/B,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,+BAA+B,mCAAmC,CAAA;AAAA,IAC9E;AAEA,IAAA,OAAO,EAAE,SAAA,EAAW,KAAA,CAAM,SAAA,EAAW,KAAA,EAAM;AAAA,EAC7C;AACF;AAEA,SAAS,qBAAqB,MAAA,EAA0D;AACtF,EAAA,MAAM,SAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG;AACpC,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AAC5B,IAAA,IAAI,GAAA,KAAQ,IAAI,OAAO,IAAA;AACvB,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,GAAG,EAAE,IAAA,EAAK;AACpC,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,GAAM,CAAC,EAAE,IAAA,EAAK;AACvC,IAAA,IAAI,CAAC,GAAA,IAAO,CAAC,KAAA,EAAO,OAAO,IAAA;AAC3B,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,EAChB;AACA,EAAA,MAAM,IAAI,MAAA,CAAO,CAAA;AACjB,EAAA,MAAM,KAAK,MAAA,CAAO,EAAA;AAClB,EAAA,IAAI,CAAC,CAAA,IAAK,CAAC,EAAA,EAAI,OAAO,IAAA;AACtB,EAAA,MAAM,SAAA,GAAY,OAAO,CAAC,CAAA;AAC1B,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA,IAAK,CAAC,cAAA,CAAe,IAAA,CAAK,EAAE,CAAA,EAAG,OAAO,IAAA;AACpE,EAAA,OAAO,EAAE,WAAW,EAAA,EAAG;AACzB;;;ACtFA,IAAM,gBAAA,GAAmB,qBAAA;AACzB,IAAM,kBAAA,GAAqB,GAAA;AAC3B,IAAM,mBAAA,GAAsB,CAAA;AAC5B,IAAM,WAAA,GAAc,OAAA;AAqBb,IAAM,OAAN,MAAW;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhB,OAAuB,QAAA,GAAW,QAAA;AAAA,EAClB,QAAA,GAAW,QAAA;AAAA,EAE3B,WAAA,CAAY,OAAA,GAAuB,EAAC,EAAG;AACrC,IAAA,MAAM,IAAA,GAAO,IAAI,UAAA,CAAW;AAAA,MAC1B,OAAA,EAAS,QAAQ,OAAA,IAAW,gBAAA;AAAA,MAC5B,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,SAAA,EAAW,QAAQ,SAAA,IAAa,kBAAA;AAAA,MAChC,UAAA,EAAY,QAAQ,UAAA,IAAc,mBAAA;AAAA,MAClC,SAAA,EAAW,aAAa,WAAW,CAAA,CAAA;AAAA,MACnC,OAAO,OAAA,CAAQ;AAAA,KAChB,CAAA;AACD,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,OAAA,CAAQ,IAAI,CAAA;AAC/B,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,SAAA,CAAU,IAAI,CAAA;AACnC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,IAAA,CAAK,IAAI,CAAA;AAAA,EAC3B;AACF","file":"index.cjs","sourcesContent":["/**\n * Error hierarchy for the Garu SDK.\n *\n * Every error has a stable `code` string so agents and typed clients can switch on it\n * without parsing messages. Non-2xx API responses are mapped to the most specific\n * subclass of `GaruAPIError` by {@link mapApiError}.\n */\n\nexport type GaruErrorCode =\n | 'authentication_error'\n | 'permission_error'\n | 'not_found'\n | 'validation_error'\n | 'rate_limited'\n | 'server_error'\n | 'api_error'\n | 'connection_error'\n | 'signature_verification_failed';\n\nexport class GaruError extends Error {\n public readonly code: GaruErrorCode;\n\n constructor(code: GaruErrorCode, message: string) {\n super(message);\n this.name = 'GaruError';\n this.code = code;\n }\n}\n\nexport class GaruConnectionError extends GaruError {\n public readonly connectionCause: unknown;\n constructor(message: string, connectionCause?: unknown) {\n super('connection_error', message);\n this.name = 'GaruConnectionError';\n this.connectionCause = connectionCause;\n }\n}\n\nexport class GaruSignatureVerificationError extends GaruError {\n constructor(message: string) {\n super('signature_verification_failed', message);\n this.name = 'GaruSignatureVerificationError';\n }\n}\n\nexport class GaruAPIError extends GaruError {\n public readonly status: number;\n public readonly requestId: string | null;\n public readonly body: unknown;\n\n constructor(\n code: GaruErrorCode,\n message: string,\n status: number,\n requestId: string | null,\n body: unknown\n ) {\n super(code, message);\n this.name = 'GaruAPIError';\n this.status = status;\n this.requestId = requestId;\n this.body = body;\n }\n}\n\nexport class GaruAuthenticationError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('authentication_error', message, status, requestId, body);\n this.name = 'GaruAuthenticationError';\n }\n}\n\nexport class GaruPermissionError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('permission_error', message, status, requestId, body);\n this.name = 'GaruPermissionError';\n }\n}\n\nexport class GaruNotFoundError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('not_found', message, status, requestId, body);\n this.name = 'GaruNotFoundError';\n }\n}\n\nexport class GaruValidationError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('validation_error', message, status, requestId, body);\n this.name = 'GaruValidationError';\n }\n}\n\nexport class GaruRateLimitError extends GaruAPIError {\n public readonly retryAfterSec: number | null;\n constructor(\n message: string,\n status: number,\n requestId: string | null,\n body: unknown,\n retryAfterSec: number | null\n ) {\n super('rate_limited', message, status, requestId, body);\n this.name = 'GaruRateLimitError';\n this.retryAfterSec = retryAfterSec;\n }\n}\n\nexport class GaruServerError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('server_error', message, status, requestId, body);\n this.name = 'GaruServerError';\n }\n}\n\n/**\n * Map a non-2xx HTTP response to the most specific {@link GaruAPIError} subclass.\n */\nexport function mapApiError(\n status: number,\n body: unknown,\n requestId: string | null,\n retryAfterSec: number | null\n): GaruAPIError {\n const message = extractMessage(body) ?? `Garu API returned HTTP ${status}`;\n\n if (status === 401) return new GaruAuthenticationError(message, status, requestId, body);\n if (status === 403) return new GaruPermissionError(message, status, requestId, body);\n if (status === 404) return new GaruNotFoundError(message, status, requestId, body);\n if (status === 400 || status === 422) {\n return new GaruValidationError(message, status, requestId, body);\n }\n if (status === 429) {\n return new GaruRateLimitError(message, status, requestId, body, retryAfterSec);\n }\n if (status >= 500) return new GaruServerError(message, status, requestId, body);\n return new GaruAPIError('api_error', message, status, requestId, body);\n}\n\nfunction extractMessage(body: unknown): string | null {\n if (typeof body === 'string') return body;\n if (body && typeof body === 'object') {\n const m = (body as { message?: unknown }).message;\n if (typeof m === 'string') return m;\n if (Array.isArray(m) && m.every((x) => typeof x === 'string')) return m.join('; ');\n }\n return null;\n}\n","import createClient from 'openapi-fetch';\n\nimport { GaruConnectionError, mapApiError, type GaruAPIError } from './errors.js';\nimport type { paths } from './generated/schema.js';\n\nexport interface HttpClientConfig {\n baseUrl: string;\n apiKey?: string;\n timeoutMs: number;\n maxRetries: number;\n userAgent: string;\n /** Injectable for tests. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n}\n\nconst RETRYABLE_STATUSES = new Set([408, 429, 500, 502, 503, 504]);\n\n/** Typed openapi-fetch client keyed to the backend's OpenAPI paths. */\nexport type GaruOpenapiClient = ReturnType<typeof createClient<paths>>;\n\n/** Arg type for `HttpClient.call` — a thunk that issues one openapi-fetch request. */\nexport type OpenapiCallResult<T> = Promise<{\n data?: T;\n error?: unknown;\n response: Response;\n}>;\n\n/**\n * HttpClient wraps the generated `openapi-fetch` client with:\n * - retries (exponential backoff, full jitter, honors `Retry-After`)\n * - typed error mapping (non-2xx → {@link GaruAPIError} subclass)\n * - connection error wrapping\n * - Authorization + User-Agent injection\n *\n * Resources call {@link call} with a thunk that returns an openapi-fetch\n * `{ data, error, response }` tuple; the wrapper either returns `data` or\n * throws the mapped error.\n */\nexport class HttpClient {\n public readonly client: GaruOpenapiClient;\n private readonly cfg: HttpClientConfig;\n\n constructor(cfg: HttpClientConfig) {\n this.cfg = cfg;\n const fetchImpl = cfg.fetch ?? globalThis.fetch;\n if (!fetchImpl) {\n throw new GaruConnectionError(\n 'No fetch implementation available. Node.js >= 18 is required.'\n );\n }\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'User-Agent': cfg.userAgent\n };\n if (cfg.apiKey) headers.Authorization = `Bearer ${cfg.apiKey}`;\n\n this.client = createClient<paths>({\n baseUrl: cfg.baseUrl.replace(/\\/+$/, ''),\n fetch: fetchImpl,\n headers\n });\n }\n\n /**\n * Issue one HTTP call against the typed client, with retries + error mapping.\n *\n * `fn` is invoked up to `maxRetries + 1` times. The timeout in `cfg.timeoutMs`\n * is enforced via `AbortController`.\n */\n async call<T>(fn: (signal: AbortSignal) => OpenapiCallResult<T>): Promise<T> {\n let lastError: GaruAPIError | GaruConnectionError | null = null;\n\n for (let attempt = 0; attempt <= this.cfg.maxRetries; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.cfg.timeoutMs);\n\n try {\n const { data, error, response } = await fn(controller.signal);\n clearTimeout(timer);\n\n if (response.ok) {\n return data as T;\n }\n\n const requestId = response.headers.get('x-request-id');\n const retryAfterSec = parseRetryAfter(response.headers.get('retry-after'));\n const apiError = mapApiError(response.status, error ?? null, requestId, retryAfterSec);\n lastError = apiError;\n\n if (!RETRYABLE_STATUSES.has(response.status) || attempt === this.cfg.maxRetries) {\n throw apiError;\n }\n\n await sleep(backoffDelay(attempt, retryAfterSec));\n continue;\n } catch (err) {\n clearTimeout(timer);\n\n if (isGaruApiError(err)) throw err;\n\n const connErr =\n err instanceof Error && err.name === 'AbortError'\n ? new GaruConnectionError(`Request timed out after ${this.cfg.timeoutMs}ms`, err)\n : new GaruConnectionError(err instanceof Error ? err.message : 'Network error', err);\n lastError = connErr;\n\n if (attempt === this.cfg.maxRetries) throw connErr;\n await sleep(backoffDelay(attempt, null));\n continue;\n }\n }\n\n // Unreachable — the loop always throws or returns on the final attempt.\n throw lastError ?? new GaruConnectionError('Request failed with no error captured');\n }\n}\n\nfunction isGaruApiError(err: unknown): boolean {\n return err instanceof Error && err.name.startsWith('Garu') && err.name.endsWith('Error');\n}\n\nfunction parseRetryAfter(value: string | null): number | null {\n if (!value) return null;\n const n = Number(value);\n return Number.isFinite(n) && n >= 0 ? n : null;\n}\n\n/**\n * Exponential backoff with full jitter. If the server returned `Retry-After`,\n * we honor it (with a small jitter).\n */\nfunction backoffDelay(attempt: number, retryAfterSec: number | null): number {\n if (retryAfterSec !== null) {\n return retryAfterSec * 1000 + Math.random() * 250;\n }\n const base = 500 * 2 ** attempt;\n const cap = 8000;\n return Math.min(cap, base) * Math.random();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { randomUUID } from 'node:crypto';\n\n/**\n * Generate a UUIDv4 suitable for use as an `X-Idempotency-Key` header value.\n *\n * @example\n * const key = generateIdempotencyKey();\n * // '3b241101-e2bb-4255-8caf-4136c566a962'\n */\nexport function generateIdempotencyKey(): string {\n return randomUUID();\n}\n","/**\n * Public types for the Garu SDK.\n *\n * The wire-level types (`WireCreateTransactionRequest`, `WireMetaResponse`, ...)\n * are generated from the backend's OpenAPI spec and live in\n * `src/generated/schema.d.ts`. The friendly types in this file\n * (`CreateChargeParams`, `Customer`, `Charge`, ...) are hand-curated for\n * ergonomics — they rename `transactions` to `charges`, collapse wire enums\n * into readable unions, and mark only truly required fields as required.\n * The resource layer maps friendly → wire at the edge.\n */\n\nimport type { components } from './generated/schema.js';\n\nexport type WireCreateTransactionRequest = components['schemas']['CreateTransactionRequest'];\nexport type WireCustomerDto = components['schemas']['CustomerDto'];\nexport type WireCardInfoDto = components['schemas']['CardInfoDto'];\nexport type WireMetaResponse = components['schemas']['MetaResponse'];\n\nexport type PaymentMethod = 'pix' | 'credit_card' | 'boleto';\n\n/** Payment-method identifier as sent to the backend over the wire. */\nexport type WirePaymentMethodId = 'pix' | 'creditcard' | 'boleto';\n\nexport type ChargeStatus =\n | 'pending'\n | 'authorized'\n | 'paid'\n | 'failed'\n | 'refunded'\n | 'cancelled'\n | 'expired';\n\nexport interface Customer {\n /** Full legal name. 3–255 chars. */\n name: string;\n email: string;\n /** CPF (11 digits) or CNPJ (14 digits), digits only. */\n document: string;\n /** 10 or 11 digits with area code, no formatting. */\n phone: string;\n /** 8 digits, no hyphen. Optional. */\n zipCode?: string;\n street?: string;\n number?: string;\n complement?: string;\n neighborhood?: string;\n city?: string;\n /** 2-letter uppercase state code, e.g. `SP`. */\n state?: string;\n}\n\nexport interface CardInfo {\n /** 13–19 digits, no spaces or hyphens. */\n cardNumber: string;\n /** 3 or 4 digits. */\n cvv: string;\n /** `YYYY-MM`. */\n expirationDate: string;\n /** As printed on the card. */\n holderName: string;\n /** 1–12. */\n installments: number;\n}\n\nexport interface CreateChargeParams {\n /** Customer buying the product. */\n customer: Customer;\n /** UUID of the product being charged. */\n productId: string;\n /** Payment method. */\n paymentMethod: PaymentMethod;\n /** Required when `paymentMethod` is `credit_card`. */\n cardInfo?: CardInfo;\n /** Free-form metadata attached to the charge. */\n additionalInfo?: string;\n /** Original checkout link, if any. */\n link?: string | null;\n /** Associated affiliate ID, if any. */\n affiliateId?: number | null;\n /** Subscription price ID (`price_*`), for subscription charges only. */\n priceId?: string | null;\n /** Optional pre-created checkout session token. */\n checkoutSessionToken?: string;\n /**\n * Idempotency key. If omitted, the SDK generates a UUIDv4.\n * Keys are valid for 24h on the backend.\n */\n idempotencyKey?: string;\n}\n\nexport interface Charge {\n id: number;\n status: ChargeStatus;\n amount: number;\n paymentMethodId: WirePaymentMethodId;\n /** ISO-8601. */\n date: string;\n /** ISO-8601. */\n deadline?: string;\n /** Product this charge belongs to. */\n product?: { id: number; uuid?: string; name?: string };\n [key: string]: unknown;\n}\n\nexport interface RefundChargeParams {\n /** Partial refund in centavos. Omit for full refund. */\n amount?: number;\n /** Free-form reason stored on the refund. */\n reason?: string;\n idempotencyKey?: string;\n}\n\nexport interface ListChargesParams {\n /** Page number (1-based). Default: 1. */\n page?: number;\n /** Items per page (1–100). Default: 20. */\n limit?: number;\n /** Filter by status (e.g. `paid`, `pending`). */\n status?: string;\n /** Search by customer name, email, or document. */\n search?: string;\n /** Filter by payment method (`pix`, `creditcard`, `boleto`). */\n paymentMethod?: string;\n}\n\nexport interface PaginatedList<T> {\n data: T[];\n meta: {\n page: number;\n limit: number;\n total: number;\n totalPages: number;\n };\n}\n\nexport type ChargeList = PaginatedList<Charge>;\n\nexport interface CustomerRecord {\n id: number;\n name: string;\n email: string;\n document: string;\n phone: string;\n personType: string;\n zipCode?: string | null;\n street?: string | null;\n number?: string | null;\n complement?: string | null;\n neighborhood?: string | null;\n city?: string | null;\n state?: string | null;\n createdAt: string;\n updatedAt: string;\n [key: string]: unknown;\n}\n\nexport type CustomerList = PaginatedList<CustomerRecord>;\n\nexport interface CreateCustomerParams {\n name: string;\n email: string;\n /** CPF (11 digits) or CNPJ (14 digits), digits only. */\n document: string;\n /** 10 or 11 digits with area code. */\n phone: string;\n /** `fisica` or `juridica`. */\n personType: 'fisica' | 'juridica';\n zipCode?: string;\n street?: string;\n number?: string;\n complement?: string;\n neighborhood?: string;\n city?: string;\n /** 2-letter uppercase state code, e.g. `SP`. */\n state?: string;\n}\n\nexport interface UpdateCustomerParams {\n name?: string;\n email?: string;\n document?: string;\n phone?: string;\n personType?: 'fisica' | 'juridica';\n zipCode?: string;\n street?: string;\n number?: string;\n complement?: string;\n neighborhood?: string;\n city?: string;\n state?: string;\n}\n\nexport interface ListCustomersParams {\n page?: number;\n limit?: number;\n search?: string;\n}\n\nexport interface MetaFeatures {\n subscriptions: boolean;\n checkout_sessions: boolean;\n idempotency_keys: boolean;\n test_mode: boolean;\n webhooks: boolean;\n}\n\nexport interface MetaResponse {\n name: string;\n version: string;\n environment: 'production' | 'staging' | 'development' | string;\n api_version: string;\n payment_methods: string[];\n currencies: string[];\n billing_intervals: string[];\n webhook_events: string[];\n features: MetaFeatures;\n docs_url: string;\n dashboard_url: string;\n support_email: string;\n}\n\n/** Map the SDK's friendly `PaymentMethod` to the backend's wire value. */\nexport function toWirePaymentMethod(pm: PaymentMethod): WirePaymentMethodId {\n return pm === 'credit_card' ? 'creditcard' : pm;\n}\n","import type { HttpClient } from '../http.js';\nimport type { components } from '../generated/schema.js';\nimport { generateIdempotencyKey } from '../idempotency.js';\nimport {\n toWirePaymentMethod,\n type Charge,\n type ChargeList,\n type CreateChargeParams,\n type ListChargesParams,\n type RefundChargeParams\n} from '../types.js';\n\ntype CreateTransactionBody = components['schemas']['CreateTransactionRequest'];\n\n/**\n * Charges — the core of the Garu API.\n *\n * A charge represents a single payment attempt against a product. The SDK\n * surfaces charges under `garu.charges` even though the backend route is\n * `/api/transactions` — this matches Stripe convention and is the name every\n * other Garu surface (MCP, CLI, docs) uses.\n */\nexport class Charges {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a charge (PIX, credit card, or boleto).\n *\n * Automatically attaches an `X-Idempotency-Key` header — if you don't pass\n * `idempotencyKey`, the SDK generates a UUIDv4. Safe to retry: the backend\n * caches the first response for 24h.\n *\n * @example\n * // PIX charge\n * const charge = await garu.charges.create({\n * productId: 'b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f',\n * paymentMethod: 'pix',\n * customer: {\n * name: 'Maria Silva',\n * email: 'maria@exemplo.com.br',\n * document: '12345678909',\n * phone: '11987654321'\n * }\n * });\n * // charge.id, charge.status\n *\n * @example\n * // Credit card charge, 3 installments\n * const charge = await garu.charges.create({\n * productId: 'b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f',\n * paymentMethod: 'credit_card',\n * customer: { name: 'Maria Silva', email: 'maria@exemplo.com.br', document: '12345678909', phone: '11987654321' },\n * cardInfo: {\n * cardNumber: '4111111111111111',\n * cvv: '123',\n * expirationDate: '2030-12',\n * holderName: 'MARIA SILVA',\n * installments: 3\n * }\n * });\n */\n async create(params: CreateChargeParams): Promise<Charge> {\n const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();\n const body = this.buildCreateBody(params);\n\n return this.http.call<Charge>(\n (signal) =>\n this.http.client.POST('/api/transactions', {\n body,\n headers: { 'X-Idempotency-Key': idempotencyKey },\n signal\n }) as Promise<{ data?: Charge; error?: unknown; response: Response }>\n );\n }\n\n /**\n * List charges for the authenticated seller, with pagination and filters.\n *\n * @example\n * const { data, meta } = await garu.charges.list({ status: 'paid', limit: 10 });\n * // meta.total paid charges\n */\n async list(params: ListChargesParams = {}): Promise<ChargeList> {\n const query: Record<string, string> = {};\n if (params.page !== undefined) query.page = String(params.page);\n if (params.limit !== undefined) query.limit = String(params.limit);\n if (params.status) query.status = params.status;\n if (params.search) query.search = params.search;\n if (params.paymentMethod) query.paymentMethod = params.paymentMethod;\n\n const qs = new URLSearchParams(query).toString();\n const url = `/api/transactions${qs ? `?${qs}` : ''}`;\n\n return this.http.call<ChargeList>((signal) =>\n (this.http.client.GET as Function)(url, { signal }).then(\n (r: { data?: ChargeList; error?: unknown; response: Response }) => r\n )\n );\n }\n\n /**\n * Fetch a single charge by numeric ID.\n *\n * @example\n * const charge = await garu.charges.get(4472);\n * if (charge.status === 'paid') { ... }\n */\n async get(id: number): Promise<Charge> {\n return this.http.call<Charge>(\n (signal) =>\n this.http.client.GET('/api/transactions/{id}', {\n params: { path: { id } },\n signal\n }) as Promise<{ data?: Charge; error?: unknown; response: Response }>\n );\n }\n\n /**\n * Refund a charge — fully, or partially by passing `amount` in centavos.\n *\n * @example\n * // Full refund\n * await garu.charges.refund(4472);\n *\n * @example\n * // Partial refund of R$ 10,00\n * await garu.charges.refund(4472, { amount: 1000, reason: 'customer_request' });\n */\n async refund(id: number, params: RefundChargeParams = {}): Promise<Charge> {\n const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();\n const body: Record<string, unknown> = {};\n if (params.amount !== undefined) body.amount = params.amount;\n if (params.reason !== undefined) body.reason = params.reason;\n\n return this.http.call<Charge>(\n (signal) =>\n this.http.client.POST('/api/transactions/{id}/refund', {\n params: { path: { id } },\n body: body as never,\n headers: { 'X-Idempotency-Key': idempotencyKey },\n signal\n }) as Promise<{ data?: Charge; error?: unknown; response: Response }>\n );\n }\n\n private buildCreateBody(params: CreateChargeParams): CreateTransactionBody {\n const body: Record<string, unknown> = {\n customer: params.customer,\n productId: params.productId,\n paymentMethodId: toWirePaymentMethod(params.paymentMethod),\n link: params.link ?? null,\n affiliateId: params.affiliateId ?? null\n };\n if (params.additionalInfo !== undefined) body.additionalInfo = params.additionalInfo;\n if (params.priceId !== undefined) body.priceId = params.priceId;\n if (params.checkoutSessionToken !== undefined) {\n body.checkoutSessionToken = params.checkoutSessionToken;\n }\n if (params.cardInfo) body.CardInfo = params.cardInfo;\n return body as unknown as CreateTransactionBody;\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type {\n CreateCustomerParams,\n CustomerList,\n CustomerRecord,\n ListCustomersParams,\n UpdateCustomerParams\n} from '../types.js';\n\n/**\n * Customers — manage your customer base.\n *\n * Customers are scoped to the seller identified by the API key. The backend\n * uses a junction table (`customer_seller_profile`) so the same person can\n * exist across multiple sellers without duplication.\n */\nexport class Customers {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a customer and link it to the current seller.\n *\n * @example\n * const customer = await garu.customers.create({\n * name: 'Maria Silva',\n * email: 'maria@exemplo.com.br',\n * document: '12345678909',\n * phone: '11987654321',\n * personType: 'fisica'\n * });\n */\n async create(params: CreateCustomerParams): Promise<CustomerRecord> {\n return this.http.call<CustomerRecord>((signal) =>\n (this.http.client.POST as Function)('/api/customers', {\n body: params,\n signal\n }).then((r: { data?: CustomerRecord; error?: unknown; response: Response }) => r)\n );\n }\n\n /**\n * List customers for the authenticated seller, with pagination and search.\n *\n * @example\n * const { data, meta } = await garu.customers.list({ search: 'maria', limit: 10 });\n */\n async list(params: ListCustomersParams = {}): Promise<CustomerList> {\n const query: Record<string, string> = {};\n if (params.page !== undefined) query.page = String(params.page);\n if (params.limit !== undefined) query.limit = String(params.limit);\n if (params.search) query.search = params.search;\n\n const qs = new URLSearchParams(query).toString();\n const url = `/api/customers${qs ? `?${qs}` : ''}`;\n\n return this.http.call<CustomerList>((signal) =>\n (this.http.client.GET as Function)(url, { signal }).then(\n (r: { data?: CustomerList; error?: unknown; response: Response }) => r\n )\n );\n }\n\n /**\n * Fetch a single customer by numeric ID.\n *\n * @example\n * const customer = await garu.customers.get(42);\n */\n async get(id: number): Promise<CustomerRecord> {\n return this.http.call<CustomerRecord>((signal) =>\n (this.http.client.GET as Function)(`/api/customers/${id}`, { signal }).then(\n (r: { data?: CustomerRecord; error?: unknown; response: Response }) => r\n )\n );\n }\n\n /**\n * Update a customer's profile for the current seller.\n *\n * @example\n * const updated = await garu.customers.update(42, { name: 'Maria Santos' });\n */\n async update(id: number, params: UpdateCustomerParams): Promise<CustomerRecord> {\n return this.http.call<CustomerRecord>((signal) =>\n (this.http.client.PUT as Function)(`/api/customers/${id}`, {\n body: params,\n signal\n }).then((r: { data?: CustomerRecord; error?: unknown; response: Response }) => r)\n );\n }\n\n /**\n * Remove a customer from the current seller.\n *\n * @example\n * await garu.customers.delete(42);\n */\n async delete(id: number): Promise<void> {\n await this.http.call<unknown>((signal) =>\n (this.http.client.DELETE as Function)(`/api/customers/${id}`, { signal }).then(\n (r: { data?: unknown; error?: unknown; response: Response }) => r\n )\n );\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { MetaResponse } from '../types.js';\n\n/**\n * Meta — capability introspection.\n *\n * Unauthenticated. Used by `garu doctor`, MCP tool `doctor`, and by SDK\n * consumers that want to know which payment methods and webhook events are\n * currently supported.\n */\nexport class Meta {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Fetch the API's current capability payload.\n *\n * @example\n * const meta = await garu.meta.get();\n * console.log(meta.version, meta.payment_methods);\n * if (meta.features.subscriptions) { ... }\n */\n async get(): Promise<MetaResponse> {\n return this.http.call<MetaResponse>(\n (signal) =>\n this.http.client.GET('/api/meta', { signal }) as Promise<{\n data?: MetaResponse;\n error?: unknown;\n response: Response;\n }>\n );\n }\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto';\n\nimport { GaruSignatureVerificationError } from './errors.js';\n\nexport interface VerifyWebhookParams {\n /** Raw request body as received — do NOT re-serialize parsed JSON. */\n payload: string | Buffer;\n /** Value of the `X-Garu-Signature` header. Format: `t=<ts>,v1=<hex>`. */\n signature: string;\n /** The webhook endpoint's signing secret. */\n secret: string;\n /** Reject signatures older than this many seconds. Default: 300 (5 min). */\n toleranceSec?: number;\n /** Injectable for tests. Defaults to `Date.now()`. */\n now?: () => number;\n}\n\nexport interface VerifiedWebhook {\n /** Timestamp from the signature header, in seconds since epoch. */\n timestamp: number;\n /** Parsed JSON body. Throws {@link GaruSignatureVerificationError} if invalid JSON. */\n event: unknown;\n}\n\n/**\n * Webhook helpers.\n *\n * Garu signs outgoing webhooks with HMAC-SHA256 over `${timestamp}.${payload}`\n * and delivers the signature in the `X-Garu-Signature` header as `t=<ts>,v1=<hex>`.\n * This matches the format in the backend's `webhook-delivery.service.ts`.\n *\n * @example\n * // Express example\n * app.post('/webhooks/garu', express.raw({ type: 'application/json' }), (req, res) => {\n * try {\n * const { event } = Garu.webhooks.verify({\n * payload: req.body,\n * signature: req.header('x-garu-signature') ?? '',\n * secret: process.env.GARU_WEBHOOK_SECRET!\n * });\n * // handle event\n * res.sendStatus(200);\n * } catch (err) {\n * res.sendStatus(400);\n * }\n * });\n */\nexport const webhooks = {\n verify(params: VerifyWebhookParams): VerifiedWebhook {\n const { signature, secret, payload } = params;\n const toleranceSec = params.toleranceSec ?? 300;\n const now = params.now ?? Date.now;\n\n if (!signature || typeof signature !== 'string') {\n throw new GaruSignatureVerificationError('Missing or malformed X-Garu-Signature header');\n }\n\n const parts = parseSignatureHeader(signature);\n if (parts === null) {\n throw new GaruSignatureVerificationError(\n 'X-Garu-Signature header does not match expected format t=<ts>,v1=<hex>'\n );\n }\n\n const payloadStr = typeof payload === 'string' ? payload : payload.toString('utf8');\n const signedPayload = `${parts.timestamp}.${payloadStr}`;\n const expected = createHmac('sha256', secret).update(signedPayload).digest('hex');\n\n const expectedBuf = Buffer.from(expected, 'hex');\n const providedBuf = Buffer.from(parts.v1, 'hex');\n if (expectedBuf.length !== providedBuf.length || !timingSafeEqual(expectedBuf, providedBuf)) {\n throw new GaruSignatureVerificationError('Signature does not match computed HMAC');\n }\n\n const nowSec = Math.floor(now() / 1000);\n if (Math.abs(nowSec - parts.timestamp) > toleranceSec) {\n throw new GaruSignatureVerificationError(\n `Signature timestamp outside tolerance window (${toleranceSec}s)`\n );\n }\n\n let event: unknown;\n try {\n event = JSON.parse(payloadStr);\n } catch {\n throw new GaruSignatureVerificationError('Webhook payload is not valid JSON');\n }\n\n return { timestamp: parts.timestamp, event };\n }\n};\n\nfunction parseSignatureHeader(header: string): { timestamp: number; v1: string } | null {\n const fields: Record<string, string> = {};\n for (const part of header.split(',')) {\n const idx = part.indexOf('=');\n if (idx === -1) return null;\n const key = part.slice(0, idx).trim();\n const value = part.slice(idx + 1).trim();\n if (!key || !value) return null;\n fields[key] = value;\n }\n const t = fields.t;\n const v1 = fields.v1;\n if (!t || !v1) return null;\n const timestamp = Number(t);\n if (!Number.isFinite(timestamp) || !/^[a-f0-9]+$/i.test(v1)) return null;\n return { timestamp, v1 };\n}\n","import { HttpClient } from './http.js';\nimport { Charges } from './resources/charges.js';\nimport { Customers } from './resources/customers.js';\nimport { Meta } from './resources/meta.js';\nimport { webhooks } from './webhooks.js';\n\nexport interface GaruOptions {\n /**\n * Your Garu API key. `sk_live_…` for production, `sk_test_…` for test mode.\n * Optional — public endpoints (`meta.get`, public charge creation) work without one.\n */\n apiKey?: string;\n /** Override the API base URL. Default: `https://garu.com.br/api`. */\n baseUrl?: string;\n /** Per-request timeout in ms. Default: 30000. */\n timeoutMs?: number;\n /** Max retries on retryable errors (connection, 408, 429, 5xx). Default: 2. */\n maxRetries?: number;\n /** Injectable for tests. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n}\n\nconst DEFAULT_BASE_URL = 'https://garu.com.br';\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst SDK_VERSION = '0.2.0';\n\n/**\n * The Garu SDK client.\n *\n * @example\n * import { Garu } from '@garuhq/node';\n *\n * const garu = new Garu({ apiKey: process.env.GARU_API_KEY });\n *\n * const charge = await garu.charges.create({\n * productId: 'b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f',\n * paymentMethod: 'pix',\n * customer: {\n * name: 'Maria Silva',\n * email: 'maria@exemplo.com.br',\n * document: '12345678909',\n * phone: '11987654321'\n * }\n * });\n */\nexport class Garu {\n public readonly charges: Charges;\n public readonly customers: Customers;\n public readonly meta: Meta;\n\n /**\n * Webhook helpers. Available both as an instance member and as a static —\n * `Garu.webhooks.verify(...)` works without constructing a client.\n */\n public static readonly webhooks = webhooks;\n public readonly webhooks = webhooks;\n\n constructor(options: GaruOptions = {}) {\n const http = new HttpClient({\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n apiKey: options.apiKey,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxRetries: options.maxRetries ?? DEFAULT_MAX_RETRIES,\n userAgent: `garu-node/${SDK_VERSION}`,\n fetch: options.fetch\n });\n this.charges = new Charges(http);\n this.customers = new Customers(http);\n this.meta = new Meta(http);\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -181,6 +181,84 @@ interface RefundChargeParams {
|
|
|
181
181
|
reason?: string;
|
|
182
182
|
idempotencyKey?: string;
|
|
183
183
|
}
|
|
184
|
+
interface ListChargesParams {
|
|
185
|
+
/** Page number (1-based). Default: 1. */
|
|
186
|
+
page?: number;
|
|
187
|
+
/** Items per page (1–100). Default: 20. */
|
|
188
|
+
limit?: number;
|
|
189
|
+
/** Filter by status (e.g. `paid`, `pending`). */
|
|
190
|
+
status?: string;
|
|
191
|
+
/** Search by customer name, email, or document. */
|
|
192
|
+
search?: string;
|
|
193
|
+
/** Filter by payment method (`pix`, `creditcard`, `boleto`). */
|
|
194
|
+
paymentMethod?: string;
|
|
195
|
+
}
|
|
196
|
+
interface PaginatedList<T> {
|
|
197
|
+
data: T[];
|
|
198
|
+
meta: {
|
|
199
|
+
page: number;
|
|
200
|
+
limit: number;
|
|
201
|
+
total: number;
|
|
202
|
+
totalPages: number;
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
type ChargeList = PaginatedList<Charge>;
|
|
206
|
+
interface CustomerRecord {
|
|
207
|
+
id: number;
|
|
208
|
+
name: string;
|
|
209
|
+
email: string;
|
|
210
|
+
document: string;
|
|
211
|
+
phone: string;
|
|
212
|
+
personType: string;
|
|
213
|
+
zipCode?: string | null;
|
|
214
|
+
street?: string | null;
|
|
215
|
+
number?: string | null;
|
|
216
|
+
complement?: string | null;
|
|
217
|
+
neighborhood?: string | null;
|
|
218
|
+
city?: string | null;
|
|
219
|
+
state?: string | null;
|
|
220
|
+
createdAt: string;
|
|
221
|
+
updatedAt: string;
|
|
222
|
+
[key: string]: unknown;
|
|
223
|
+
}
|
|
224
|
+
type CustomerList = PaginatedList<CustomerRecord>;
|
|
225
|
+
interface CreateCustomerParams {
|
|
226
|
+
name: string;
|
|
227
|
+
email: string;
|
|
228
|
+
/** CPF (11 digits) or CNPJ (14 digits), digits only. */
|
|
229
|
+
document: string;
|
|
230
|
+
/** 10 or 11 digits with area code. */
|
|
231
|
+
phone: string;
|
|
232
|
+
/** `fisica` or `juridica`. */
|
|
233
|
+
personType: 'fisica' | 'juridica';
|
|
234
|
+
zipCode?: string;
|
|
235
|
+
street?: string;
|
|
236
|
+
number?: string;
|
|
237
|
+
complement?: string;
|
|
238
|
+
neighborhood?: string;
|
|
239
|
+
city?: string;
|
|
240
|
+
/** 2-letter uppercase state code, e.g. `SP`. */
|
|
241
|
+
state?: string;
|
|
242
|
+
}
|
|
243
|
+
interface UpdateCustomerParams {
|
|
244
|
+
name?: string;
|
|
245
|
+
email?: string;
|
|
246
|
+
document?: string;
|
|
247
|
+
phone?: string;
|
|
248
|
+
personType?: 'fisica' | 'juridica';
|
|
249
|
+
zipCode?: string;
|
|
250
|
+
street?: string;
|
|
251
|
+
number?: string;
|
|
252
|
+
complement?: string;
|
|
253
|
+
neighborhood?: string;
|
|
254
|
+
city?: string;
|
|
255
|
+
state?: string;
|
|
256
|
+
}
|
|
257
|
+
interface ListCustomersParams {
|
|
258
|
+
page?: number;
|
|
259
|
+
limit?: number;
|
|
260
|
+
search?: string;
|
|
261
|
+
}
|
|
184
262
|
interface MetaFeatures {
|
|
185
263
|
subscriptions: boolean;
|
|
186
264
|
checkout_sessions: boolean;
|
|
@@ -233,7 +311,7 @@ declare class Charges {
|
|
|
233
311
|
* phone: '11987654321'
|
|
234
312
|
* }
|
|
235
313
|
* });
|
|
236
|
-
*
|
|
314
|
+
* // charge.id, charge.status
|
|
237
315
|
*
|
|
238
316
|
* @example
|
|
239
317
|
* // Credit card charge, 3 installments
|
|
@@ -251,6 +329,14 @@ declare class Charges {
|
|
|
251
329
|
* });
|
|
252
330
|
*/
|
|
253
331
|
create(params: CreateChargeParams): Promise<Charge>;
|
|
332
|
+
/**
|
|
333
|
+
* List charges for the authenticated seller, with pagination and filters.
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* const { data, meta } = await garu.charges.list({ status: 'paid', limit: 10 });
|
|
337
|
+
* // meta.total paid charges
|
|
338
|
+
*/
|
|
339
|
+
list(params?: ListChargesParams): Promise<ChargeList>;
|
|
254
340
|
/**
|
|
255
341
|
* Fetch a single charge by numeric ID.
|
|
256
342
|
*
|
|
@@ -274,6 +360,59 @@ declare class Charges {
|
|
|
274
360
|
private buildCreateBody;
|
|
275
361
|
}
|
|
276
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Customers — manage your customer base.
|
|
365
|
+
*
|
|
366
|
+
* Customers are scoped to the seller identified by the API key. The backend
|
|
367
|
+
* uses a junction table (`customer_seller_profile`) so the same person can
|
|
368
|
+
* exist across multiple sellers without duplication.
|
|
369
|
+
*/
|
|
370
|
+
declare class Customers {
|
|
371
|
+
private readonly http;
|
|
372
|
+
constructor(http: HttpClient);
|
|
373
|
+
/**
|
|
374
|
+
* Create a customer and link it to the current seller.
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* const customer = await garu.customers.create({
|
|
378
|
+
* name: 'Maria Silva',
|
|
379
|
+
* email: 'maria@exemplo.com.br',
|
|
380
|
+
* document: '12345678909',
|
|
381
|
+
* phone: '11987654321',
|
|
382
|
+
* personType: 'fisica'
|
|
383
|
+
* });
|
|
384
|
+
*/
|
|
385
|
+
create(params: CreateCustomerParams): Promise<CustomerRecord>;
|
|
386
|
+
/**
|
|
387
|
+
* List customers for the authenticated seller, with pagination and search.
|
|
388
|
+
*
|
|
389
|
+
* @example
|
|
390
|
+
* const { data, meta } = await garu.customers.list({ search: 'maria', limit: 10 });
|
|
391
|
+
*/
|
|
392
|
+
list(params?: ListCustomersParams): Promise<CustomerList>;
|
|
393
|
+
/**
|
|
394
|
+
* Fetch a single customer by numeric ID.
|
|
395
|
+
*
|
|
396
|
+
* @example
|
|
397
|
+
* const customer = await garu.customers.get(42);
|
|
398
|
+
*/
|
|
399
|
+
get(id: number): Promise<CustomerRecord>;
|
|
400
|
+
/**
|
|
401
|
+
* Update a customer's profile for the current seller.
|
|
402
|
+
*
|
|
403
|
+
* @example
|
|
404
|
+
* const updated = await garu.customers.update(42, { name: 'Maria Santos' });
|
|
405
|
+
*/
|
|
406
|
+
update(id: number, params: UpdateCustomerParams): Promise<CustomerRecord>;
|
|
407
|
+
/**
|
|
408
|
+
* Remove a customer from the current seller.
|
|
409
|
+
*
|
|
410
|
+
* @example
|
|
411
|
+
* await garu.customers.delete(42);
|
|
412
|
+
*/
|
|
413
|
+
delete(id: number): Promise<void>;
|
|
414
|
+
}
|
|
415
|
+
|
|
277
416
|
/**
|
|
278
417
|
* Meta — capability introspection.
|
|
279
418
|
*
|
|
@@ -331,6 +470,7 @@ interface GaruOptions {
|
|
|
331
470
|
*/
|
|
332
471
|
declare class Garu {
|
|
333
472
|
readonly charges: Charges;
|
|
473
|
+
readonly customers: Customers;
|
|
334
474
|
readonly meta: Meta;
|
|
335
475
|
/**
|
|
336
476
|
* Webhook helpers. Available both as an instance member and as a static —
|
|
@@ -390,4 +530,4 @@ declare class GaruServerError extends GaruAPIError {
|
|
|
390
530
|
constructor(message: string, status: number, requestId: string | null, body: unknown);
|
|
391
531
|
}
|
|
392
532
|
|
|
393
|
-
export { type CardInfo, type Charge, type ChargeStatus, type CreateChargeParams, type Customer, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type MetaFeatures, type MetaResponse, type PaymentMethod, type RefundChargeParams, type VerifiedWebhook, type VerifyWebhookParams, type WirePaymentMethodId, webhooks };
|
|
533
|
+
export { type CardInfo, type Charge, type ChargeList, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type Customer, type CustomerList, type CustomerRecord, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PaymentMethod, type RefundChargeParams, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WirePaymentMethodId, webhooks };
|
package/dist/index.d.ts
CHANGED
|
@@ -181,6 +181,84 @@ interface RefundChargeParams {
|
|
|
181
181
|
reason?: string;
|
|
182
182
|
idempotencyKey?: string;
|
|
183
183
|
}
|
|
184
|
+
interface ListChargesParams {
|
|
185
|
+
/** Page number (1-based). Default: 1. */
|
|
186
|
+
page?: number;
|
|
187
|
+
/** Items per page (1–100). Default: 20. */
|
|
188
|
+
limit?: number;
|
|
189
|
+
/** Filter by status (e.g. `paid`, `pending`). */
|
|
190
|
+
status?: string;
|
|
191
|
+
/** Search by customer name, email, or document. */
|
|
192
|
+
search?: string;
|
|
193
|
+
/** Filter by payment method (`pix`, `creditcard`, `boleto`). */
|
|
194
|
+
paymentMethod?: string;
|
|
195
|
+
}
|
|
196
|
+
interface PaginatedList<T> {
|
|
197
|
+
data: T[];
|
|
198
|
+
meta: {
|
|
199
|
+
page: number;
|
|
200
|
+
limit: number;
|
|
201
|
+
total: number;
|
|
202
|
+
totalPages: number;
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
type ChargeList = PaginatedList<Charge>;
|
|
206
|
+
interface CustomerRecord {
|
|
207
|
+
id: number;
|
|
208
|
+
name: string;
|
|
209
|
+
email: string;
|
|
210
|
+
document: string;
|
|
211
|
+
phone: string;
|
|
212
|
+
personType: string;
|
|
213
|
+
zipCode?: string | null;
|
|
214
|
+
street?: string | null;
|
|
215
|
+
number?: string | null;
|
|
216
|
+
complement?: string | null;
|
|
217
|
+
neighborhood?: string | null;
|
|
218
|
+
city?: string | null;
|
|
219
|
+
state?: string | null;
|
|
220
|
+
createdAt: string;
|
|
221
|
+
updatedAt: string;
|
|
222
|
+
[key: string]: unknown;
|
|
223
|
+
}
|
|
224
|
+
type CustomerList = PaginatedList<CustomerRecord>;
|
|
225
|
+
interface CreateCustomerParams {
|
|
226
|
+
name: string;
|
|
227
|
+
email: string;
|
|
228
|
+
/** CPF (11 digits) or CNPJ (14 digits), digits only. */
|
|
229
|
+
document: string;
|
|
230
|
+
/** 10 or 11 digits with area code. */
|
|
231
|
+
phone: string;
|
|
232
|
+
/** `fisica` or `juridica`. */
|
|
233
|
+
personType: 'fisica' | 'juridica';
|
|
234
|
+
zipCode?: string;
|
|
235
|
+
street?: string;
|
|
236
|
+
number?: string;
|
|
237
|
+
complement?: string;
|
|
238
|
+
neighborhood?: string;
|
|
239
|
+
city?: string;
|
|
240
|
+
/** 2-letter uppercase state code, e.g. `SP`. */
|
|
241
|
+
state?: string;
|
|
242
|
+
}
|
|
243
|
+
interface UpdateCustomerParams {
|
|
244
|
+
name?: string;
|
|
245
|
+
email?: string;
|
|
246
|
+
document?: string;
|
|
247
|
+
phone?: string;
|
|
248
|
+
personType?: 'fisica' | 'juridica';
|
|
249
|
+
zipCode?: string;
|
|
250
|
+
street?: string;
|
|
251
|
+
number?: string;
|
|
252
|
+
complement?: string;
|
|
253
|
+
neighborhood?: string;
|
|
254
|
+
city?: string;
|
|
255
|
+
state?: string;
|
|
256
|
+
}
|
|
257
|
+
interface ListCustomersParams {
|
|
258
|
+
page?: number;
|
|
259
|
+
limit?: number;
|
|
260
|
+
search?: string;
|
|
261
|
+
}
|
|
184
262
|
interface MetaFeatures {
|
|
185
263
|
subscriptions: boolean;
|
|
186
264
|
checkout_sessions: boolean;
|
|
@@ -233,7 +311,7 @@ declare class Charges {
|
|
|
233
311
|
* phone: '11987654321'
|
|
234
312
|
* }
|
|
235
313
|
* });
|
|
236
|
-
*
|
|
314
|
+
* // charge.id, charge.status
|
|
237
315
|
*
|
|
238
316
|
* @example
|
|
239
317
|
* // Credit card charge, 3 installments
|
|
@@ -251,6 +329,14 @@ declare class Charges {
|
|
|
251
329
|
* });
|
|
252
330
|
*/
|
|
253
331
|
create(params: CreateChargeParams): Promise<Charge>;
|
|
332
|
+
/**
|
|
333
|
+
* List charges for the authenticated seller, with pagination and filters.
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* const { data, meta } = await garu.charges.list({ status: 'paid', limit: 10 });
|
|
337
|
+
* // meta.total paid charges
|
|
338
|
+
*/
|
|
339
|
+
list(params?: ListChargesParams): Promise<ChargeList>;
|
|
254
340
|
/**
|
|
255
341
|
* Fetch a single charge by numeric ID.
|
|
256
342
|
*
|
|
@@ -274,6 +360,59 @@ declare class Charges {
|
|
|
274
360
|
private buildCreateBody;
|
|
275
361
|
}
|
|
276
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Customers — manage your customer base.
|
|
365
|
+
*
|
|
366
|
+
* Customers are scoped to the seller identified by the API key. The backend
|
|
367
|
+
* uses a junction table (`customer_seller_profile`) so the same person can
|
|
368
|
+
* exist across multiple sellers without duplication.
|
|
369
|
+
*/
|
|
370
|
+
declare class Customers {
|
|
371
|
+
private readonly http;
|
|
372
|
+
constructor(http: HttpClient);
|
|
373
|
+
/**
|
|
374
|
+
* Create a customer and link it to the current seller.
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* const customer = await garu.customers.create({
|
|
378
|
+
* name: 'Maria Silva',
|
|
379
|
+
* email: 'maria@exemplo.com.br',
|
|
380
|
+
* document: '12345678909',
|
|
381
|
+
* phone: '11987654321',
|
|
382
|
+
* personType: 'fisica'
|
|
383
|
+
* });
|
|
384
|
+
*/
|
|
385
|
+
create(params: CreateCustomerParams): Promise<CustomerRecord>;
|
|
386
|
+
/**
|
|
387
|
+
* List customers for the authenticated seller, with pagination and search.
|
|
388
|
+
*
|
|
389
|
+
* @example
|
|
390
|
+
* const { data, meta } = await garu.customers.list({ search: 'maria', limit: 10 });
|
|
391
|
+
*/
|
|
392
|
+
list(params?: ListCustomersParams): Promise<CustomerList>;
|
|
393
|
+
/**
|
|
394
|
+
* Fetch a single customer by numeric ID.
|
|
395
|
+
*
|
|
396
|
+
* @example
|
|
397
|
+
* const customer = await garu.customers.get(42);
|
|
398
|
+
*/
|
|
399
|
+
get(id: number): Promise<CustomerRecord>;
|
|
400
|
+
/**
|
|
401
|
+
* Update a customer's profile for the current seller.
|
|
402
|
+
*
|
|
403
|
+
* @example
|
|
404
|
+
* const updated = await garu.customers.update(42, { name: 'Maria Santos' });
|
|
405
|
+
*/
|
|
406
|
+
update(id: number, params: UpdateCustomerParams): Promise<CustomerRecord>;
|
|
407
|
+
/**
|
|
408
|
+
* Remove a customer from the current seller.
|
|
409
|
+
*
|
|
410
|
+
* @example
|
|
411
|
+
* await garu.customers.delete(42);
|
|
412
|
+
*/
|
|
413
|
+
delete(id: number): Promise<void>;
|
|
414
|
+
}
|
|
415
|
+
|
|
277
416
|
/**
|
|
278
417
|
* Meta — capability introspection.
|
|
279
418
|
*
|
|
@@ -331,6 +470,7 @@ interface GaruOptions {
|
|
|
331
470
|
*/
|
|
332
471
|
declare class Garu {
|
|
333
472
|
readonly charges: Charges;
|
|
473
|
+
readonly customers: Customers;
|
|
334
474
|
readonly meta: Meta;
|
|
335
475
|
/**
|
|
336
476
|
* Webhook helpers. Available both as an instance member and as a static —
|
|
@@ -390,4 +530,4 @@ declare class GaruServerError extends GaruAPIError {
|
|
|
390
530
|
constructor(message: string, status: number, requestId: string | null, body: unknown);
|
|
391
531
|
}
|
|
392
532
|
|
|
393
|
-
export { type CardInfo, type Charge, type ChargeStatus, type CreateChargeParams, type Customer, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type MetaFeatures, type MetaResponse, type PaymentMethod, type RefundChargeParams, type VerifiedWebhook, type VerifyWebhookParams, type WirePaymentMethodId, webhooks };
|
|
533
|
+
export { type CardInfo, type Charge, type ChargeList, type ChargeStatus, type CreateChargeParams, type CreateCustomerParams, type Customer, type CustomerList, type CustomerRecord, Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, type GaruErrorCode, GaruNotFoundError, type GaruOptions, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, type ListChargesParams, type ListCustomersParams, type MetaFeatures, type MetaResponse, type PaginatedList, type PaymentMethod, type RefundChargeParams, type UpdateCustomerParams, type VerifiedWebhook, type VerifyWebhookParams, type WirePaymentMethodId, webhooks };
|
package/dist/index.js
CHANGED
|
@@ -216,7 +216,7 @@ var Charges = class {
|
|
|
216
216
|
* phone: '11987654321'
|
|
217
217
|
* }
|
|
218
218
|
* });
|
|
219
|
-
*
|
|
219
|
+
* // charge.id, charge.status
|
|
220
220
|
*
|
|
221
221
|
* @example
|
|
222
222
|
* // Credit card charge, 3 installments
|
|
@@ -244,6 +244,28 @@ var Charges = class {
|
|
|
244
244
|
})
|
|
245
245
|
);
|
|
246
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* List charges for the authenticated seller, with pagination and filters.
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* const { data, meta } = await garu.charges.list({ status: 'paid', limit: 10 });
|
|
252
|
+
* // meta.total paid charges
|
|
253
|
+
*/
|
|
254
|
+
async list(params = {}) {
|
|
255
|
+
const query = {};
|
|
256
|
+
if (params.page !== void 0) query.page = String(params.page);
|
|
257
|
+
if (params.limit !== void 0) query.limit = String(params.limit);
|
|
258
|
+
if (params.status) query.status = params.status;
|
|
259
|
+
if (params.search) query.search = params.search;
|
|
260
|
+
if (params.paymentMethod) query.paymentMethod = params.paymentMethod;
|
|
261
|
+
const qs = new URLSearchParams(query).toString();
|
|
262
|
+
const url = `/api/transactions${qs ? `?${qs}` : ""}`;
|
|
263
|
+
return this.http.call(
|
|
264
|
+
(signal) => this.http.client.GET(url, { signal }).then(
|
|
265
|
+
(r) => r
|
|
266
|
+
)
|
|
267
|
+
);
|
|
268
|
+
}
|
|
247
269
|
/**
|
|
248
270
|
* Fetch a single charge by numeric ID.
|
|
249
271
|
*
|
|
@@ -302,6 +324,93 @@ var Charges = class {
|
|
|
302
324
|
}
|
|
303
325
|
};
|
|
304
326
|
|
|
327
|
+
// src/resources/customers.ts
|
|
328
|
+
var Customers = class {
|
|
329
|
+
constructor(http) {
|
|
330
|
+
this.http = http;
|
|
331
|
+
}
|
|
332
|
+
http;
|
|
333
|
+
/**
|
|
334
|
+
* Create a customer and link it to the current seller.
|
|
335
|
+
*
|
|
336
|
+
* @example
|
|
337
|
+
* const customer = await garu.customers.create({
|
|
338
|
+
* name: 'Maria Silva',
|
|
339
|
+
* email: 'maria@exemplo.com.br',
|
|
340
|
+
* document: '12345678909',
|
|
341
|
+
* phone: '11987654321',
|
|
342
|
+
* personType: 'fisica'
|
|
343
|
+
* });
|
|
344
|
+
*/
|
|
345
|
+
async create(params) {
|
|
346
|
+
return this.http.call(
|
|
347
|
+
(signal) => this.http.client.POST("/api/customers", {
|
|
348
|
+
body: params,
|
|
349
|
+
signal
|
|
350
|
+
}).then((r) => r)
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* List customers for the authenticated seller, with pagination and search.
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* const { data, meta } = await garu.customers.list({ search: 'maria', limit: 10 });
|
|
358
|
+
*/
|
|
359
|
+
async list(params = {}) {
|
|
360
|
+
const query = {};
|
|
361
|
+
if (params.page !== void 0) query.page = String(params.page);
|
|
362
|
+
if (params.limit !== void 0) query.limit = String(params.limit);
|
|
363
|
+
if (params.search) query.search = params.search;
|
|
364
|
+
const qs = new URLSearchParams(query).toString();
|
|
365
|
+
const url = `/api/customers${qs ? `?${qs}` : ""}`;
|
|
366
|
+
return this.http.call(
|
|
367
|
+
(signal) => this.http.client.GET(url, { signal }).then(
|
|
368
|
+
(r) => r
|
|
369
|
+
)
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Fetch a single customer by numeric ID.
|
|
374
|
+
*
|
|
375
|
+
* @example
|
|
376
|
+
* const customer = await garu.customers.get(42);
|
|
377
|
+
*/
|
|
378
|
+
async get(id) {
|
|
379
|
+
return this.http.call(
|
|
380
|
+
(signal) => this.http.client.GET(`/api/customers/${id}`, { signal }).then(
|
|
381
|
+
(r) => r
|
|
382
|
+
)
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Update a customer's profile for the current seller.
|
|
387
|
+
*
|
|
388
|
+
* @example
|
|
389
|
+
* const updated = await garu.customers.update(42, { name: 'Maria Santos' });
|
|
390
|
+
*/
|
|
391
|
+
async update(id, params) {
|
|
392
|
+
return this.http.call(
|
|
393
|
+
(signal) => this.http.client.PUT(`/api/customers/${id}`, {
|
|
394
|
+
body: params,
|
|
395
|
+
signal
|
|
396
|
+
}).then((r) => r)
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Remove a customer from the current seller.
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* await garu.customers.delete(42);
|
|
404
|
+
*/
|
|
405
|
+
async delete(id) {
|
|
406
|
+
await this.http.call(
|
|
407
|
+
(signal) => this.http.client.DELETE(`/api/customers/${id}`, { signal }).then(
|
|
408
|
+
(r) => r
|
|
409
|
+
)
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
|
|
305
414
|
// src/resources/meta.ts
|
|
306
415
|
var Meta = class {
|
|
307
416
|
constructor(http) {
|
|
@@ -381,9 +490,10 @@ function parseSignatureHeader(header) {
|
|
|
381
490
|
var DEFAULT_BASE_URL = "https://garu.com.br";
|
|
382
491
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
383
492
|
var DEFAULT_MAX_RETRIES = 2;
|
|
384
|
-
var SDK_VERSION = "0.
|
|
493
|
+
var SDK_VERSION = "0.2.0";
|
|
385
494
|
var Garu = class {
|
|
386
495
|
charges;
|
|
496
|
+
customers;
|
|
387
497
|
meta;
|
|
388
498
|
/**
|
|
389
499
|
* Webhook helpers. Available both as an instance member and as a static —
|
|
@@ -401,6 +511,7 @@ var Garu = class {
|
|
|
401
511
|
fetch: options.fetch
|
|
402
512
|
});
|
|
403
513
|
this.charges = new Charges(http);
|
|
514
|
+
this.customers = new Customers(http);
|
|
404
515
|
this.meta = new Meta(http);
|
|
405
516
|
}
|
|
406
517
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/idempotency.ts","../src/types.ts","../src/resources/charges.ts","../src/resources/meta.ts","../src/webhooks.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Error hierarchy for the Garu SDK.\n *\n * Every error has a stable `code` string so agents and typed clients can switch on it\n * without parsing messages. Non-2xx API responses are mapped to the most specific\n * subclass of `GaruAPIError` by {@link mapApiError}.\n */\n\nexport type GaruErrorCode =\n | 'authentication_error'\n | 'permission_error'\n | 'not_found'\n | 'validation_error'\n | 'rate_limited'\n | 'server_error'\n | 'api_error'\n | 'connection_error'\n | 'signature_verification_failed';\n\nexport class GaruError extends Error {\n public readonly code: GaruErrorCode;\n\n constructor(code: GaruErrorCode, message: string) {\n super(message);\n this.name = 'GaruError';\n this.code = code;\n }\n}\n\nexport class GaruConnectionError extends GaruError {\n public readonly connectionCause: unknown;\n constructor(message: string, connectionCause?: unknown) {\n super('connection_error', message);\n this.name = 'GaruConnectionError';\n this.connectionCause = connectionCause;\n }\n}\n\nexport class GaruSignatureVerificationError extends GaruError {\n constructor(message: string) {\n super('signature_verification_failed', message);\n this.name = 'GaruSignatureVerificationError';\n }\n}\n\nexport class GaruAPIError extends GaruError {\n public readonly status: number;\n public readonly requestId: string | null;\n public readonly body: unknown;\n\n constructor(\n code: GaruErrorCode,\n message: string,\n status: number,\n requestId: string | null,\n body: unknown\n ) {\n super(code, message);\n this.name = 'GaruAPIError';\n this.status = status;\n this.requestId = requestId;\n this.body = body;\n }\n}\n\nexport class GaruAuthenticationError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('authentication_error', message, status, requestId, body);\n this.name = 'GaruAuthenticationError';\n }\n}\n\nexport class GaruPermissionError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('permission_error', message, status, requestId, body);\n this.name = 'GaruPermissionError';\n }\n}\n\nexport class GaruNotFoundError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('not_found', message, status, requestId, body);\n this.name = 'GaruNotFoundError';\n }\n}\n\nexport class GaruValidationError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('validation_error', message, status, requestId, body);\n this.name = 'GaruValidationError';\n }\n}\n\nexport class GaruRateLimitError extends GaruAPIError {\n public readonly retryAfterSec: number | null;\n constructor(\n message: string,\n status: number,\n requestId: string | null,\n body: unknown,\n retryAfterSec: number | null\n ) {\n super('rate_limited', message, status, requestId, body);\n this.name = 'GaruRateLimitError';\n this.retryAfterSec = retryAfterSec;\n }\n}\n\nexport class GaruServerError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('server_error', message, status, requestId, body);\n this.name = 'GaruServerError';\n }\n}\n\n/**\n * Map a non-2xx HTTP response to the most specific {@link GaruAPIError} subclass.\n */\nexport function mapApiError(\n status: number,\n body: unknown,\n requestId: string | null,\n retryAfterSec: number | null\n): GaruAPIError {\n const message = extractMessage(body) ?? `Garu API returned HTTP ${status}`;\n\n if (status === 401) return new GaruAuthenticationError(message, status, requestId, body);\n if (status === 403) return new GaruPermissionError(message, status, requestId, body);\n if (status === 404) return new GaruNotFoundError(message, status, requestId, body);\n if (status === 400 || status === 422) {\n return new GaruValidationError(message, status, requestId, body);\n }\n if (status === 429) {\n return new GaruRateLimitError(message, status, requestId, body, retryAfterSec);\n }\n if (status >= 500) return new GaruServerError(message, status, requestId, body);\n return new GaruAPIError('api_error', message, status, requestId, body);\n}\n\nfunction extractMessage(body: unknown): string | null {\n if (typeof body === 'string') return body;\n if (body && typeof body === 'object') {\n const m = (body as { message?: unknown }).message;\n if (typeof m === 'string') return m;\n if (Array.isArray(m) && m.every((x) => typeof x === 'string')) return m.join('; ');\n }\n return null;\n}\n","import createClient from 'openapi-fetch';\n\nimport { GaruConnectionError, mapApiError, type GaruAPIError } from './errors.js';\nimport type { paths } from './generated/schema.js';\n\nexport interface HttpClientConfig {\n baseUrl: string;\n apiKey?: string;\n timeoutMs: number;\n maxRetries: number;\n userAgent: string;\n /** Injectable for tests. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n}\n\nconst RETRYABLE_STATUSES = new Set([408, 429, 500, 502, 503, 504]);\n\n/** Typed openapi-fetch client keyed to the backend's OpenAPI paths. */\nexport type GaruOpenapiClient = ReturnType<typeof createClient<paths>>;\n\n/** Arg type for `HttpClient.call` — a thunk that issues one openapi-fetch request. */\nexport type OpenapiCallResult<T> = Promise<{\n data?: T;\n error?: unknown;\n response: Response;\n}>;\n\n/**\n * HttpClient wraps the generated `openapi-fetch` client with:\n * - retries (exponential backoff, full jitter, honors `Retry-After`)\n * - typed error mapping (non-2xx → {@link GaruAPIError} subclass)\n * - connection error wrapping\n * - Authorization + User-Agent injection\n *\n * Resources call {@link call} with a thunk that returns an openapi-fetch\n * `{ data, error, response }` tuple; the wrapper either returns `data` or\n * throws the mapped error.\n */\nexport class HttpClient {\n public readonly client: GaruOpenapiClient;\n private readonly cfg: HttpClientConfig;\n\n constructor(cfg: HttpClientConfig) {\n this.cfg = cfg;\n const fetchImpl = cfg.fetch ?? globalThis.fetch;\n if (!fetchImpl) {\n throw new GaruConnectionError(\n 'No fetch implementation available. Node.js >= 18 is required.'\n );\n }\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'User-Agent': cfg.userAgent\n };\n if (cfg.apiKey) headers.Authorization = `Bearer ${cfg.apiKey}`;\n\n this.client = createClient<paths>({\n baseUrl: cfg.baseUrl.replace(/\\/+$/, ''),\n fetch: fetchImpl,\n headers\n });\n }\n\n /**\n * Issue one HTTP call against the typed client, with retries + error mapping.\n *\n * `fn` is invoked up to `maxRetries + 1` times. The timeout in `cfg.timeoutMs`\n * is enforced via `AbortController`.\n */\n async call<T>(fn: (signal: AbortSignal) => OpenapiCallResult<T>): Promise<T> {\n let lastError: GaruAPIError | GaruConnectionError | null = null;\n\n for (let attempt = 0; attempt <= this.cfg.maxRetries; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.cfg.timeoutMs);\n\n try {\n const { data, error, response } = await fn(controller.signal);\n clearTimeout(timer);\n\n if (response.ok) {\n return data as T;\n }\n\n const requestId = response.headers.get('x-request-id');\n const retryAfterSec = parseRetryAfter(response.headers.get('retry-after'));\n const apiError = mapApiError(response.status, error ?? null, requestId, retryAfterSec);\n lastError = apiError;\n\n if (!RETRYABLE_STATUSES.has(response.status) || attempt === this.cfg.maxRetries) {\n throw apiError;\n }\n\n await sleep(backoffDelay(attempt, retryAfterSec));\n continue;\n } catch (err) {\n clearTimeout(timer);\n\n if (isGaruApiError(err)) throw err;\n\n const connErr =\n err instanceof Error && err.name === 'AbortError'\n ? new GaruConnectionError(`Request timed out after ${this.cfg.timeoutMs}ms`, err)\n : new GaruConnectionError(err instanceof Error ? err.message : 'Network error', err);\n lastError = connErr;\n\n if (attempt === this.cfg.maxRetries) throw connErr;\n await sleep(backoffDelay(attempt, null));\n continue;\n }\n }\n\n // Unreachable — the loop always throws or returns on the final attempt.\n throw lastError ?? new GaruConnectionError('Request failed with no error captured');\n }\n}\n\nfunction isGaruApiError(err: unknown): boolean {\n return err instanceof Error && err.name.startsWith('Garu') && err.name.endsWith('Error');\n}\n\nfunction parseRetryAfter(value: string | null): number | null {\n if (!value) return null;\n const n = Number(value);\n return Number.isFinite(n) && n >= 0 ? n : null;\n}\n\n/**\n * Exponential backoff with full jitter. If the server returned `Retry-After`,\n * we honor it (with a small jitter).\n */\nfunction backoffDelay(attempt: number, retryAfterSec: number | null): number {\n if (retryAfterSec !== null) {\n return retryAfterSec * 1000 + Math.random() * 250;\n }\n const base = 500 * 2 ** attempt;\n const cap = 8000;\n return Math.min(cap, base) * Math.random();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { randomUUID } from 'node:crypto';\n\n/**\n * Generate a UUIDv4 suitable for use as an `X-Idempotency-Key` header value.\n *\n * @example\n * const key = generateIdempotencyKey();\n * // '3b241101-e2bb-4255-8caf-4136c566a962'\n */\nexport function generateIdempotencyKey(): string {\n return randomUUID();\n}\n","/**\n * Public types for the Garu SDK.\n *\n * The wire-level types (`WireCreateTransactionRequest`, `WireMetaResponse`, ...)\n * are generated from the backend's OpenAPI spec and live in\n * `src/generated/schema.d.ts`. The friendly types in this file\n * (`CreateChargeParams`, `Customer`, `Charge`, ...) are hand-curated for\n * ergonomics — they rename `transactions` to `charges`, collapse wire enums\n * into readable unions, and mark only truly required fields as required.\n * The resource layer maps friendly → wire at the edge.\n */\n\nimport type { components } from './generated/schema.js';\n\nexport type WireCreateTransactionRequest = components['schemas']['CreateTransactionRequest'];\nexport type WireCustomerDto = components['schemas']['CustomerDto'];\nexport type WireCardInfoDto = components['schemas']['CardInfoDto'];\nexport type WireMetaResponse = components['schemas']['MetaResponse'];\n\nexport type PaymentMethod = 'pix' | 'credit_card' | 'boleto';\n\n/** Payment-method identifier as sent to the backend over the wire. */\nexport type WirePaymentMethodId = 'pix' | 'creditcard' | 'boleto';\n\nexport type ChargeStatus =\n | 'pending'\n | 'authorized'\n | 'paid'\n | 'failed'\n | 'refunded'\n | 'cancelled'\n | 'expired';\n\nexport interface Customer {\n /** Full legal name. 3–255 chars. */\n name: string;\n email: string;\n /** CPF (11 digits) or CNPJ (14 digits), digits only. */\n document: string;\n /** 10 or 11 digits with area code, no formatting. */\n phone: string;\n /** 8 digits, no hyphen. Optional. */\n zipCode?: string;\n street?: string;\n number?: string;\n complement?: string;\n neighborhood?: string;\n city?: string;\n /** 2-letter uppercase state code, e.g. `SP`. */\n state?: string;\n}\n\nexport interface CardInfo {\n /** 13–19 digits, no spaces or hyphens. */\n cardNumber: string;\n /** 3 or 4 digits. */\n cvv: string;\n /** `YYYY-MM`. */\n expirationDate: string;\n /** As printed on the card. */\n holderName: string;\n /** 1–12. */\n installments: number;\n}\n\nexport interface CreateChargeParams {\n /** Customer buying the product. */\n customer: Customer;\n /** UUID of the product being charged. */\n productId: string;\n /** Payment method. */\n paymentMethod: PaymentMethod;\n /** Required when `paymentMethod` is `credit_card`. */\n cardInfo?: CardInfo;\n /** Free-form metadata attached to the charge. */\n additionalInfo?: string;\n /** Original checkout link, if any. */\n link?: string | null;\n /** Associated affiliate ID, if any. */\n affiliateId?: number | null;\n /** Subscription price ID (`price_*`), for subscription charges only. */\n priceId?: string | null;\n /** Optional pre-created checkout session token. */\n checkoutSessionToken?: string;\n /**\n * Idempotency key. If omitted, the SDK generates a UUIDv4.\n * Keys are valid for 24h on the backend.\n */\n idempotencyKey?: string;\n}\n\nexport interface Charge {\n id: number;\n status: ChargeStatus;\n amount: number;\n paymentMethodId: WirePaymentMethodId;\n /** ISO-8601. */\n date: string;\n /** ISO-8601. */\n deadline?: string;\n /** Product this charge belongs to. */\n product?: { id: number; uuid?: string; name?: string };\n [key: string]: unknown;\n}\n\nexport interface RefundChargeParams {\n /** Partial refund in centavos. Omit for full refund. */\n amount?: number;\n /** Free-form reason stored on the refund. */\n reason?: string;\n idempotencyKey?: string;\n}\n\nexport interface MetaFeatures {\n subscriptions: boolean;\n checkout_sessions: boolean;\n idempotency_keys: boolean;\n test_mode: boolean;\n webhooks: boolean;\n}\n\nexport interface MetaResponse {\n name: string;\n version: string;\n environment: 'production' | 'staging' | 'development' | string;\n api_version: string;\n payment_methods: string[];\n currencies: string[];\n billing_intervals: string[];\n webhook_events: string[];\n features: MetaFeatures;\n docs_url: string;\n dashboard_url: string;\n support_email: string;\n}\n\n/** Map the SDK's friendly `PaymentMethod` to the backend's wire value. */\nexport function toWirePaymentMethod(pm: PaymentMethod): WirePaymentMethodId {\n return pm === 'credit_card' ? 'creditcard' : pm;\n}\n","import type { HttpClient } from '../http.js';\nimport type { components } from '../generated/schema.js';\nimport { generateIdempotencyKey } from '../idempotency.js';\nimport {\n toWirePaymentMethod,\n type Charge,\n type CreateChargeParams,\n type RefundChargeParams\n} from '../types.js';\n\ntype CreateTransactionBody = components['schemas']['CreateTransactionRequest'];\n\n/**\n * Charges — the core of the Garu API.\n *\n * A charge represents a single payment attempt against a product. The SDK\n * surfaces charges under `garu.charges` even though the backend route is\n * `/api/transactions` — this matches Stripe convention and is the name every\n * other Garu surface (MCP, CLI, docs) uses.\n */\nexport class Charges {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a charge (PIX, credit card, or boleto).\n *\n * Automatically attaches an `X-Idempotency-Key` header — if you don't pass\n * `idempotencyKey`, the SDK generates a UUIDv4. Safe to retry: the backend\n * caches the first response for 24h.\n *\n * @example\n * // PIX charge\n * const charge = await garu.charges.create({\n * productId: 'b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f',\n * paymentMethod: 'pix',\n * customer: {\n * name: 'Maria Silva',\n * email: 'maria@exemplo.com.br',\n * document: '12345678909',\n * phone: '11987654321'\n * }\n * });\n * console.log(charge.id, charge.status);\n *\n * @example\n * // Credit card charge, 3 installments\n * const charge = await garu.charges.create({\n * productId: 'b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f',\n * paymentMethod: 'credit_card',\n * customer: { name: 'Maria Silva', email: 'maria@exemplo.com.br', document: '12345678909', phone: '11987654321' },\n * cardInfo: {\n * cardNumber: '4111111111111111',\n * cvv: '123',\n * expirationDate: '2030-12',\n * holderName: 'MARIA SILVA',\n * installments: 3\n * }\n * });\n */\n async create(params: CreateChargeParams): Promise<Charge> {\n const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();\n const body = this.buildCreateBody(params);\n\n return this.http.call<Charge>(\n (signal) =>\n this.http.client.POST('/api/transactions', {\n body,\n headers: { 'X-Idempotency-Key': idempotencyKey },\n signal\n }) as Promise<{ data?: Charge; error?: unknown; response: Response }>\n );\n }\n\n /**\n * Fetch a single charge by numeric ID.\n *\n * @example\n * const charge = await garu.charges.get(4472);\n * if (charge.status === 'paid') { ... }\n */\n async get(id: number): Promise<Charge> {\n return this.http.call<Charge>(\n (signal) =>\n this.http.client.GET('/api/transactions/{id}', {\n params: { path: { id } },\n signal\n }) as Promise<{ data?: Charge; error?: unknown; response: Response }>\n );\n }\n\n /**\n * Refund a charge — fully, or partially by passing `amount` in centavos.\n *\n * @example\n * // Full refund\n * await garu.charges.refund(4472);\n *\n * @example\n * // Partial refund of R$ 10,00\n * await garu.charges.refund(4472, { amount: 1000, reason: 'customer_request' });\n */\n async refund(id: number, params: RefundChargeParams = {}): Promise<Charge> {\n const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();\n const body: Record<string, unknown> = {};\n if (params.amount !== undefined) body.amount = params.amount;\n if (params.reason !== undefined) body.reason = params.reason;\n\n return this.http.call<Charge>(\n (signal) =>\n this.http.client.POST('/api/transactions/{id}/refund', {\n params: { path: { id } },\n body: body as never,\n headers: { 'X-Idempotency-Key': idempotencyKey },\n signal\n }) as Promise<{ data?: Charge; error?: unknown; response: Response }>\n );\n }\n\n private buildCreateBody(params: CreateChargeParams): CreateTransactionBody {\n const body: Record<string, unknown> = {\n customer: params.customer,\n productId: params.productId,\n paymentMethodId: toWirePaymentMethod(params.paymentMethod),\n link: params.link ?? null,\n affiliateId: params.affiliateId ?? null\n };\n if (params.additionalInfo !== undefined) body.additionalInfo = params.additionalInfo;\n if (params.priceId !== undefined) body.priceId = params.priceId;\n if (params.checkoutSessionToken !== undefined) {\n body.checkoutSessionToken = params.checkoutSessionToken;\n }\n if (params.cardInfo) body.CardInfo = params.cardInfo;\n return body as unknown as CreateTransactionBody;\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { MetaResponse } from '../types.js';\n\n/**\n * Meta — capability introspection.\n *\n * Unauthenticated. Used by `garu doctor`, MCP tool `doctor`, and by SDK\n * consumers that want to know which payment methods and webhook events are\n * currently supported.\n */\nexport class Meta {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Fetch the API's current capability payload.\n *\n * @example\n * const meta = await garu.meta.get();\n * console.log(meta.version, meta.payment_methods);\n * if (meta.features.subscriptions) { ... }\n */\n async get(): Promise<MetaResponse> {\n return this.http.call<MetaResponse>(\n (signal) =>\n this.http.client.GET('/api/meta', { signal }) as Promise<{\n data?: MetaResponse;\n error?: unknown;\n response: Response;\n }>\n );\n }\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto';\n\nimport { GaruSignatureVerificationError } from './errors.js';\n\nexport interface VerifyWebhookParams {\n /** Raw request body as received — do NOT re-serialize parsed JSON. */\n payload: string | Buffer;\n /** Value of the `X-Garu-Signature` header. Format: `t=<ts>,v1=<hex>`. */\n signature: string;\n /** The webhook endpoint's signing secret. */\n secret: string;\n /** Reject signatures older than this many seconds. Default: 300 (5 min). */\n toleranceSec?: number;\n /** Injectable for tests. Defaults to `Date.now()`. */\n now?: () => number;\n}\n\nexport interface VerifiedWebhook {\n /** Timestamp from the signature header, in seconds since epoch. */\n timestamp: number;\n /** Parsed JSON body. Throws {@link GaruSignatureVerificationError} if invalid JSON. */\n event: unknown;\n}\n\n/**\n * Webhook helpers.\n *\n * Garu signs outgoing webhooks with HMAC-SHA256 over `${timestamp}.${payload}`\n * and delivers the signature in the `X-Garu-Signature` header as `t=<ts>,v1=<hex>`.\n * This matches the format in the backend's `webhook-delivery.service.ts`.\n *\n * @example\n * // Express example\n * app.post('/webhooks/garu', express.raw({ type: 'application/json' }), (req, res) => {\n * try {\n * const { event } = Garu.webhooks.verify({\n * payload: req.body,\n * signature: req.header('x-garu-signature') ?? '',\n * secret: process.env.GARU_WEBHOOK_SECRET!\n * });\n * // handle event\n * res.sendStatus(200);\n * } catch (err) {\n * res.sendStatus(400);\n * }\n * });\n */\nexport const webhooks = {\n verify(params: VerifyWebhookParams): VerifiedWebhook {\n const { signature, secret, payload } = params;\n const toleranceSec = params.toleranceSec ?? 300;\n const now = params.now ?? Date.now;\n\n if (!signature || typeof signature !== 'string') {\n throw new GaruSignatureVerificationError('Missing or malformed X-Garu-Signature header');\n }\n\n const parts = parseSignatureHeader(signature);\n if (parts === null) {\n throw new GaruSignatureVerificationError(\n 'X-Garu-Signature header does not match expected format t=<ts>,v1=<hex>'\n );\n }\n\n const payloadStr = typeof payload === 'string' ? payload : payload.toString('utf8');\n const signedPayload = `${parts.timestamp}.${payloadStr}`;\n const expected = createHmac('sha256', secret).update(signedPayload).digest('hex');\n\n const expectedBuf = Buffer.from(expected, 'hex');\n const providedBuf = Buffer.from(parts.v1, 'hex');\n if (expectedBuf.length !== providedBuf.length || !timingSafeEqual(expectedBuf, providedBuf)) {\n throw new GaruSignatureVerificationError('Signature does not match computed HMAC');\n }\n\n const nowSec = Math.floor(now() / 1000);\n if (Math.abs(nowSec - parts.timestamp) > toleranceSec) {\n throw new GaruSignatureVerificationError(\n `Signature timestamp outside tolerance window (${toleranceSec}s)`\n );\n }\n\n let event: unknown;\n try {\n event = JSON.parse(payloadStr);\n } catch {\n throw new GaruSignatureVerificationError('Webhook payload is not valid JSON');\n }\n\n return { timestamp: parts.timestamp, event };\n }\n};\n\nfunction parseSignatureHeader(header: string): { timestamp: number; v1: string } | null {\n const fields: Record<string, string> = {};\n for (const part of header.split(',')) {\n const idx = part.indexOf('=');\n if (idx === -1) return null;\n const key = part.slice(0, idx).trim();\n const value = part.slice(idx + 1).trim();\n if (!key || !value) return null;\n fields[key] = value;\n }\n const t = fields.t;\n const v1 = fields.v1;\n if (!t || !v1) return null;\n const timestamp = Number(t);\n if (!Number.isFinite(timestamp) || !/^[a-f0-9]+$/i.test(v1)) return null;\n return { timestamp, v1 };\n}\n","import { HttpClient } from './http.js';\nimport { Charges } from './resources/charges.js';\nimport { Meta } from './resources/meta.js';\nimport { webhooks } from './webhooks.js';\n\nexport interface GaruOptions {\n /**\n * Your Garu API key. `sk_live_…` for production, `sk_test_…` for test mode.\n * Optional — public endpoints (`meta.get`, public charge creation) work without one.\n */\n apiKey?: string;\n /** Override the API base URL. Default: `https://garu.com.br/api`. */\n baseUrl?: string;\n /** Per-request timeout in ms. Default: 30000. */\n timeoutMs?: number;\n /** Max retries on retryable errors (connection, 408, 429, 5xx). Default: 2. */\n maxRetries?: number;\n /** Injectable for tests. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n}\n\nconst DEFAULT_BASE_URL = 'https://garu.com.br';\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst SDK_VERSION = '0.1.0';\n\n/**\n * The Garu SDK client.\n *\n * @example\n * import { Garu } from '@garuhq/node';\n *\n * const garu = new Garu({ apiKey: process.env.GARU_API_KEY });\n *\n * const charge = await garu.charges.create({\n * productId: 'b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f',\n * paymentMethod: 'pix',\n * customer: {\n * name: 'Maria Silva',\n * email: 'maria@exemplo.com.br',\n * document: '12345678909',\n * phone: '11987654321'\n * }\n * });\n */\nexport class Garu {\n public readonly charges: Charges;\n public readonly meta: Meta;\n\n /**\n * Webhook helpers. Available both as an instance member and as a static —\n * `Garu.webhooks.verify(...)` works without constructing a client.\n */\n public static readonly webhooks = webhooks;\n public readonly webhooks = webhooks;\n\n constructor(options: GaruOptions = {}) {\n const http = new HttpClient({\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n apiKey: options.apiKey,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxRetries: options.maxRetries ?? DEFAULT_MAX_RETRIES,\n userAgent: `garu-node/${SDK_VERSION}`,\n fetch: options.fetch\n });\n this.charges = new Charges(http);\n this.meta = new Meta(http);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/idempotency.ts","../src/types.ts","../src/resources/charges.ts","../src/resources/customers.ts","../src/resources/meta.ts","../src/webhooks.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Error hierarchy for the Garu SDK.\n *\n * Every error has a stable `code` string so agents and typed clients can switch on it\n * without parsing messages. Non-2xx API responses are mapped to the most specific\n * subclass of `GaruAPIError` by {@link mapApiError}.\n */\n\nexport type GaruErrorCode =\n | 'authentication_error'\n | 'permission_error'\n | 'not_found'\n | 'validation_error'\n | 'rate_limited'\n | 'server_error'\n | 'api_error'\n | 'connection_error'\n | 'signature_verification_failed';\n\nexport class GaruError extends Error {\n public readonly code: GaruErrorCode;\n\n constructor(code: GaruErrorCode, message: string) {\n super(message);\n this.name = 'GaruError';\n this.code = code;\n }\n}\n\nexport class GaruConnectionError extends GaruError {\n public readonly connectionCause: unknown;\n constructor(message: string, connectionCause?: unknown) {\n super('connection_error', message);\n this.name = 'GaruConnectionError';\n this.connectionCause = connectionCause;\n }\n}\n\nexport class GaruSignatureVerificationError extends GaruError {\n constructor(message: string) {\n super('signature_verification_failed', message);\n this.name = 'GaruSignatureVerificationError';\n }\n}\n\nexport class GaruAPIError extends GaruError {\n public readonly status: number;\n public readonly requestId: string | null;\n public readonly body: unknown;\n\n constructor(\n code: GaruErrorCode,\n message: string,\n status: number,\n requestId: string | null,\n body: unknown\n ) {\n super(code, message);\n this.name = 'GaruAPIError';\n this.status = status;\n this.requestId = requestId;\n this.body = body;\n }\n}\n\nexport class GaruAuthenticationError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('authentication_error', message, status, requestId, body);\n this.name = 'GaruAuthenticationError';\n }\n}\n\nexport class GaruPermissionError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('permission_error', message, status, requestId, body);\n this.name = 'GaruPermissionError';\n }\n}\n\nexport class GaruNotFoundError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('not_found', message, status, requestId, body);\n this.name = 'GaruNotFoundError';\n }\n}\n\nexport class GaruValidationError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('validation_error', message, status, requestId, body);\n this.name = 'GaruValidationError';\n }\n}\n\nexport class GaruRateLimitError extends GaruAPIError {\n public readonly retryAfterSec: number | null;\n constructor(\n message: string,\n status: number,\n requestId: string | null,\n body: unknown,\n retryAfterSec: number | null\n ) {\n super('rate_limited', message, status, requestId, body);\n this.name = 'GaruRateLimitError';\n this.retryAfterSec = retryAfterSec;\n }\n}\n\nexport class GaruServerError extends GaruAPIError {\n constructor(message: string, status: number, requestId: string | null, body: unknown) {\n super('server_error', message, status, requestId, body);\n this.name = 'GaruServerError';\n }\n}\n\n/**\n * Map a non-2xx HTTP response to the most specific {@link GaruAPIError} subclass.\n */\nexport function mapApiError(\n status: number,\n body: unknown,\n requestId: string | null,\n retryAfterSec: number | null\n): GaruAPIError {\n const message = extractMessage(body) ?? `Garu API returned HTTP ${status}`;\n\n if (status === 401) return new GaruAuthenticationError(message, status, requestId, body);\n if (status === 403) return new GaruPermissionError(message, status, requestId, body);\n if (status === 404) return new GaruNotFoundError(message, status, requestId, body);\n if (status === 400 || status === 422) {\n return new GaruValidationError(message, status, requestId, body);\n }\n if (status === 429) {\n return new GaruRateLimitError(message, status, requestId, body, retryAfterSec);\n }\n if (status >= 500) return new GaruServerError(message, status, requestId, body);\n return new GaruAPIError('api_error', message, status, requestId, body);\n}\n\nfunction extractMessage(body: unknown): string | null {\n if (typeof body === 'string') return body;\n if (body && typeof body === 'object') {\n const m = (body as { message?: unknown }).message;\n if (typeof m === 'string') return m;\n if (Array.isArray(m) && m.every((x) => typeof x === 'string')) return m.join('; ');\n }\n return null;\n}\n","import createClient from 'openapi-fetch';\n\nimport { GaruConnectionError, mapApiError, type GaruAPIError } from './errors.js';\nimport type { paths } from './generated/schema.js';\n\nexport interface HttpClientConfig {\n baseUrl: string;\n apiKey?: string;\n timeoutMs: number;\n maxRetries: number;\n userAgent: string;\n /** Injectable for tests. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n}\n\nconst RETRYABLE_STATUSES = new Set([408, 429, 500, 502, 503, 504]);\n\n/** Typed openapi-fetch client keyed to the backend's OpenAPI paths. */\nexport type GaruOpenapiClient = ReturnType<typeof createClient<paths>>;\n\n/** Arg type for `HttpClient.call` — a thunk that issues one openapi-fetch request. */\nexport type OpenapiCallResult<T> = Promise<{\n data?: T;\n error?: unknown;\n response: Response;\n}>;\n\n/**\n * HttpClient wraps the generated `openapi-fetch` client with:\n * - retries (exponential backoff, full jitter, honors `Retry-After`)\n * - typed error mapping (non-2xx → {@link GaruAPIError} subclass)\n * - connection error wrapping\n * - Authorization + User-Agent injection\n *\n * Resources call {@link call} with a thunk that returns an openapi-fetch\n * `{ data, error, response }` tuple; the wrapper either returns `data` or\n * throws the mapped error.\n */\nexport class HttpClient {\n public readonly client: GaruOpenapiClient;\n private readonly cfg: HttpClientConfig;\n\n constructor(cfg: HttpClientConfig) {\n this.cfg = cfg;\n const fetchImpl = cfg.fetch ?? globalThis.fetch;\n if (!fetchImpl) {\n throw new GaruConnectionError(\n 'No fetch implementation available. Node.js >= 18 is required.'\n );\n }\n const headers: Record<string, string> = {\n Accept: 'application/json',\n 'User-Agent': cfg.userAgent\n };\n if (cfg.apiKey) headers.Authorization = `Bearer ${cfg.apiKey}`;\n\n this.client = createClient<paths>({\n baseUrl: cfg.baseUrl.replace(/\\/+$/, ''),\n fetch: fetchImpl,\n headers\n });\n }\n\n /**\n * Issue one HTTP call against the typed client, with retries + error mapping.\n *\n * `fn` is invoked up to `maxRetries + 1` times. The timeout in `cfg.timeoutMs`\n * is enforced via `AbortController`.\n */\n async call<T>(fn: (signal: AbortSignal) => OpenapiCallResult<T>): Promise<T> {\n let lastError: GaruAPIError | GaruConnectionError | null = null;\n\n for (let attempt = 0; attempt <= this.cfg.maxRetries; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.cfg.timeoutMs);\n\n try {\n const { data, error, response } = await fn(controller.signal);\n clearTimeout(timer);\n\n if (response.ok) {\n return data as T;\n }\n\n const requestId = response.headers.get('x-request-id');\n const retryAfterSec = parseRetryAfter(response.headers.get('retry-after'));\n const apiError = mapApiError(response.status, error ?? null, requestId, retryAfterSec);\n lastError = apiError;\n\n if (!RETRYABLE_STATUSES.has(response.status) || attempt === this.cfg.maxRetries) {\n throw apiError;\n }\n\n await sleep(backoffDelay(attempt, retryAfterSec));\n continue;\n } catch (err) {\n clearTimeout(timer);\n\n if (isGaruApiError(err)) throw err;\n\n const connErr =\n err instanceof Error && err.name === 'AbortError'\n ? new GaruConnectionError(`Request timed out after ${this.cfg.timeoutMs}ms`, err)\n : new GaruConnectionError(err instanceof Error ? err.message : 'Network error', err);\n lastError = connErr;\n\n if (attempt === this.cfg.maxRetries) throw connErr;\n await sleep(backoffDelay(attempt, null));\n continue;\n }\n }\n\n // Unreachable — the loop always throws or returns on the final attempt.\n throw lastError ?? new GaruConnectionError('Request failed with no error captured');\n }\n}\n\nfunction isGaruApiError(err: unknown): boolean {\n return err instanceof Error && err.name.startsWith('Garu') && err.name.endsWith('Error');\n}\n\nfunction parseRetryAfter(value: string | null): number | null {\n if (!value) return null;\n const n = Number(value);\n return Number.isFinite(n) && n >= 0 ? n : null;\n}\n\n/**\n * Exponential backoff with full jitter. If the server returned `Retry-After`,\n * we honor it (with a small jitter).\n */\nfunction backoffDelay(attempt: number, retryAfterSec: number | null): number {\n if (retryAfterSec !== null) {\n return retryAfterSec * 1000 + Math.random() * 250;\n }\n const base = 500 * 2 ** attempt;\n const cap = 8000;\n return Math.min(cap, base) * Math.random();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { randomUUID } from 'node:crypto';\n\n/**\n * Generate a UUIDv4 suitable for use as an `X-Idempotency-Key` header value.\n *\n * @example\n * const key = generateIdempotencyKey();\n * // '3b241101-e2bb-4255-8caf-4136c566a962'\n */\nexport function generateIdempotencyKey(): string {\n return randomUUID();\n}\n","/**\n * Public types for the Garu SDK.\n *\n * The wire-level types (`WireCreateTransactionRequest`, `WireMetaResponse`, ...)\n * are generated from the backend's OpenAPI spec and live in\n * `src/generated/schema.d.ts`. The friendly types in this file\n * (`CreateChargeParams`, `Customer`, `Charge`, ...) are hand-curated for\n * ergonomics — they rename `transactions` to `charges`, collapse wire enums\n * into readable unions, and mark only truly required fields as required.\n * The resource layer maps friendly → wire at the edge.\n */\n\nimport type { components } from './generated/schema.js';\n\nexport type WireCreateTransactionRequest = components['schemas']['CreateTransactionRequest'];\nexport type WireCustomerDto = components['schemas']['CustomerDto'];\nexport type WireCardInfoDto = components['schemas']['CardInfoDto'];\nexport type WireMetaResponse = components['schemas']['MetaResponse'];\n\nexport type PaymentMethod = 'pix' | 'credit_card' | 'boleto';\n\n/** Payment-method identifier as sent to the backend over the wire. */\nexport type WirePaymentMethodId = 'pix' | 'creditcard' | 'boleto';\n\nexport type ChargeStatus =\n | 'pending'\n | 'authorized'\n | 'paid'\n | 'failed'\n | 'refunded'\n | 'cancelled'\n | 'expired';\n\nexport interface Customer {\n /** Full legal name. 3–255 chars. */\n name: string;\n email: string;\n /** CPF (11 digits) or CNPJ (14 digits), digits only. */\n document: string;\n /** 10 or 11 digits with area code, no formatting. */\n phone: string;\n /** 8 digits, no hyphen. Optional. */\n zipCode?: string;\n street?: string;\n number?: string;\n complement?: string;\n neighborhood?: string;\n city?: string;\n /** 2-letter uppercase state code, e.g. `SP`. */\n state?: string;\n}\n\nexport interface CardInfo {\n /** 13–19 digits, no spaces or hyphens. */\n cardNumber: string;\n /** 3 or 4 digits. */\n cvv: string;\n /** `YYYY-MM`. */\n expirationDate: string;\n /** As printed on the card. */\n holderName: string;\n /** 1–12. */\n installments: number;\n}\n\nexport interface CreateChargeParams {\n /** Customer buying the product. */\n customer: Customer;\n /** UUID of the product being charged. */\n productId: string;\n /** Payment method. */\n paymentMethod: PaymentMethod;\n /** Required when `paymentMethod` is `credit_card`. */\n cardInfo?: CardInfo;\n /** Free-form metadata attached to the charge. */\n additionalInfo?: string;\n /** Original checkout link, if any. */\n link?: string | null;\n /** Associated affiliate ID, if any. */\n affiliateId?: number | null;\n /** Subscription price ID (`price_*`), for subscription charges only. */\n priceId?: string | null;\n /** Optional pre-created checkout session token. */\n checkoutSessionToken?: string;\n /**\n * Idempotency key. If omitted, the SDK generates a UUIDv4.\n * Keys are valid for 24h on the backend.\n */\n idempotencyKey?: string;\n}\n\nexport interface Charge {\n id: number;\n status: ChargeStatus;\n amount: number;\n paymentMethodId: WirePaymentMethodId;\n /** ISO-8601. */\n date: string;\n /** ISO-8601. */\n deadline?: string;\n /** Product this charge belongs to. */\n product?: { id: number; uuid?: string; name?: string };\n [key: string]: unknown;\n}\n\nexport interface RefundChargeParams {\n /** Partial refund in centavos. Omit for full refund. */\n amount?: number;\n /** Free-form reason stored on the refund. */\n reason?: string;\n idempotencyKey?: string;\n}\n\nexport interface ListChargesParams {\n /** Page number (1-based). Default: 1. */\n page?: number;\n /** Items per page (1–100). Default: 20. */\n limit?: number;\n /** Filter by status (e.g. `paid`, `pending`). */\n status?: string;\n /** Search by customer name, email, or document. */\n search?: string;\n /** Filter by payment method (`pix`, `creditcard`, `boleto`). */\n paymentMethod?: string;\n}\n\nexport interface PaginatedList<T> {\n data: T[];\n meta: {\n page: number;\n limit: number;\n total: number;\n totalPages: number;\n };\n}\n\nexport type ChargeList = PaginatedList<Charge>;\n\nexport interface CustomerRecord {\n id: number;\n name: string;\n email: string;\n document: string;\n phone: string;\n personType: string;\n zipCode?: string | null;\n street?: string | null;\n number?: string | null;\n complement?: string | null;\n neighborhood?: string | null;\n city?: string | null;\n state?: string | null;\n createdAt: string;\n updatedAt: string;\n [key: string]: unknown;\n}\n\nexport type CustomerList = PaginatedList<CustomerRecord>;\n\nexport interface CreateCustomerParams {\n name: string;\n email: string;\n /** CPF (11 digits) or CNPJ (14 digits), digits only. */\n document: string;\n /** 10 or 11 digits with area code. */\n phone: string;\n /** `fisica` or `juridica`. */\n personType: 'fisica' | 'juridica';\n zipCode?: string;\n street?: string;\n number?: string;\n complement?: string;\n neighborhood?: string;\n city?: string;\n /** 2-letter uppercase state code, e.g. `SP`. */\n state?: string;\n}\n\nexport interface UpdateCustomerParams {\n name?: string;\n email?: string;\n document?: string;\n phone?: string;\n personType?: 'fisica' | 'juridica';\n zipCode?: string;\n street?: string;\n number?: string;\n complement?: string;\n neighborhood?: string;\n city?: string;\n state?: string;\n}\n\nexport interface ListCustomersParams {\n page?: number;\n limit?: number;\n search?: string;\n}\n\nexport interface MetaFeatures {\n subscriptions: boolean;\n checkout_sessions: boolean;\n idempotency_keys: boolean;\n test_mode: boolean;\n webhooks: boolean;\n}\n\nexport interface MetaResponse {\n name: string;\n version: string;\n environment: 'production' | 'staging' | 'development' | string;\n api_version: string;\n payment_methods: string[];\n currencies: string[];\n billing_intervals: string[];\n webhook_events: string[];\n features: MetaFeatures;\n docs_url: string;\n dashboard_url: string;\n support_email: string;\n}\n\n/** Map the SDK's friendly `PaymentMethod` to the backend's wire value. */\nexport function toWirePaymentMethod(pm: PaymentMethod): WirePaymentMethodId {\n return pm === 'credit_card' ? 'creditcard' : pm;\n}\n","import type { HttpClient } from '../http.js';\nimport type { components } from '../generated/schema.js';\nimport { generateIdempotencyKey } from '../idempotency.js';\nimport {\n toWirePaymentMethod,\n type Charge,\n type ChargeList,\n type CreateChargeParams,\n type ListChargesParams,\n type RefundChargeParams\n} from '../types.js';\n\ntype CreateTransactionBody = components['schemas']['CreateTransactionRequest'];\n\n/**\n * Charges — the core of the Garu API.\n *\n * A charge represents a single payment attempt against a product. The SDK\n * surfaces charges under `garu.charges` even though the backend route is\n * `/api/transactions` — this matches Stripe convention and is the name every\n * other Garu surface (MCP, CLI, docs) uses.\n */\nexport class Charges {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a charge (PIX, credit card, or boleto).\n *\n * Automatically attaches an `X-Idempotency-Key` header — if you don't pass\n * `idempotencyKey`, the SDK generates a UUIDv4. Safe to retry: the backend\n * caches the first response for 24h.\n *\n * @example\n * // PIX charge\n * const charge = await garu.charges.create({\n * productId: 'b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f',\n * paymentMethod: 'pix',\n * customer: {\n * name: 'Maria Silva',\n * email: 'maria@exemplo.com.br',\n * document: '12345678909',\n * phone: '11987654321'\n * }\n * });\n * // charge.id, charge.status\n *\n * @example\n * // Credit card charge, 3 installments\n * const charge = await garu.charges.create({\n * productId: 'b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f',\n * paymentMethod: 'credit_card',\n * customer: { name: 'Maria Silva', email: 'maria@exemplo.com.br', document: '12345678909', phone: '11987654321' },\n * cardInfo: {\n * cardNumber: '4111111111111111',\n * cvv: '123',\n * expirationDate: '2030-12',\n * holderName: 'MARIA SILVA',\n * installments: 3\n * }\n * });\n */\n async create(params: CreateChargeParams): Promise<Charge> {\n const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();\n const body = this.buildCreateBody(params);\n\n return this.http.call<Charge>(\n (signal) =>\n this.http.client.POST('/api/transactions', {\n body,\n headers: { 'X-Idempotency-Key': idempotencyKey },\n signal\n }) as Promise<{ data?: Charge; error?: unknown; response: Response }>\n );\n }\n\n /**\n * List charges for the authenticated seller, with pagination and filters.\n *\n * @example\n * const { data, meta } = await garu.charges.list({ status: 'paid', limit: 10 });\n * // meta.total paid charges\n */\n async list(params: ListChargesParams = {}): Promise<ChargeList> {\n const query: Record<string, string> = {};\n if (params.page !== undefined) query.page = String(params.page);\n if (params.limit !== undefined) query.limit = String(params.limit);\n if (params.status) query.status = params.status;\n if (params.search) query.search = params.search;\n if (params.paymentMethod) query.paymentMethod = params.paymentMethod;\n\n const qs = new URLSearchParams(query).toString();\n const url = `/api/transactions${qs ? `?${qs}` : ''}`;\n\n return this.http.call<ChargeList>((signal) =>\n (this.http.client.GET as Function)(url, { signal }).then(\n (r: { data?: ChargeList; error?: unknown; response: Response }) => r\n )\n );\n }\n\n /**\n * Fetch a single charge by numeric ID.\n *\n * @example\n * const charge = await garu.charges.get(4472);\n * if (charge.status === 'paid') { ... }\n */\n async get(id: number): Promise<Charge> {\n return this.http.call<Charge>(\n (signal) =>\n this.http.client.GET('/api/transactions/{id}', {\n params: { path: { id } },\n signal\n }) as Promise<{ data?: Charge; error?: unknown; response: Response }>\n );\n }\n\n /**\n * Refund a charge — fully, or partially by passing `amount` in centavos.\n *\n * @example\n * // Full refund\n * await garu.charges.refund(4472);\n *\n * @example\n * // Partial refund of R$ 10,00\n * await garu.charges.refund(4472, { amount: 1000, reason: 'customer_request' });\n */\n async refund(id: number, params: RefundChargeParams = {}): Promise<Charge> {\n const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();\n const body: Record<string, unknown> = {};\n if (params.amount !== undefined) body.amount = params.amount;\n if (params.reason !== undefined) body.reason = params.reason;\n\n return this.http.call<Charge>(\n (signal) =>\n this.http.client.POST('/api/transactions/{id}/refund', {\n params: { path: { id } },\n body: body as never,\n headers: { 'X-Idempotency-Key': idempotencyKey },\n signal\n }) as Promise<{ data?: Charge; error?: unknown; response: Response }>\n );\n }\n\n private buildCreateBody(params: CreateChargeParams): CreateTransactionBody {\n const body: Record<string, unknown> = {\n customer: params.customer,\n productId: params.productId,\n paymentMethodId: toWirePaymentMethod(params.paymentMethod),\n link: params.link ?? null,\n affiliateId: params.affiliateId ?? null\n };\n if (params.additionalInfo !== undefined) body.additionalInfo = params.additionalInfo;\n if (params.priceId !== undefined) body.priceId = params.priceId;\n if (params.checkoutSessionToken !== undefined) {\n body.checkoutSessionToken = params.checkoutSessionToken;\n }\n if (params.cardInfo) body.CardInfo = params.cardInfo;\n return body as unknown as CreateTransactionBody;\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type {\n CreateCustomerParams,\n CustomerList,\n CustomerRecord,\n ListCustomersParams,\n UpdateCustomerParams\n} from '../types.js';\n\n/**\n * Customers — manage your customer base.\n *\n * Customers are scoped to the seller identified by the API key. The backend\n * uses a junction table (`customer_seller_profile`) so the same person can\n * exist across multiple sellers without duplication.\n */\nexport class Customers {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a customer and link it to the current seller.\n *\n * @example\n * const customer = await garu.customers.create({\n * name: 'Maria Silva',\n * email: 'maria@exemplo.com.br',\n * document: '12345678909',\n * phone: '11987654321',\n * personType: 'fisica'\n * });\n */\n async create(params: CreateCustomerParams): Promise<CustomerRecord> {\n return this.http.call<CustomerRecord>((signal) =>\n (this.http.client.POST as Function)('/api/customers', {\n body: params,\n signal\n }).then((r: { data?: CustomerRecord; error?: unknown; response: Response }) => r)\n );\n }\n\n /**\n * List customers for the authenticated seller, with pagination and search.\n *\n * @example\n * const { data, meta } = await garu.customers.list({ search: 'maria', limit: 10 });\n */\n async list(params: ListCustomersParams = {}): Promise<CustomerList> {\n const query: Record<string, string> = {};\n if (params.page !== undefined) query.page = String(params.page);\n if (params.limit !== undefined) query.limit = String(params.limit);\n if (params.search) query.search = params.search;\n\n const qs = new URLSearchParams(query).toString();\n const url = `/api/customers${qs ? `?${qs}` : ''}`;\n\n return this.http.call<CustomerList>((signal) =>\n (this.http.client.GET as Function)(url, { signal }).then(\n (r: { data?: CustomerList; error?: unknown; response: Response }) => r\n )\n );\n }\n\n /**\n * Fetch a single customer by numeric ID.\n *\n * @example\n * const customer = await garu.customers.get(42);\n */\n async get(id: number): Promise<CustomerRecord> {\n return this.http.call<CustomerRecord>((signal) =>\n (this.http.client.GET as Function)(`/api/customers/${id}`, { signal }).then(\n (r: { data?: CustomerRecord; error?: unknown; response: Response }) => r\n )\n );\n }\n\n /**\n * Update a customer's profile for the current seller.\n *\n * @example\n * const updated = await garu.customers.update(42, { name: 'Maria Santos' });\n */\n async update(id: number, params: UpdateCustomerParams): Promise<CustomerRecord> {\n return this.http.call<CustomerRecord>((signal) =>\n (this.http.client.PUT as Function)(`/api/customers/${id}`, {\n body: params,\n signal\n }).then((r: { data?: CustomerRecord; error?: unknown; response: Response }) => r)\n );\n }\n\n /**\n * Remove a customer from the current seller.\n *\n * @example\n * await garu.customers.delete(42);\n */\n async delete(id: number): Promise<void> {\n await this.http.call<unknown>((signal) =>\n (this.http.client.DELETE as Function)(`/api/customers/${id}`, { signal }).then(\n (r: { data?: unknown; error?: unknown; response: Response }) => r\n )\n );\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { MetaResponse } from '../types.js';\n\n/**\n * Meta — capability introspection.\n *\n * Unauthenticated. Used by `garu doctor`, MCP tool `doctor`, and by SDK\n * consumers that want to know which payment methods and webhook events are\n * currently supported.\n */\nexport class Meta {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Fetch the API's current capability payload.\n *\n * @example\n * const meta = await garu.meta.get();\n * console.log(meta.version, meta.payment_methods);\n * if (meta.features.subscriptions) { ... }\n */\n async get(): Promise<MetaResponse> {\n return this.http.call<MetaResponse>(\n (signal) =>\n this.http.client.GET('/api/meta', { signal }) as Promise<{\n data?: MetaResponse;\n error?: unknown;\n response: Response;\n }>\n );\n }\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto';\n\nimport { GaruSignatureVerificationError } from './errors.js';\n\nexport interface VerifyWebhookParams {\n /** Raw request body as received — do NOT re-serialize parsed JSON. */\n payload: string | Buffer;\n /** Value of the `X-Garu-Signature` header. Format: `t=<ts>,v1=<hex>`. */\n signature: string;\n /** The webhook endpoint's signing secret. */\n secret: string;\n /** Reject signatures older than this many seconds. Default: 300 (5 min). */\n toleranceSec?: number;\n /** Injectable for tests. Defaults to `Date.now()`. */\n now?: () => number;\n}\n\nexport interface VerifiedWebhook {\n /** Timestamp from the signature header, in seconds since epoch. */\n timestamp: number;\n /** Parsed JSON body. Throws {@link GaruSignatureVerificationError} if invalid JSON. */\n event: unknown;\n}\n\n/**\n * Webhook helpers.\n *\n * Garu signs outgoing webhooks with HMAC-SHA256 over `${timestamp}.${payload}`\n * and delivers the signature in the `X-Garu-Signature` header as `t=<ts>,v1=<hex>`.\n * This matches the format in the backend's `webhook-delivery.service.ts`.\n *\n * @example\n * // Express example\n * app.post('/webhooks/garu', express.raw({ type: 'application/json' }), (req, res) => {\n * try {\n * const { event } = Garu.webhooks.verify({\n * payload: req.body,\n * signature: req.header('x-garu-signature') ?? '',\n * secret: process.env.GARU_WEBHOOK_SECRET!\n * });\n * // handle event\n * res.sendStatus(200);\n * } catch (err) {\n * res.sendStatus(400);\n * }\n * });\n */\nexport const webhooks = {\n verify(params: VerifyWebhookParams): VerifiedWebhook {\n const { signature, secret, payload } = params;\n const toleranceSec = params.toleranceSec ?? 300;\n const now = params.now ?? Date.now;\n\n if (!signature || typeof signature !== 'string') {\n throw new GaruSignatureVerificationError('Missing or malformed X-Garu-Signature header');\n }\n\n const parts = parseSignatureHeader(signature);\n if (parts === null) {\n throw new GaruSignatureVerificationError(\n 'X-Garu-Signature header does not match expected format t=<ts>,v1=<hex>'\n );\n }\n\n const payloadStr = typeof payload === 'string' ? payload : payload.toString('utf8');\n const signedPayload = `${parts.timestamp}.${payloadStr}`;\n const expected = createHmac('sha256', secret).update(signedPayload).digest('hex');\n\n const expectedBuf = Buffer.from(expected, 'hex');\n const providedBuf = Buffer.from(parts.v1, 'hex');\n if (expectedBuf.length !== providedBuf.length || !timingSafeEqual(expectedBuf, providedBuf)) {\n throw new GaruSignatureVerificationError('Signature does not match computed HMAC');\n }\n\n const nowSec = Math.floor(now() / 1000);\n if (Math.abs(nowSec - parts.timestamp) > toleranceSec) {\n throw new GaruSignatureVerificationError(\n `Signature timestamp outside tolerance window (${toleranceSec}s)`\n );\n }\n\n let event: unknown;\n try {\n event = JSON.parse(payloadStr);\n } catch {\n throw new GaruSignatureVerificationError('Webhook payload is not valid JSON');\n }\n\n return { timestamp: parts.timestamp, event };\n }\n};\n\nfunction parseSignatureHeader(header: string): { timestamp: number; v1: string } | null {\n const fields: Record<string, string> = {};\n for (const part of header.split(',')) {\n const idx = part.indexOf('=');\n if (idx === -1) return null;\n const key = part.slice(0, idx).trim();\n const value = part.slice(idx + 1).trim();\n if (!key || !value) return null;\n fields[key] = value;\n }\n const t = fields.t;\n const v1 = fields.v1;\n if (!t || !v1) return null;\n const timestamp = Number(t);\n if (!Number.isFinite(timestamp) || !/^[a-f0-9]+$/i.test(v1)) return null;\n return { timestamp, v1 };\n}\n","import { HttpClient } from './http.js';\nimport { Charges } from './resources/charges.js';\nimport { Customers } from './resources/customers.js';\nimport { Meta } from './resources/meta.js';\nimport { webhooks } from './webhooks.js';\n\nexport interface GaruOptions {\n /**\n * Your Garu API key. `sk_live_…` for production, `sk_test_…` for test mode.\n * Optional — public endpoints (`meta.get`, public charge creation) work without one.\n */\n apiKey?: string;\n /** Override the API base URL. Default: `https://garu.com.br/api`. */\n baseUrl?: string;\n /** Per-request timeout in ms. Default: 30000. */\n timeoutMs?: number;\n /** Max retries on retryable errors (connection, 408, 429, 5xx). Default: 2. */\n maxRetries?: number;\n /** Injectable for tests. Defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n}\n\nconst DEFAULT_BASE_URL = 'https://garu.com.br';\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst SDK_VERSION = '0.2.0';\n\n/**\n * The Garu SDK client.\n *\n * @example\n * import { Garu } from '@garuhq/node';\n *\n * const garu = new Garu({ apiKey: process.env.GARU_API_KEY });\n *\n * const charge = await garu.charges.create({\n * productId: 'b3f2c1e8-6e4a-4b9f-9d1c-2a1f6c3d4e5f',\n * paymentMethod: 'pix',\n * customer: {\n * name: 'Maria Silva',\n * email: 'maria@exemplo.com.br',\n * document: '12345678909',\n * phone: '11987654321'\n * }\n * });\n */\nexport class Garu {\n public readonly charges: Charges;\n public readonly customers: Customers;\n public readonly meta: Meta;\n\n /**\n * Webhook helpers. Available both as an instance member and as a static —\n * `Garu.webhooks.verify(...)` works without constructing a client.\n */\n public static readonly webhooks = webhooks;\n public readonly webhooks = webhooks;\n\n constructor(options: GaruOptions = {}) {\n const http = new HttpClient({\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\n apiKey: options.apiKey,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxRetries: options.maxRetries ?? DEFAULT_MAX_RETRIES,\n userAgent: `garu-node/${SDK_VERSION}`,\n fetch: options.fetch\n });\n this.charges = new Charges(http);\n this.customers = new Customers(http);\n this.meta = new Meta(http);\n }\n}\n"]}
|