@garuhq/node 0.1.0 → 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.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
- * console.log(charge.id, charge.status);
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
- * console.log(charge.id, charge.status);
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
@@ -78,31 +78,24 @@ var GaruServerError = class extends GaruAPIError {
78
78
  };
79
79
  function mapApiError(status, body, requestId, retryAfterSec) {
80
80
  const message = extractMessage(body) ?? `Garu API returned HTTP ${status}`;
81
- if (status === 401)
82
- return new GaruAuthenticationError(message, status, requestId, body);
83
- if (status === 403)
84
- return new GaruPermissionError(message, status, requestId, body);
85
- if (status === 404)
86
- return new GaruNotFoundError(message, status, requestId, body);
81
+ if (status === 401) return new GaruAuthenticationError(message, status, requestId, body);
82
+ if (status === 403) return new GaruPermissionError(message, status, requestId, body);
83
+ if (status === 404) return new GaruNotFoundError(message, status, requestId, body);
87
84
  if (status === 400 || status === 422) {
88
85
  return new GaruValidationError(message, status, requestId, body);
89
86
  }
90
87
  if (status === 429) {
91
88
  return new GaruRateLimitError(message, status, requestId, body, retryAfterSec);
92
89
  }
93
- if (status >= 500)
94
- return new GaruServerError(message, status, requestId, body);
90
+ if (status >= 500) return new GaruServerError(message, status, requestId, body);
95
91
  return new GaruAPIError("api_error", message, status, requestId, body);
96
92
  }
97
93
  function extractMessage(body) {
98
- if (typeof body === "string")
99
- return body;
94
+ if (typeof body === "string") return body;
100
95
  if (body && typeof body === "object") {
101
96
  const m = body.message;
102
- if (typeof m === "string")
103
- return m;
104
- if (Array.isArray(m) && m.every((x) => typeof x === "string"))
105
- return m.join("; ");
97
+ if (typeof m === "string") return m;
98
+ if (Array.isArray(m) && m.every((x) => typeof x === "string")) return m.join("; ");
106
99
  }
107
100
  return null;
108
101
  }
@@ -124,8 +117,7 @@ var HttpClient = class {
124
117
  Accept: "application/json",
125
118
  "User-Agent": cfg.userAgent
126
119
  };
127
- if (cfg.apiKey)
128
- headers.Authorization = `Bearer ${cfg.apiKey}`;
120
+ if (cfg.apiKey) headers.Authorization = `Bearer ${cfg.apiKey}`;
129
121
  this.client = createClient({
130
122
  baseUrl: cfg.baseUrl.replace(/\/+$/, ""),
131
123
  fetch: fetchImpl,
@@ -160,12 +152,10 @@ var HttpClient = class {
160
152
  continue;
161
153
  } catch (err) {
162
154
  clearTimeout(timer);
163
- if (isGaruApiError(err))
164
- throw err;
155
+ if (isGaruApiError(err)) throw err;
165
156
  const connErr = err instanceof Error && err.name === "AbortError" ? new GaruConnectionError(`Request timed out after ${this.cfg.timeoutMs}ms`, err) : new GaruConnectionError(err instanceof Error ? err.message : "Network error", err);
166
157
  lastError = connErr;
167
- if (attempt === this.cfg.maxRetries)
168
- throw connErr;
158
+ if (attempt === this.cfg.maxRetries) throw connErr;
169
159
  await sleep(backoffDelay(attempt, null));
170
160
  continue;
171
161
  }
@@ -177,8 +167,7 @@ function isGaruApiError(err) {
177
167
  return err instanceof Error && err.name.startsWith("Garu") && err.name.endsWith("Error");
178
168
  }
179
169
  function parseRetryAfter(value) {
180
- if (!value)
181
- return null;
170
+ if (!value) return null;
182
171
  const n = Number(value);
183
172
  return Number.isFinite(n) && n >= 0 ? n : null;
184
173
  }
@@ -207,6 +196,7 @@ var Charges = class {
207
196
  constructor(http) {
208
197
  this.http = http;
209
198
  }
199
+ http;
210
200
  /**
211
201
  * Create a charge (PIX, credit card, or boleto).
212
202
  *
@@ -226,7 +216,7 @@ var Charges = class {
226
216
  * phone: '11987654321'
227
217
  * }
228
218
  * });
229
- * console.log(charge.id, charge.status);
219
+ * // charge.id, charge.status
230
220
  *
231
221
  * @example
232
222
  * // Credit card charge, 3 installments
@@ -254,6 +244,28 @@ var Charges = class {
254
244
  })
255
245
  );
256
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
+ }
257
269
  /**
258
270
  * Fetch a single charge by numeric ID.
259
271
  *
@@ -283,10 +295,8 @@ var Charges = class {
283
295
  async refund(id, params = {}) {
284
296
  const idempotencyKey = params.idempotencyKey ?? generateIdempotencyKey();
285
297
  const body = {};
286
- if (params.amount !== void 0)
287
- body.amount = params.amount;
288
- if (params.reason !== void 0)
289
- body.reason = params.reason;
298
+ if (params.amount !== void 0) body.amount = params.amount;
299
+ if (params.reason !== void 0) body.reason = params.reason;
290
300
  return this.http.call(
291
301
  (signal) => this.http.client.POST("/api/transactions/{id}/refund", {
292
302
  params: { path: { id } },
@@ -304,24 +314,109 @@ var Charges = class {
304
314
  link: params.link ?? null,
305
315
  affiliateId: params.affiliateId ?? null
306
316
  };
307
- if (params.additionalInfo !== void 0)
308
- body.additionalInfo = params.additionalInfo;
309
- if (params.priceId !== void 0)
310
- body.priceId = params.priceId;
317
+ if (params.additionalInfo !== void 0) body.additionalInfo = params.additionalInfo;
318
+ if (params.priceId !== void 0) body.priceId = params.priceId;
311
319
  if (params.checkoutSessionToken !== void 0) {
312
320
  body.checkoutSessionToken = params.checkoutSessionToken;
313
321
  }
314
- if (params.cardInfo)
315
- body.CardInfo = params.cardInfo;
322
+ if (params.cardInfo) body.CardInfo = params.cardInfo;
316
323
  return body;
317
324
  }
318
325
  };
319
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
+
320
414
  // src/resources/meta.ts
321
415
  var Meta = class {
322
416
  constructor(http) {
323
417
  this.http = http;
324
418
  }
419
+ http;
325
420
  /**
326
421
  * Fetch the API's current capability payload.
327
422
  *
@@ -377,21 +472,17 @@ function parseSignatureHeader(header) {
377
472
  const fields = {};
378
473
  for (const part of header.split(",")) {
379
474
  const idx = part.indexOf("=");
380
- if (idx === -1)
381
- return null;
475
+ if (idx === -1) return null;
382
476
  const key = part.slice(0, idx).trim();
383
477
  const value = part.slice(idx + 1).trim();
384
- if (!key || !value)
385
- return null;
478
+ if (!key || !value) return null;
386
479
  fields[key] = value;
387
480
  }
388
481
  const t = fields.t;
389
482
  const v1 = fields.v1;
390
- if (!t || !v1)
391
- return null;
483
+ if (!t || !v1) return null;
392
484
  const timestamp = Number(t);
393
- if (!Number.isFinite(timestamp) || !/^[a-f0-9]+$/i.test(v1))
394
- return null;
485
+ if (!Number.isFinite(timestamp) || !/^[a-f0-9]+$/i.test(v1)) return null;
395
486
  return { timestamp, v1 };
396
487
  }
397
488
 
@@ -399,9 +490,10 @@ function parseSignatureHeader(header) {
399
490
  var DEFAULT_BASE_URL = "https://garu.com.br";
400
491
  var DEFAULT_TIMEOUT_MS = 3e4;
401
492
  var DEFAULT_MAX_RETRIES = 2;
402
- var SDK_VERSION = "0.1.0";
493
+ var SDK_VERSION = "0.2.0";
403
494
  var Garu = class {
404
495
  charges;
496
+ customers;
405
497
  meta;
406
498
  /**
407
499
  * Webhook helpers. Available both as an instance member and as a static —
@@ -419,10 +511,11 @@ var Garu = class {
419
511
  fetch: options.fetch
420
512
  });
421
513
  this.charges = new Charges(http);
514
+ this.customers = new Customers(http);
422
515
  this.meta = new Meta(http);
423
516
  }
424
517
  };
425
518
 
426
519
  export { Garu, GaruAPIError, GaruAuthenticationError, GaruConnectionError, GaruError, GaruNotFoundError, GaruPermissionError, GaruRateLimitError, GaruServerError, GaruSignatureVerificationError, GaruValidationError, webhooks };
427
- //# sourceMappingURL=out.js.map
520
+ //# sourceMappingURL=index.js.map
428
521
  //# sourceMappingURL=index.js.map