@sinnu-dev/sdk 0.0.0-stage → 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/README.md CHANGED
@@ -1,3 +1,162 @@
1
- # Temporary Holding Version
1
+ # Sinnu SDK para Node.js
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ SDK oficial da [Sinnu](https://sinnu.com.br) para receber com **Pix** e **cartão de crédito**
4
+ direto do seu sistema.
5
+
6
+ Feito para **agências**, **prestadores de serviço**, **SaaS** e qualquer negócio que
7
+ cobra clientes pela internet: gere um link de pagamento, mande para o cliente e saiba na
8
+ hora quando o dinheiro entrou.
9
+
10
+ 📘 **Documentação completa:** [docs.sinnu.com.br](https://docs.sinnu.com.br)
11
+
12
+ ## O que dá para fazer
13
+
14
+ - **Cobrar** com links de pagamento: Pix e cartão em até 12x, no checkout hospedado da Sinnu.
15
+ - **Acompanhar** as transações: status, valor bruto, taxas e valor líquido.
16
+ - **Estornar** uma venda pelo próprio sistema.
17
+ - **Ser avisado** de cada pagamento por webhook, com assinatura verificada.
18
+
19
+ ## Instalação
20
+
21
+ ```bash
22
+ npm install @sinnu-dev/sdk
23
+ ```
24
+
25
+ Requer Node.js 18 ou mais recente. Funciona com TypeScript e JavaScript (ESM e CommonJS).
26
+
27
+ ## Primeiros passos
28
+
29
+ Gere sua **chave secreta** (`sk_live_...`) no painel da Sinnu, em **Chave de API**, e guarde
30
+ em uma variável de ambiente do servidor.
31
+
32
+ > A chave secreta dá acesso à sua conta. Use só no backend: nunca no navegador nem no app.
33
+
34
+ ```ts
35
+ import { Sinnu } from "@sinnu-dev/sdk";
36
+
37
+ const sinnu = new Sinnu({ apiKey: process.env.SINNU_API_KEY! });
38
+
39
+ const link = await sinnu.links.create({
40
+ title: "Consultoria inicial",
41
+ amountCents: 9900, // R$ 99,00
42
+ methods: ["pix", "credit_card"],
43
+ maxInstallments: 12,
44
+ });
45
+
46
+ // Envie esta URL para o seu cliente pagar.
47
+ console.log(sinnu.checkout.url(link.slug));
48
+ ```
49
+
50
+ Valores são sempre em **centavos**: `9900` é R$ 99,00.
51
+
52
+ ## Cobrar pedidos do seu sistema
53
+
54
+ O link é o produto e pode ser vendido muitas vezes. Para saber qual pedido cada venda
55
+ pagou, abra o checkout com a referência do pedido:
56
+
57
+ ```ts
58
+ const link = await sinnu.links.create({
59
+ title: "Consultoria inicial",
60
+ amountCents: 9900,
61
+ externalReference: "CONSULTORIA-1H", // código do produto no seu sistema
62
+ redirectUrl: "https://sualoja.com.br/obrigado", // ou o deep link do app: meuapp://pedido
63
+ });
64
+
65
+ // Um checkout por pedido: a referência volta na transação e no webhook.
66
+ const url = sinnu.checkout.url(link.slug, { reference: "pedido-123" });
67
+ ```
68
+
69
+ Depois do pagamento confirmado, o comprador volta para o `redirectUrl` (liberado por empresa:
70
+ confirme com a Sinnu se já está ativo para a sua) com
71
+ `transactionId`, `reference` e `status=approved` na query. Use esses parâmetros só para
72
+ mostrar a tela certa: libere o pedido pelo webhook ou por `transactions.get(transactionId)`.
73
+
74
+ ## Acompanhar transações
75
+
76
+ ```ts
77
+ const page = await sinnu.transactions.list({ status: "approved" });
78
+ console.log(`${page.total} vendas aprovadas`);
79
+
80
+ // Ou percorra todas as páginas:
81
+ for await (const tx of sinnu.transactions.listAll({ status: "approved" })) {
82
+ console.log(tx.id, tx.method, tx.amount, tx.net);
83
+ }
84
+ ```
85
+
86
+ ## Estornar uma venda
87
+
88
+ O estorno é sempre do valor total da transação.
89
+
90
+ ```ts
91
+ const tx = await sinnu.transactions.refund("ID_DA_TRANSACAO", {
92
+ reason: "Pedido cancelado pelo cliente",
93
+ });
94
+ ```
95
+
96
+ ## Receber webhooks
97
+
98
+ A Sinnu avisa seu sistema a cada evento de pagamento. Verifique a assinatura com o
99
+ **corpo cru** da requisição antes de processar:
100
+
101
+ ```ts
102
+ import { constructEvent, SinnuWebhookSignatureError } from "@sinnu-dev/sdk";
103
+
104
+ try {
105
+ const event = constructEvent({
106
+ payload: rawBody,
107
+ signature: req.headers["x-sinnu-signature"],
108
+ secret: process.env.SINNU_WEBHOOK_SECRET!,
109
+ });
110
+
111
+ if (event.type === "transaction.approved") {
112
+ // event.data.reference é o pedido do seu sistema (o ?ref= do checkout):
113
+ // libere o pedido, envie o acesso, emita a nota...
114
+ }
115
+ } catch (err) {
116
+ if (err instanceof SinnuWebhookSignatureError) {
117
+ // assinatura inválida: responda 400 e descarte
118
+ }
119
+ }
120
+ ```
121
+
122
+ ## Tratamento de erros
123
+
124
+ Toda falha da API vira um `SinnuError` (ou uma subclasse), com o status HTTP em
125
+ `statusCode`:
126
+
127
+ ```ts
128
+ import { SinnuAuthError, SinnuError, SinnuValidationError } from "@sinnu-dev/sdk";
129
+
130
+ try {
131
+ await sinnu.links.create({ title: "Teste", amountCents: 500 });
132
+ } catch (err) {
133
+ if (err instanceof SinnuAuthError) console.error("Chave de API inválida");
134
+ else if (err instanceof SinnuValidationError) console.error(err.body);
135
+ else if (err instanceof SinnuError) console.error(err.statusCode, err.message);
136
+ }
137
+ ```
138
+
139
+ Também existem `SinnuNotFoundError` e `SinnuRateLimitError`.
140
+
141
+ ## Recursos
142
+
143
+ | Recurso | Métodos |
144
+ |---|---|
145
+ | `sinnu.links` | `create`, `get`, `update`, `archive`, `list`, `listAll`, `transactions` |
146
+ | `sinnu.transactions` | `list`, `listAll`, `get`, `refund` |
147
+ | `sinnu.checkout` | `url` |
148
+ | `sinnu.webhooks` | `constructEvent`, `verifySignature`, `computeSignature` |
149
+
150
+ Para chamar direto qualquer rota da API pública com tipos, use `sinnu.http`.
151
+
152
+ ## Links úteis
153
+
154
+ - [Guia do SDK](https://docs.sinnu.com.br/sdk)
155
+ - [Início rápido](https://docs.sinnu.com.br/guias/inicio-rapido)
156
+ - [Autenticação](https://docs.sinnu.com.br/guias/autenticacao)
157
+ - [Webhooks](https://docs.sinnu.com.br/guias/webhooks)
158
+ - [Referência da API](https://docs.sinnu.com.br/api-reference)
159
+
160
+ ## Licença
161
+
162
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,446 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ Checkout: () => Checkout,
34
+ DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
35
+ DEFAULT_CHECKOUT_BASE_URL: () => DEFAULT_CHECKOUT_BASE_URL,
36
+ SINNU_SIGNATURE_HEADER: () => SINNU_SIGNATURE_HEADER,
37
+ Sinnu: () => Sinnu,
38
+ SinnuAuthError: () => SinnuAuthError,
39
+ SinnuError: () => SinnuError,
40
+ SinnuNotFoundError: () => SinnuNotFoundError,
41
+ SinnuRateLimitError: () => SinnuRateLimitError,
42
+ SinnuValidationError: () => SinnuValidationError,
43
+ SinnuWebhookSignatureError: () => SinnuWebhookSignatureError,
44
+ collectAll: () => collectAll,
45
+ computeSignature: () => computeSignature,
46
+ constructEvent: () => constructEvent,
47
+ createTypedClient: () => createTypedClient,
48
+ default: () => index_default,
49
+ paginate: () => paginate,
50
+ unwrap: () => unwrap,
51
+ verifySignature: () => verifySignature,
52
+ webhooks: () => webhooks
53
+ });
54
+ module.exports = __toCommonJS(index_exports);
55
+
56
+ // src/client.ts
57
+ var import_openapi_fetch = __toESM(require("openapi-fetch"), 1);
58
+
59
+ // src/errors.ts
60
+ var SinnuError = class extends Error {
61
+ constructor(message, statusCode, body, response) {
62
+ super(message);
63
+ this.name = "SinnuError";
64
+ this.statusCode = statusCode;
65
+ this.body = body;
66
+ this.response = response;
67
+ }
68
+ };
69
+ var SinnuAuthError = class extends SinnuError {
70
+ constructor(message, statusCode = 401, body, response) {
71
+ super(message, statusCode, body, response);
72
+ this.name = "SinnuAuthError";
73
+ }
74
+ };
75
+ var SinnuNotFoundError = class extends SinnuError {
76
+ constructor(message, body, response) {
77
+ super(message, 404, body, response);
78
+ this.name = "SinnuNotFoundError";
79
+ }
80
+ };
81
+ var SinnuValidationError = class extends SinnuError {
82
+ constructor(message, statusCode, body, response) {
83
+ super(message, statusCode, body, response);
84
+ this.name = "SinnuValidationError";
85
+ }
86
+ };
87
+ var SinnuRateLimitError = class extends SinnuError {
88
+ constructor(message, body, response) {
89
+ super(message, 429, body, response);
90
+ this.name = "SinnuRateLimitError";
91
+ }
92
+ };
93
+ function toSinnuError(statusCode, body, response) {
94
+ const message = body?.message ?? `Requisi\xE7\xE3o falhou com status ${statusCode}`;
95
+ switch (statusCode) {
96
+ case 401:
97
+ case 403:
98
+ return new SinnuAuthError(message, statusCode, body, response);
99
+ case 404:
100
+ return new SinnuNotFoundError(message, body, response);
101
+ case 400:
102
+ case 422:
103
+ return new SinnuValidationError(message, statusCode, body, response);
104
+ case 429:
105
+ return new SinnuRateLimitError(message, body, response);
106
+ default:
107
+ return new SinnuError(message, statusCode, body, response);
108
+ }
109
+ }
110
+
111
+ // src/client.ts
112
+ var DEFAULT_BASE_URL = "https://api.sinnu.com.br";
113
+ var API_KEY_PREFIXES = ["sk_live_"];
114
+ function assertApiKey(apiKey) {
115
+ if (!apiKey || typeof apiKey !== "string") {
116
+ throw new Error(
117
+ "[@sinnu-dev/sdk] apiKey \xE9 obrigat\xF3ria. Gere uma chave secreta no painel sinnu (Integra\xE7\xF5es)."
118
+ );
119
+ }
120
+ if (!API_KEY_PREFIXES.some((p) => apiKey.startsWith(p))) {
121
+ console.warn(
122
+ "[@sinnu-dev/sdk] apiKey n\xE3o come\xE7a com 'sk_live_'. Use a chave secreta no backend, nunca uma chave no cliente."
123
+ );
124
+ }
125
+ }
126
+ function createTypedClient(options) {
127
+ assertApiKey(options.apiKey);
128
+ return (0, import_openapi_fetch.default)({
129
+ baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
130
+ fetch: options.fetch,
131
+ headers: {
132
+ Authorization: `Bearer ${options.apiKey}`,
133
+ "Content-Type": "application/json",
134
+ ...options.headers
135
+ }
136
+ });
137
+ }
138
+ async function unwrap(p) {
139
+ const { data, error, response } = await p;
140
+ if (error || !response.ok) {
141
+ throw toSinnuError(
142
+ response.status,
143
+ error ?? void 0,
144
+ response
145
+ );
146
+ }
147
+ if (data === void 0 || data === null) {
148
+ throw toSinnuError(response.status, { message: "Resposta sem corpo" }, response);
149
+ }
150
+ return data;
151
+ }
152
+ var RawHttp = class {
153
+ constructor(baseUrl, apiKey, extraHeaders, fetchImpl) {
154
+ this.baseUrl = baseUrl;
155
+ this.apiKey = apiKey;
156
+ this.extraHeaders = extraHeaders;
157
+ this.fetchImpl = fetchImpl;
158
+ }
159
+ async request(path, options = {}) {
160
+ const url = new URL(path.replace(/^\//, ""), ensureTrailingSlash(this.baseUrl));
161
+ if (options.query) {
162
+ for (const [key, value] of Object.entries(options.query)) {
163
+ if (value !== void 0) {
164
+ url.searchParams.set(key, String(value));
165
+ }
166
+ }
167
+ }
168
+ const response = await this.fetchImpl(url.toString(), {
169
+ method: options.method ?? "GET",
170
+ headers: {
171
+ Authorization: `Bearer ${this.apiKey}`,
172
+ "Content-Type": "application/json",
173
+ Accept: "application/json",
174
+ ...this.extraHeaders
175
+ },
176
+ body: options.body !== void 0 ? JSON.stringify(options.body) : void 0
177
+ });
178
+ const text = await response.text();
179
+ const parsed = text ? safeJsonParse(text) : void 0;
180
+ if (!response.ok) {
181
+ throw toSinnuError(response.status, parsed, response);
182
+ }
183
+ return parsed;
184
+ }
185
+ };
186
+ function ensureTrailingSlash(url) {
187
+ return url.endsWith("/") ? url : `${url}/`;
188
+ }
189
+ function safeJsonParse(text) {
190
+ try {
191
+ return JSON.parse(text);
192
+ } catch {
193
+ return text;
194
+ }
195
+ }
196
+
197
+ // src/resources/checkout.ts
198
+ var DEFAULT_CHECKOUT_BASE_URL = "https://pay.sinnu.com.br";
199
+ var Checkout = class {
200
+ constructor(options = {}) {
201
+ this.options = options;
202
+ }
203
+ /**
204
+ * Monta a URL pública do checkout hosted para um `slug` (8 chars) gerado
205
+ * ao criar um link (`sinnu.links.create(...).url` já vem pronto; este
206
+ * helper é útil quando você só tem o slug).
207
+ *
208
+ * @example
209
+ * const url = sinnu.checkout.url("abcd1234", { reference: "pedido-123" });
210
+ * // => "https://pay.sinnu.com.br/abcd1234?ref=pedido-123"
211
+ */
212
+ url(slug, options = {}) {
213
+ if (!slug || typeof slug !== "string") {
214
+ throw new Error("[@sinnu-dev/sdk] slug do checkout \xE9 obrigat\xF3rio.");
215
+ }
216
+ const base = options.checkoutBaseUrl ?? this.options.checkoutBaseUrl ?? DEFAULT_CHECKOUT_BASE_URL;
217
+ const url = new URL(encodeURIComponent(slug), ensureTrailingSlash2(base));
218
+ const query = { ...this.options.query, ...options.query };
219
+ for (const [key, value] of Object.entries(query)) {
220
+ if (value !== void 0) {
221
+ url.searchParams.set(key, String(value));
222
+ }
223
+ }
224
+ if (options.reference !== void 0) {
225
+ if (options.reference.length > 255) {
226
+ throw new Error("[@sinnu-dev/sdk] reference tem no m\xE1ximo 255 caracteres.");
227
+ }
228
+ url.searchParams.set("ref", options.reference);
229
+ }
230
+ return url.toString();
231
+ }
232
+ };
233
+ function ensureTrailingSlash2(url) {
234
+ return url.endsWith("/") ? url : `${url}/`;
235
+ }
236
+
237
+ // src/pagination.ts
238
+ async function* paginate(fetchPage) {
239
+ let page = 1;
240
+ let seen = 0;
241
+ while (true) {
242
+ const result = await fetchPage(page);
243
+ for (const item of result.data) {
244
+ yield item;
245
+ }
246
+ seen += result.data.length;
247
+ const pageSize = result.pageSize || result.data.length;
248
+ if (result.data.length === 0 || seen >= result.total || pageSize === 0) {
249
+ return;
250
+ }
251
+ page += 1;
252
+ }
253
+ }
254
+ async function collectAll(fetchPage) {
255
+ const out = [];
256
+ for await (const item of paginate(fetchPage)) {
257
+ out.push(item);
258
+ }
259
+ return out;
260
+ }
261
+
262
+ // src/resources/links.ts
263
+ var Links = class {
264
+ constructor(http) {
265
+ this.http = http;
266
+ }
267
+ /** Cria um link de pagamento (valor em centavos). */
268
+ async create(body) {
269
+ return this.http.request("/api/payment-links", {
270
+ method: "POST",
271
+ body
272
+ });
273
+ }
274
+ /** Busca um link de pagamento pelo id. */
275
+ async get(id) {
276
+ return this.http.request(`/api/payment-links/${encodeURIComponent(id)}`);
277
+ }
278
+ /** Atualiza parcialmente um link de pagamento. */
279
+ async update(id, body) {
280
+ return this.http.request(`/api/payment-links/${encodeURIComponent(id)}`, {
281
+ method: "PATCH",
282
+ body
283
+ });
284
+ }
285
+ /** Arquiva um link de pagamento. */
286
+ async archive(id) {
287
+ await this.http.request(`/api/payment-links/${encodeURIComponent(id)}`, {
288
+ method: "DELETE"
289
+ });
290
+ }
291
+ /** Lista links de pagamento (paginado). */
292
+ async list(params = {}) {
293
+ return this.http.request("/api/payment-links", {
294
+ query: { page: params.page, pageSize: params.pageSize }
295
+ });
296
+ }
297
+ /** Lista transações de um link de pagamento (paginado). */
298
+ async transactions(id, params = {}) {
299
+ return this.http.request(
300
+ `/api/payment-links/${encodeURIComponent(id)}/transactions`,
301
+ { query: { page: params.page, pageSize: params.pageSize } }
302
+ );
303
+ }
304
+ /** Itera todos os links de pagamento, página a página. */
305
+ listAll(params = {}) {
306
+ return paginate((page) => this.list({ ...params, page }));
307
+ }
308
+ };
309
+
310
+ // src/resources/transactions.ts
311
+ var Transactions = class {
312
+ constructor(http) {
313
+ this.http = http;
314
+ }
315
+ /** Lista transações (paginado, com filtro opcional por status). */
316
+ async list(params = {}) {
317
+ return this.http.request("/api/transactions/", {
318
+ query: {
319
+ status: params.status,
320
+ search: params.search,
321
+ customer: params.customer,
322
+ page: params.page,
323
+ pageSize: params.pageSize
324
+ }
325
+ });
326
+ }
327
+ /** Busca uma transação pelo id. */
328
+ async get(id) {
329
+ return this.http.request(`/api/transactions/${encodeURIComponent(id)}/`);
330
+ }
331
+ /** Estorna (refund) uma transação. */
332
+ async refund(id, body = {}) {
333
+ return this.http.request(
334
+ `/api/transactions/${encodeURIComponent(id)}/refund/`,
335
+ { method: "POST", body }
336
+ );
337
+ }
338
+ /** Itera todas as transações, página a página. */
339
+ listAll(params = {}) {
340
+ return paginate((page) => this.list({ ...params, page }));
341
+ }
342
+ };
343
+
344
+ // src/webhooks.ts
345
+ var import_node_crypto = require("crypto");
346
+ var SINNU_SIGNATURE_HEADER = "x-sinnu-signature";
347
+ var SinnuWebhookSignatureError = class extends SinnuError {
348
+ constructor(message) {
349
+ super(message, 0);
350
+ this.name = "SinnuWebhookSignatureError";
351
+ }
352
+ };
353
+ function normalizeSignature(signature) {
354
+ if (signature === void 0) {
355
+ throw new SinnuWebhookSignatureError(
356
+ "[@sinnu-dev/sdk] header de assinatura ausente. Esperado 'X-Sinnu-Signature'."
357
+ );
358
+ }
359
+ const value = Array.isArray(signature) ? signature[0] : signature;
360
+ if (!value) {
361
+ throw new SinnuWebhookSignatureError("[@sinnu-dev/sdk] header de assinatura vazio.");
362
+ }
363
+ return value.startsWith("sha256=") ? value.slice("sha256=".length) : value;
364
+ }
365
+ function toBuffer(payload) {
366
+ return typeof payload === "string" ? Buffer.from(payload, "utf8") : payload;
367
+ }
368
+ function computeSignature(payload, secret) {
369
+ return (0, import_node_crypto.createHmac)("sha256", secret).update(toBuffer(payload)).digest("hex");
370
+ }
371
+ function verifySignature(options) {
372
+ const { payload, signature, secret } = options;
373
+ if (!secret) {
374
+ throw new SinnuWebhookSignatureError(
375
+ "[@sinnu-dev/sdk] webhook secret \xE9 obrigat\xF3rio para verificar a assinatura."
376
+ );
377
+ }
378
+ const provided = normalizeSignature(signature);
379
+ const expected = computeSignature(payload, secret);
380
+ const providedBuf = Buffer.from(provided, "hex");
381
+ const expectedBuf = Buffer.from(expected, "hex");
382
+ if (providedBuf.length !== expectedBuf.length) {
383
+ return false;
384
+ }
385
+ return (0, import_node_crypto.timingSafeEqual)(providedBuf, expectedBuf);
386
+ }
387
+ function constructEvent(options) {
388
+ if (!verifySignature(options)) {
389
+ throw new SinnuWebhookSignatureError(
390
+ "[@sinnu-dev/sdk] assinatura de webhook inv\xE1lida. Requisi\xE7\xE3o rejeitada."
391
+ );
392
+ }
393
+ const text = typeof options.payload === "string" ? options.payload : options.payload.toString("utf8");
394
+ try {
395
+ return JSON.parse(text);
396
+ } catch {
397
+ throw new SinnuWebhookSignatureError("[@sinnu-dev/sdk] corpo do webhook n\xE3o \xE9 um JSON v\xE1lido.");
398
+ }
399
+ }
400
+ var webhooks = {
401
+ signatureHeader: SINNU_SIGNATURE_HEADER,
402
+ computeSignature,
403
+ verifySignature,
404
+ constructEvent
405
+ };
406
+
407
+ // src/index.ts
408
+ var Sinnu = class {
409
+ constructor(options) {
410
+ /** Verificação de webhooks (HMAC SHA-256): não faz requisições. */
411
+ this.webhooks = webhooks;
412
+ this.http = createTypedClient(options);
413
+ const raw = new RawHttp(
414
+ options.baseUrl ?? DEFAULT_BASE_URL,
415
+ options.apiKey,
416
+ options.headers ?? {},
417
+ options.fetch ?? fetch
418
+ );
419
+ this.links = new Links(raw);
420
+ this.transactions = new Transactions(raw);
421
+ this.checkout = new Checkout({ checkoutBaseUrl: options.checkoutBaseUrl });
422
+ }
423
+ };
424
+ var index_default = Sinnu;
425
+ // Annotate the CommonJS export names for ESM import in node:
426
+ 0 && (module.exports = {
427
+ Checkout,
428
+ DEFAULT_BASE_URL,
429
+ DEFAULT_CHECKOUT_BASE_URL,
430
+ SINNU_SIGNATURE_HEADER,
431
+ Sinnu,
432
+ SinnuAuthError,
433
+ SinnuError,
434
+ SinnuNotFoundError,
435
+ SinnuRateLimitError,
436
+ SinnuValidationError,
437
+ SinnuWebhookSignatureError,
438
+ collectAll,
439
+ computeSignature,
440
+ constructEvent,
441
+ createTypedClient,
442
+ paginate,
443
+ unwrap,
444
+ verifySignature,
445
+ webhooks
446
+ });