@setup-automatizado/sicredi-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,1495 @@
1
+ 'use strict';
2
+
3
+ var https = require('https');
4
+ var fs = require('fs');
5
+
6
+ var __defProp = Object.defineProperty;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+
16
+ // src/errors/base.ts
17
+ exports.SicrediError = void 0;
18
+ var init_base = __esm({
19
+ "src/errors/base.ts"() {
20
+ exports.SicrediError = class extends Error {
21
+ code;
22
+ hint;
23
+ constructor(message, code, hint) {
24
+ super(message);
25
+ this.name = "SicrediError";
26
+ this.code = code;
27
+ this.hint = hint;
28
+ Object.setPrototypeOf(this, new.target.prototype);
29
+ }
30
+ };
31
+ }
32
+ });
33
+
34
+ // src/errors/connection-error.ts
35
+ exports.SicrediConnectionError = void 0;
36
+ var init_connection_error = __esm({
37
+ "src/errors/connection-error.ts"() {
38
+ init_base();
39
+ exports.SicrediConnectionError = class _SicrediConnectionError extends exports.SicrediError {
40
+ cause;
41
+ constructor(message, cause, hint) {
42
+ super(message, "CONNECTION_ERROR", hint);
43
+ this.name = "SicrediConnectionError";
44
+ this.cause = cause;
45
+ Object.setPrototypeOf(this, new.target.prototype);
46
+ }
47
+ static timeout(ms) {
48
+ return new _SicrediConnectionError(`Request timed out after ${ms}ms`);
49
+ }
50
+ static refused(host) {
51
+ return new _SicrediConnectionError(`Connection refused to host: ${host}`);
52
+ }
53
+ static tlsFailure(detail) {
54
+ return new _SicrediConnectionError(
55
+ `TLS/mTLS handshake failed: ${detail}`,
56
+ void 0,
57
+ "Verify that your mTLS certificates are valid, not expired, and correctly configured. Ensure the CA chain is complete."
58
+ );
59
+ }
60
+ };
61
+ }
62
+ });
63
+
64
+ // src/core/http-client-bun.ts
65
+ var http_client_bun_exports = {};
66
+ __export(http_client_bun_exports, {
67
+ BunHttpClient: () => BunHttpClient
68
+ });
69
+ var BunHttpClient;
70
+ var init_http_client_bun = __esm({
71
+ "src/core/http-client-bun.ts"() {
72
+ init_connection_error();
73
+ BunHttpClient = class {
74
+ tlsOptions;
75
+ defaultTimeout;
76
+ debug;
77
+ constructor(config) {
78
+ this.defaultTimeout = config.timeout;
79
+ this.debug = config.debug;
80
+ this.tlsOptions = {
81
+ cert: config.certificates.cert,
82
+ key: config.certificates.key,
83
+ ca: config.certificates.ca,
84
+ passphrase: config.certificates.passphrase
85
+ };
86
+ }
87
+ async request(options) {
88
+ const timeout = options.timeout ?? this.defaultTimeout;
89
+ if (this.debug) {
90
+ const url = new URL(options.url);
91
+ console.debug(`[sicredi-sdk] ${options.method} ${url.pathname}`);
92
+ }
93
+ const controller = new AbortController();
94
+ const timer = setTimeout(() => controller.abort(), timeout);
95
+ try {
96
+ const response = await fetch(options.url, {
97
+ method: options.method,
98
+ headers: options.headers,
99
+ body: options.body,
100
+ signal: controller.signal,
101
+ // @ts-expect-error Bun-specific TLS options
102
+ tls: this.tlsOptions
103
+ });
104
+ const body = await response.text();
105
+ const headers = {};
106
+ response.headers.forEach((value, key) => {
107
+ headers[key] = value;
108
+ });
109
+ return {
110
+ status: response.status,
111
+ headers,
112
+ body
113
+ };
114
+ } catch (error) {
115
+ if (error instanceof DOMException && error.name === "AbortError") {
116
+ throw exports.SicrediConnectionError.timeout(timeout);
117
+ }
118
+ if (error instanceof Error) {
119
+ const msg = error.message.toLowerCase();
120
+ if (msg.includes("econnrefused")) {
121
+ throw exports.SicrediConnectionError.refused(new URL(options.url).hostname);
122
+ }
123
+ if (msg.includes("tls") || msg.includes("ssl") || msg.includes("certificate")) {
124
+ throw exports.SicrediConnectionError.tlsFailure(error.message);
125
+ }
126
+ throw new exports.SicrediConnectionError(error.message, error);
127
+ }
128
+ throw new exports.SicrediConnectionError("Unknown connection error");
129
+ } finally {
130
+ clearTimeout(timer);
131
+ }
132
+ }
133
+ };
134
+ }
135
+ });
136
+
137
+ // src/core/http-client-node.ts
138
+ var http_client_node_exports = {};
139
+ __export(http_client_node_exports, {
140
+ NodeHttpClient: () => NodeHttpClient
141
+ });
142
+ var NodeHttpClient;
143
+ var init_http_client_node = __esm({
144
+ "src/core/http-client-node.ts"() {
145
+ init_connection_error();
146
+ NodeHttpClient = class {
147
+ agent;
148
+ defaultTimeout;
149
+ debug;
150
+ constructor(config) {
151
+ this.defaultTimeout = config.timeout;
152
+ this.debug = config.debug;
153
+ this.agent = new https.Agent({
154
+ cert: config.certificates.cert,
155
+ key: config.certificates.key,
156
+ ca: config.certificates.ca,
157
+ passphrase: config.certificates.passphrase,
158
+ keepAlive: true,
159
+ maxSockets: 10
160
+ });
161
+ }
162
+ request(options) {
163
+ return new Promise((resolve, reject) => {
164
+ const url = new URL(options.url);
165
+ const timeout = options.timeout ?? this.defaultTimeout;
166
+ if (this.debug) {
167
+ console.debug(`[sicredi-sdk] ${options.method} ${url.pathname}`);
168
+ }
169
+ const req = https.request(
170
+ {
171
+ hostname: url.hostname,
172
+ port: url.port || 443,
173
+ path: url.pathname + url.search,
174
+ method: options.method,
175
+ headers: options.headers,
176
+ agent: this.agent,
177
+ timeout
178
+ },
179
+ (res) => {
180
+ const chunks = [];
181
+ res.on("data", (chunk) => chunks.push(chunk));
182
+ res.on("end", () => {
183
+ const body = Buffer.concat(chunks).toString("utf-8");
184
+ const headers = {};
185
+ for (const [key, value] of Object.entries(res.headers)) {
186
+ if (typeof value === "string") {
187
+ headers[key] = value;
188
+ } else if (Array.isArray(value)) {
189
+ headers[key] = value.join(", ");
190
+ }
191
+ }
192
+ resolve({
193
+ status: res.statusCode ?? 0,
194
+ headers,
195
+ body
196
+ });
197
+ });
198
+ res.on("error", (err) => {
199
+ reject(new exports.SicrediConnectionError(err.message, err));
200
+ });
201
+ }
202
+ );
203
+ req.on("timeout", () => {
204
+ req.destroy();
205
+ reject(exports.SicrediConnectionError.timeout(timeout));
206
+ });
207
+ req.on("error", (err) => {
208
+ const msg = err.message.toLowerCase();
209
+ if (msg.includes("econnrefused")) {
210
+ reject(exports.SicrediConnectionError.refused(url.hostname));
211
+ } else if (msg.includes("ssl") || msg.includes("tls") || msg.includes("certificate")) {
212
+ reject(exports.SicrediConnectionError.tlsFailure(err.message));
213
+ } else {
214
+ reject(new exports.SicrediConnectionError(err.message, err));
215
+ }
216
+ });
217
+ if (options.body) {
218
+ req.write(options.body);
219
+ }
220
+ req.end();
221
+ });
222
+ }
223
+ };
224
+ }
225
+ });
226
+
227
+ // src/errors/api-error.ts
228
+ init_base();
229
+ var SicrediApiError = class _SicrediApiError extends exports.SicrediError {
230
+ statusCode;
231
+ type;
232
+ title;
233
+ detail;
234
+ violacoes;
235
+ constructor(statusCode, body) {
236
+ const message = body.detail ? `${body.title}: ${body.detail}` : body.title;
237
+ super(message, "API_ERROR");
238
+ this.name = "SicrediApiError";
239
+ this.statusCode = statusCode;
240
+ this.type = body.type;
241
+ this.title = body.title;
242
+ this.detail = body.detail;
243
+ this.violacoes = body.violacoes;
244
+ Object.setPrototypeOf(this, new.target.prototype);
245
+ }
246
+ static fromResponse(statusCode, body) {
247
+ if (typeof body === "object" && body !== null && "title" in body && typeof body.title === "string") {
248
+ return new _SicrediApiError(statusCode, body);
249
+ }
250
+ const fallback = {
251
+ title: "Unknown API Error",
252
+ status: statusCode,
253
+ detail: typeof body === "string" ? body : JSON.stringify(body)
254
+ };
255
+ return new _SicrediApiError(statusCode, fallback);
256
+ }
257
+ };
258
+
259
+ // src/errors/auth-error.ts
260
+ init_base();
261
+ var SicrediAuthError = class _SicrediAuthError extends exports.SicrediError {
262
+ constructor(message, hint) {
263
+ super(message, "AUTH_ERROR", hint);
264
+ this.name = "SicrediAuthError";
265
+ Object.setPrototypeOf(this, new.target.prototype);
266
+ }
267
+ static invalidCredentials() {
268
+ return new _SicrediAuthError(
269
+ "Invalid credentials",
270
+ "Check that your clientId and clientSecret are correct and have not been revoked."
271
+ );
272
+ }
273
+ static tokenExpired() {
274
+ return new _SicrediAuthError(
275
+ "Access token has expired",
276
+ "The token will be automatically refreshed on the next request. If this persists, re-authenticate."
277
+ );
278
+ }
279
+ static insufficientScope(required) {
280
+ return new _SicrediAuthError(
281
+ "Insufficient scope for this operation",
282
+ `This operation requires the following scope: ${required}. Ensure your credentials are provisioned with the necessary permissions.`
283
+ );
284
+ }
285
+ };
286
+
287
+ // src/utils/constants.ts
288
+ var SICREDI_URLS = {
289
+ production: "https://api-pix.sicredi.com.br",
290
+ sandbox: "https://api-pix-h.sicredi.com.br"
291
+ };
292
+ var SICREDI_ISPB = "01181521";
293
+ var OAUTH_SCOPES = "cob.write cob.read cobv.write cobv.read pix.read webhook.read webhook.write lotecobv.write lotecobv.read";
294
+ var API_VERSIONS = {
295
+ cob: {
296
+ create: "/api/v2/cob",
297
+ get: "/api/v3/cob",
298
+ // NOTE: GET uses v3!
299
+ update: "/api/v2/cob",
300
+ list: "/api/v2/cob"
301
+ },
302
+ cobv: {
303
+ create: "/api/v2/cobv",
304
+ get: "/api/v2/cobv",
305
+ update: "/api/v2/cobv",
306
+ list: "/api/v2/cobv"
307
+ },
308
+ pix: {
309
+ base: "/api/v2/pix"
310
+ },
311
+ lotecobv: {
312
+ base: "/api/v2/lotecobv"
313
+ },
314
+ loc: {
315
+ base: "/api/v2/loc"
316
+ },
317
+ webhook: {
318
+ base: "/api/v2/webhook"
319
+ }
320
+ };
321
+ var TOKEN_ENDPOINT = "/oauth/token";
322
+ var DEFAULT_TIMEOUT = 3e4;
323
+ var DEFAULT_MAX_RETRIES = 3;
324
+ var TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
325
+
326
+ // src/core/auth-manager.ts
327
+ var AuthManager = class {
328
+ constructor(clientId, clientSecret, baseUrl, httpClient) {
329
+ this.clientId = clientId;
330
+ this.clientSecret = clientSecret;
331
+ this.baseUrl = baseUrl;
332
+ this.httpClient = httpClient;
333
+ }
334
+ cachedToken = null;
335
+ refreshPromise = null;
336
+ async getAccessToken() {
337
+ if (this.cachedToken && !this.isTokenExpiringSoon()) {
338
+ return this.cachedToken.accessToken;
339
+ }
340
+ if (this.refreshPromise) {
341
+ return this.refreshPromise;
342
+ }
343
+ this.refreshPromise = this.refreshToken();
344
+ try {
345
+ return await this.refreshPromise;
346
+ } finally {
347
+ this.refreshPromise = null;
348
+ }
349
+ }
350
+ invalidateToken() {
351
+ this.cachedToken = null;
352
+ }
353
+ isTokenExpiringSoon() {
354
+ if (!this.cachedToken) return true;
355
+ return Date.now() >= this.cachedToken.expiresAt - TOKEN_REFRESH_BUFFER_MS;
356
+ }
357
+ async refreshToken() {
358
+ const credentials = btoa(`${this.clientId}:${this.clientSecret}`);
359
+ const scopes = encodeURIComponent(OAUTH_SCOPES);
360
+ const url = `${this.baseUrl}${TOKEN_ENDPOINT}?grant_type=client_credentials&scope=${scopes}`;
361
+ const response = await this.httpClient.request({
362
+ method: "POST",
363
+ url,
364
+ headers: {
365
+ Authorization: `Basic ${credentials}`,
366
+ "Content-Type": "application/x-www-form-urlencoded"
367
+ }
368
+ });
369
+ if (response.status !== 200) {
370
+ let body;
371
+ try {
372
+ body = JSON.parse(response.body);
373
+ } catch {
374
+ }
375
+ if (response.status === 401 || response.status === 403) {
376
+ throw SicrediAuthError.invalidCredentials();
377
+ }
378
+ throw SicrediApiError.fromResponse(response.status, body);
379
+ }
380
+ let tokenData;
381
+ try {
382
+ tokenData = JSON.parse(response.body);
383
+ } catch {
384
+ throw new SicrediAuthError("Invalid token response from server");
385
+ }
386
+ this.cachedToken = {
387
+ accessToken: tokenData.access_token,
388
+ expiresAt: Date.now() + tokenData.expires_in * 1e3,
389
+ scope: tokenData.scope
390
+ };
391
+ return this.cachedToken.accessToken;
392
+ }
393
+ };
394
+
395
+ // src/errors/certificate-error.ts
396
+ init_base();
397
+ var SicrediCertificateError = class _SicrediCertificateError extends exports.SicrediError {
398
+ constructor(message, hint) {
399
+ super(message, "CERTIFICATE_ERROR", hint);
400
+ this.name = "SicrediCertificateError";
401
+ Object.setPrototypeOf(this, new.target.prototype);
402
+ }
403
+ static notFound(path) {
404
+ return new _SicrediCertificateError(
405
+ `Certificate file not found: ${path}`,
406
+ "Verify that the file exists at the specified path and that the process has read permissions."
407
+ );
408
+ }
409
+ static invalidFormat(detail) {
410
+ return new _SicrediCertificateError(
411
+ `Invalid certificate format: ${detail}`,
412
+ "Certificate appears to be in DER format. Convert to PEM using: openssl x509 -inform der -in cert.cer -out cert.pem"
413
+ );
414
+ }
415
+ static keyMismatch() {
416
+ return new _SicrediCertificateError(
417
+ "Private key does not match the certificate",
418
+ "Ensure the private key corresponds to the public key in the certificate. Verify with: openssl x509 -noout -modulus -in cert.pem | openssl md5 && openssl rsa -noout -modulus -in key.pem | openssl md5"
419
+ );
420
+ }
421
+ static expired() {
422
+ return new _SicrediCertificateError(
423
+ "Certificate has expired",
424
+ "Request a new certificate from Sicredi and update your configuration."
425
+ );
426
+ }
427
+ };
428
+
429
+ // src/core/certificate-manager.ts
430
+ var PEM_HEADER_PATTERN = /-----BEGIN [A-Z\s]+-----/;
431
+ var DER_SIGNATURE = [48, 130];
432
+ function isPemContent(content) {
433
+ return PEM_HEADER_PATTERN.test(content);
434
+ }
435
+ function isDerContent(buffer) {
436
+ return buffer.length > 2 && buffer[0] === DER_SIGNATURE[0] && buffer[1] === DER_SIGNATURE[1];
437
+ }
438
+ function loadCertificateContent(input, label) {
439
+ if (isPemContent(input)) {
440
+ return input;
441
+ }
442
+ if (!fs.existsSync(input)) {
443
+ throw SicrediCertificateError.notFound(input);
444
+ }
445
+ const raw = fs.readFileSync(input);
446
+ const text = raw.toString("utf-8");
447
+ if (isPemContent(text)) {
448
+ return text;
449
+ }
450
+ if (isDerContent(raw)) {
451
+ throw SicrediCertificateError.invalidFormat(
452
+ `${label} at "${input}" appears to be in DER format`
453
+ );
454
+ }
455
+ return raw;
456
+ }
457
+ var CertificateManager = class {
458
+ constructor(options) {
459
+ this.options = options;
460
+ }
461
+ resolved = null;
462
+ resolve() {
463
+ if (this.resolved) {
464
+ return this.resolved;
465
+ }
466
+ const cert = loadCertificateContent(this.options.cert, "Certificate");
467
+ const key = loadCertificateContent(this.options.key, "Private key");
468
+ const ca = this.options.ca ? loadCertificateContent(this.options.ca, "CA certificate") : void 0;
469
+ this.resolved = {
470
+ cert,
471
+ key,
472
+ ca,
473
+ passphrase: this.options.passphrase
474
+ };
475
+ return this.resolved;
476
+ }
477
+ clear() {
478
+ this.resolved = null;
479
+ }
480
+ };
481
+
482
+ // src/core/http-client.ts
483
+ function isBunRuntime() {
484
+ return typeof globalThis !== "undefined" && "Bun" in globalThis;
485
+ }
486
+ async function createHttpClient(config) {
487
+ if (isBunRuntime()) {
488
+ const { BunHttpClient: BunHttpClient2 } = await Promise.resolve().then(() => (init_http_client_bun(), http_client_bun_exports));
489
+ return new BunHttpClient2(config);
490
+ }
491
+ const { NodeHttpClient: NodeHttpClient2 } = await Promise.resolve().then(() => (init_http_client_node(), http_client_node_exports));
492
+ return new NodeHttpClient2(config);
493
+ }
494
+
495
+ // src/errors/validation-error.ts
496
+ init_base();
497
+ var SicrediValidationError = class extends exports.SicrediError {
498
+ field;
499
+ constraint;
500
+ constructor(field, constraint, hint) {
501
+ super(`Validation failed for field '${field}': ${constraint}`, "VALIDATION_ERROR", hint);
502
+ this.name = "SicrediValidationError";
503
+ this.field = field;
504
+ this.constraint = constraint;
505
+ Object.setPrototypeOf(this, new.target.prototype);
506
+ }
507
+ };
508
+
509
+ // src/utils/txid.ts
510
+ var TXID_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
511
+ var TXID_MIN_LENGTH = 26;
512
+ var TXID_MAX_LENGTH = 35;
513
+ var TXID_PATTERN = /^[a-zA-Z0-9]{26,35}$/;
514
+ function generateTxId(length = 35) {
515
+ if (length < TXID_MIN_LENGTH || length > TXID_MAX_LENGTH) {
516
+ throw new Error(`txid length must be between ${TXID_MIN_LENGTH} and ${TXID_MAX_LENGTH}`);
517
+ }
518
+ const bytes = new Uint8Array(length);
519
+ crypto.getRandomValues(bytes);
520
+ let result = "";
521
+ for (let i = 0; i < length; i++) {
522
+ result += TXID_CHARS[bytes[i] % TXID_CHARS.length];
523
+ }
524
+ return result;
525
+ }
526
+ function isValidTxId(txid) {
527
+ return TXID_PATTERN.test(txid);
528
+ }
529
+
530
+ // src/core/retry.ts
531
+ init_connection_error();
532
+ var DEFAULT_BASE_DELAY_MS = 500;
533
+ var DEFAULT_MAX_DELAY_MS = 15e3;
534
+ var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([408, 429, 500, 502, 503, 504]);
535
+ function isRetryableStatusCode(statusCode) {
536
+ return RETRYABLE_STATUS_CODES.has(statusCode);
537
+ }
538
+ function isRetryableError(error) {
539
+ if (error instanceof exports.SicrediConnectionError) {
540
+ return true;
541
+ }
542
+ if (error instanceof Error) {
543
+ const msg = error.message.toLowerCase();
544
+ return msg.includes("econnreset") || msg.includes("econnrefused") || msg.includes("etimedout") || msg.includes("socket hang up") || msg.includes("network");
545
+ }
546
+ return false;
547
+ }
548
+ function calculateDelay(attempt, baseDelayMs, maxDelayMs) {
549
+ const exponentialDelay = baseDelayMs * 2 ** attempt;
550
+ const jitter = Math.random() * baseDelayMs;
551
+ return Math.min(exponentialDelay + jitter, maxDelayMs);
552
+ }
553
+ function sleep(ms) {
554
+ return new Promise((resolve) => setTimeout(resolve, ms));
555
+ }
556
+ async function withRetry(fn, options) {
557
+ const {
558
+ maxRetries,
559
+ baseDelayMs = DEFAULT_BASE_DELAY_MS,
560
+ maxDelayMs = DEFAULT_MAX_DELAY_MS
561
+ } = options;
562
+ let lastError;
563
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
564
+ try {
565
+ return await fn();
566
+ } catch (error) {
567
+ lastError = error;
568
+ if (attempt >= maxRetries) {
569
+ break;
570
+ }
571
+ if (!isRetryableError(error)) {
572
+ break;
573
+ }
574
+ const delay = calculateDelay(attempt, baseDelayMs, maxDelayMs);
575
+ await sleep(delay);
576
+ }
577
+ }
578
+ throw lastError;
579
+ }
580
+
581
+ // src/resources/base.ts
582
+ var BaseResource = class {
583
+ baseUrl;
584
+ httpClient;
585
+ authManager;
586
+ retryOptions;
587
+ debug;
588
+ constructor(config) {
589
+ this.baseUrl = config.baseUrl;
590
+ this.httpClient = config.httpClient;
591
+ this.authManager = config.authManager;
592
+ this.retryOptions = config.retryOptions;
593
+ this.debug = config.debug;
594
+ }
595
+ async request(method, path, body, query) {
596
+ return withRetry(async () => {
597
+ const token = await this.authManager.getAccessToken();
598
+ const url = this.buildUrl(path, query);
599
+ const response = await this.httpClient.request({
600
+ method,
601
+ url,
602
+ headers: {
603
+ Authorization: `Bearer ${token}`,
604
+ "Content-Type": "application/json",
605
+ Accept: "application/json"
606
+ },
607
+ body: body ? JSON.stringify(body) : void 0
608
+ });
609
+ if (response.status === 401 || response.status === 403) {
610
+ this.authManager.invalidateToken();
611
+ throw response.status === 401 ? SicrediAuthError.tokenExpired() : SicrediAuthError.insufficientScope("required scope");
612
+ }
613
+ if (response.status >= 400) {
614
+ let parsedBody;
615
+ try {
616
+ parsedBody = JSON.parse(response.body);
617
+ } catch {
618
+ parsedBody = {
619
+ title: "Unknown error",
620
+ status: response.status,
621
+ detail: response.body
622
+ };
623
+ }
624
+ const error = SicrediApiError.fromResponse(response.status, parsedBody);
625
+ if (isRetryableStatusCode(response.status)) {
626
+ throw error;
627
+ }
628
+ throw error;
629
+ }
630
+ if (response.status === 204 || !response.body) {
631
+ return void 0;
632
+ }
633
+ try {
634
+ return JSON.parse(response.body);
635
+ } catch {
636
+ return response.body;
637
+ }
638
+ }, this.retryOptions);
639
+ }
640
+ buildUrl(path, query) {
641
+ const url = new URL(path, this.baseUrl);
642
+ if (query) {
643
+ for (const [key, value] of Object.entries(query)) {
644
+ if (value !== void 0) {
645
+ url.searchParams.set(key, String(value));
646
+ }
647
+ }
648
+ }
649
+ return url.toString();
650
+ }
651
+ };
652
+
653
+ // src/resources/cob.ts
654
+ var CobResource = class extends BaseResource {
655
+ /**
656
+ * Create a PIX immediate charge with a specific txid.
657
+ * PUT /api/v2/cob/{txid}
658
+ */
659
+ async create(txid, data) {
660
+ if (!isValidTxId(txid)) {
661
+ throw new SicrediValidationError("txid", "Must be 26-35 alphanumeric characters");
662
+ }
663
+ return this.request("PUT", `${API_VERSIONS.cob.create}/${txid}`, data);
664
+ }
665
+ /**
666
+ * Create a PIX immediate charge with auto-generated txid.
667
+ * POST /api/v2/cob
668
+ */
669
+ async createAuto(data) {
670
+ return this.request("POST", API_VERSIONS.cob.create, data);
671
+ }
672
+ /**
673
+ * Get a PIX immediate charge by txid.
674
+ * GET /api/v3/cob/{txid} (note: v3!)
675
+ */
676
+ async get(txid, revisao) {
677
+ if (!isValidTxId(txid)) {
678
+ throw new SicrediValidationError("txid", "Must be 26-35 alphanumeric characters");
679
+ }
680
+ return this.request("GET", `${API_VERSIONS.cob.get}/${txid}`, void 0, {
681
+ revisao
682
+ });
683
+ }
684
+ /**
685
+ * Update (patch) a PIX immediate charge.
686
+ * PATCH /api/v2/cob/{txid}
687
+ */
688
+ async update(txid, data) {
689
+ if (!isValidTxId(txid)) {
690
+ throw new SicrediValidationError("txid", "Must be 26-35 alphanumeric characters");
691
+ }
692
+ return this.request("PATCH", `${API_VERSIONS.cob.update}/${txid}`, data);
693
+ }
694
+ /**
695
+ * Cancel a PIX immediate charge by setting status to REMOVIDA_PELO_USUARIO_RECEBEDOR.
696
+ * PATCH /api/v2/cob/{txid}
697
+ */
698
+ async cancel(txid) {
699
+ return this.update(txid, { status: "REMOVIDA_PELO_USUARIO_RECEBEDOR" });
700
+ }
701
+ /**
702
+ * List PIX immediate charges with filters.
703
+ * GET /api/v2/cob
704
+ */
705
+ async list(params) {
706
+ const query = {
707
+ inicio: params.inicio,
708
+ fim: params.fim,
709
+ cpf: params.cpf,
710
+ cnpj: params.cnpj,
711
+ locationPresente: params.locationPresente,
712
+ status: params.status,
713
+ "paginacao.paginaAtual": params.paginacao?.paginaAtual,
714
+ "paginacao.itensPorPagina": params.paginacao?.itensPorPagina
715
+ };
716
+ return this.request("GET", API_VERSIONS.cob.list, void 0, query);
717
+ }
718
+ /**
719
+ * Generate a txid (helper utility).
720
+ */
721
+ generateTxId(length) {
722
+ return generateTxId(length);
723
+ }
724
+ };
725
+
726
+ // src/resources/cobv.ts
727
+ var CobvResource = class extends BaseResource {
728
+ /**
729
+ * Create a Boleto Hibrido (PIX with due date) charge.
730
+ * PUT /api/v2/cobv/{txid}
731
+ */
732
+ async create(txid, data) {
733
+ if (!isValidTxId(txid)) {
734
+ throw new SicrediValidationError("txid", "Must be 26-35 alphanumeric characters");
735
+ }
736
+ return this.request("PUT", `${API_VERSIONS.cobv.create}/${txid}`, data);
737
+ }
738
+ /**
739
+ * Get a Boleto Hibrido charge by txid.
740
+ * GET /api/v2/cobv/{txid}
741
+ */
742
+ async get(txid, revisao) {
743
+ if (!isValidTxId(txid)) {
744
+ throw new SicrediValidationError("txid", "Must be 26-35 alphanumeric characters");
745
+ }
746
+ return this.request("GET", `${API_VERSIONS.cobv.get}/${txid}`, void 0, {
747
+ revisao
748
+ });
749
+ }
750
+ /**
751
+ * Update (patch) a Boleto Hibrido charge.
752
+ * PATCH /api/v2/cobv/{txid}
753
+ */
754
+ async update(txid, data) {
755
+ if (!isValidTxId(txid)) {
756
+ throw new SicrediValidationError("txid", "Must be 26-35 alphanumeric characters");
757
+ }
758
+ return this.request("PATCH", `${API_VERSIONS.cobv.update}/${txid}`, data);
759
+ }
760
+ /**
761
+ * Cancel a Boleto Hibrido charge.
762
+ * PATCH /api/v2/cobv/{txid}
763
+ */
764
+ async cancel(txid) {
765
+ return this.update(txid, { status: "REMOVIDA_PELO_USUARIO_RECEBEDOR" });
766
+ }
767
+ /**
768
+ * List Boleto Hibrido charges with filters.
769
+ * GET /api/v2/cobv
770
+ */
771
+ async list(params) {
772
+ const query = {
773
+ inicio: params.inicio,
774
+ fim: params.fim,
775
+ cpf: params.cpf,
776
+ cnpj: params.cnpj,
777
+ locationPresente: params.locationPresente,
778
+ status: params.status,
779
+ loteCobVId: params.loteCobVId,
780
+ "paginacao.paginaAtual": params.paginacao?.paginaAtual,
781
+ "paginacao.itensPorPagina": params.paginacao?.itensPorPagina
782
+ };
783
+ return this.request("GET", API_VERSIONS.cobv.list, void 0, query);
784
+ }
785
+ };
786
+
787
+ // src/resources/loc.ts
788
+ var LocResource = class extends BaseResource {
789
+ /**
790
+ * Create a payload location.
791
+ * POST /api/v2/loc
792
+ */
793
+ async create(data) {
794
+ return this.request("POST", API_VERSIONS.loc.base, data);
795
+ }
796
+ /**
797
+ * Get a payload location by ID.
798
+ * GET /api/v2/loc/{id}
799
+ */
800
+ async get(id) {
801
+ return this.request("GET", `${API_VERSIONS.loc.base}/${id}`);
802
+ }
803
+ /**
804
+ * List payload locations.
805
+ * GET /api/v2/loc
806
+ */
807
+ async list(params) {
808
+ const query = {
809
+ inicio: params.inicio,
810
+ fim: params.fim,
811
+ tipoCob: params.tipoCob,
812
+ txIdPresente: params.txIdPresente,
813
+ "paginacao.paginaAtual": params.paginacao?.paginaAtual,
814
+ "paginacao.itensPorPagina": params.paginacao?.itensPorPagina
815
+ };
816
+ return this.request("GET", API_VERSIONS.loc.base, void 0, query);
817
+ }
818
+ /**
819
+ * Unlink a charge from a payload location.
820
+ * DELETE /api/v2/loc/{id}/txid
821
+ */
822
+ async unlink(id) {
823
+ return this.request("DELETE", `${API_VERSIONS.loc.base}/${id}/txid`);
824
+ }
825
+ };
826
+
827
+ // src/resources/lotecobv.ts
828
+ var LoteCobvResource = class extends BaseResource {
829
+ /**
830
+ * Create or replace a batch of cobv charges.
831
+ * PUT /api/v2/lotecobv/{id}
832
+ */
833
+ async create(id, data) {
834
+ await this.request("PUT", `${API_VERSIONS.lotecobv.base}/${id}`, data);
835
+ }
836
+ /**
837
+ * Revise specific charges within a batch.
838
+ * PATCH /api/v2/lotecobv/{id}
839
+ */
840
+ async update(id, data) {
841
+ await this.request("PATCH", `${API_VERSIONS.lotecobv.base}/${id}`, data);
842
+ }
843
+ /**
844
+ * Query a specific batch of cobv charges.
845
+ * GET /api/v2/lotecobv/{id}
846
+ */
847
+ async get(id) {
848
+ return this.request("GET", `${API_VERSIONS.lotecobv.base}/${id}`);
849
+ }
850
+ /**
851
+ * List batches of cobv charges.
852
+ * GET /api/v2/lotecobv
853
+ */
854
+ async list(params) {
855
+ const query = {
856
+ inicio: params.inicio,
857
+ fim: params.fim,
858
+ "paginacao.paginaAtual": params.paginacao?.paginaAtual,
859
+ "paginacao.itensPorPagina": params.paginacao?.itensPorPagina
860
+ };
861
+ return this.request("GET", API_VERSIONS.lotecobv.base, void 0, query);
862
+ }
863
+ };
864
+
865
+ // src/resources/pix.ts
866
+ var PixResource = class extends BaseResource {
867
+ /**
868
+ * Query a received PIX payment by its end-to-end ID.
869
+ * GET /api/v2/pix/{e2eid}
870
+ */
871
+ async get(e2eid) {
872
+ return this.request("GET", `${API_VERSIONS.pix.base}/${e2eid}`);
873
+ }
874
+ /**
875
+ * List received PIX payments with filters.
876
+ * GET /api/v2/pix
877
+ */
878
+ async list(params) {
879
+ const query = {
880
+ inicio: params.inicio,
881
+ fim: params.fim,
882
+ txid: params.txid,
883
+ txIdPresente: params.txIdPresente,
884
+ devolucaoPresente: params.devolucaoPresente,
885
+ cpf: params.cpf,
886
+ cnpj: params.cnpj,
887
+ "paginacao.paginaAtual": params.paginacao?.paginaAtual,
888
+ "paginacao.itensPorPagina": params.paginacao?.itensPorPagina
889
+ };
890
+ return this.request("GET", API_VERSIONS.pix.base, void 0, query);
891
+ }
892
+ /**
893
+ * Request a refund/return for a received PIX payment.
894
+ * PUT /api/v2/pix/{e2eid}/devolucao/{id}
895
+ */
896
+ async requestReturn(e2eid, id, data) {
897
+ return this.request(
898
+ "PUT",
899
+ `${API_VERSIONS.pix.base}/${e2eid}/devolucao/${id}`,
900
+ data
901
+ );
902
+ }
903
+ /**
904
+ * Query the status of a refund/return.
905
+ * GET /api/v2/pix/{e2eid}/devolucao/{id}
906
+ */
907
+ async getReturn(e2eid, id) {
908
+ return this.request(
909
+ "GET",
910
+ `${API_VERSIONS.pix.base}/${e2eid}/devolucao/${id}`
911
+ );
912
+ }
913
+ };
914
+
915
+ // src/resources/webhook.ts
916
+ var WebhookResource = class extends BaseResource {
917
+ /**
918
+ * Configure a webhook for a PIX key.
919
+ * PUT /api/v2/webhook/{chave}
920
+ */
921
+ async configure(chave, webhookUrl) {
922
+ const body = { webhookUrl };
923
+ await this.request("PUT", `${API_VERSIONS.webhook.base}/${chave}`, body);
924
+ }
925
+ /**
926
+ * Get webhook configuration for a PIX key.
927
+ * GET /api/v2/webhook/{chave}
928
+ */
929
+ async get(chave) {
930
+ return this.request("GET", `${API_VERSIONS.webhook.base}/${chave}`);
931
+ }
932
+ /**
933
+ * Delete webhook configuration for a PIX key.
934
+ * DELETE /api/v2/webhook/{chave}
935
+ */
936
+ async delete(chave) {
937
+ await this.request("DELETE", `${API_VERSIONS.webhook.base}/${chave}`);
938
+ }
939
+ /**
940
+ * List all webhook configurations.
941
+ * GET /api/v2/webhook
942
+ */
943
+ async list(params) {
944
+ const query = {
945
+ inicio: params.inicio,
946
+ fim: params.fim,
947
+ "paginacao.paginaAtual": params.paginacao?.paginaAtual,
948
+ "paginacao.itensPorPagina": params.paginacao?.itensPorPagina
949
+ };
950
+ return this.request("GET", API_VERSIONS.webhook.base, void 0, query);
951
+ }
952
+ };
953
+
954
+ // src/client.ts
955
+ var PROXY_PASSTHROUGH = /* @__PURE__ */ new Set(["then", "catch", "finally", "toJSON", "toString", "valueOf"]);
956
+ var Sicredi = class {
957
+ cob;
958
+ cobv;
959
+ pix;
960
+ lotecobv;
961
+ loc;
962
+ webhook;
963
+ _config;
964
+ _initPromise = null;
965
+ _cob = null;
966
+ _cobv = null;
967
+ _pix = null;
968
+ _lotecobv = null;
969
+ _loc = null;
970
+ _webhook = null;
971
+ constructor(config) {
972
+ this._config = {
973
+ ...config,
974
+ environment: config.environment ?? "production",
975
+ timeout: config.timeout ?? DEFAULT_TIMEOUT,
976
+ maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,
977
+ debug: config.debug ?? false
978
+ };
979
+ const self = this;
980
+ this.cob = new Proxy({}, {
981
+ get(_target, prop) {
982
+ if (typeof prop !== "string" || PROXY_PASSTHROUGH.has(prop)) return void 0;
983
+ return async (...args) => {
984
+ await self._ensureInit();
985
+ const method = self._cob[prop];
986
+ if (typeof method === "function") {
987
+ return method.apply(self._cob, args);
988
+ }
989
+ return method;
990
+ };
991
+ }
992
+ });
993
+ this.cobv = new Proxy({}, {
994
+ get(_target, prop) {
995
+ if (typeof prop !== "string" || PROXY_PASSTHROUGH.has(prop)) return void 0;
996
+ return async (...args) => {
997
+ await self._ensureInit();
998
+ const method = self._cobv[prop];
999
+ if (typeof method === "function") {
1000
+ return method.apply(self._cobv, args);
1001
+ }
1002
+ return method;
1003
+ };
1004
+ }
1005
+ });
1006
+ this.pix = new Proxy({}, {
1007
+ get(_target, prop) {
1008
+ if (typeof prop !== "string" || PROXY_PASSTHROUGH.has(prop)) return void 0;
1009
+ return async (...args) => {
1010
+ await self._ensureInit();
1011
+ const method = self._pix[prop];
1012
+ if (typeof method === "function") {
1013
+ return method.apply(self._pix, args);
1014
+ }
1015
+ return method;
1016
+ };
1017
+ }
1018
+ });
1019
+ this.lotecobv = new Proxy({}, {
1020
+ get(_target, prop) {
1021
+ if (typeof prop !== "string" || PROXY_PASSTHROUGH.has(prop)) return void 0;
1022
+ return async (...args) => {
1023
+ await self._ensureInit();
1024
+ const method = self._lotecobv[prop];
1025
+ if (typeof method === "function") {
1026
+ return method.apply(self._lotecobv, args);
1027
+ }
1028
+ return method;
1029
+ };
1030
+ }
1031
+ });
1032
+ this.loc = new Proxy({}, {
1033
+ get(_target, prop) {
1034
+ if (typeof prop !== "string" || PROXY_PASSTHROUGH.has(prop)) return void 0;
1035
+ return async (...args) => {
1036
+ await self._ensureInit();
1037
+ const method = self._loc[prop];
1038
+ if (typeof method === "function") {
1039
+ return method.apply(self._loc, args);
1040
+ }
1041
+ return method;
1042
+ };
1043
+ }
1044
+ });
1045
+ this.webhook = new Proxy({}, {
1046
+ get(_target, prop) {
1047
+ if (typeof prop !== "string" || PROXY_PASSTHROUGH.has(prop)) return void 0;
1048
+ return async (...args) => {
1049
+ await self._ensureInit();
1050
+ const method = self._webhook[prop];
1051
+ if (typeof method === "function") {
1052
+ return method.apply(self._webhook, args);
1053
+ }
1054
+ return method;
1055
+ };
1056
+ }
1057
+ });
1058
+ }
1059
+ get baseUrl() {
1060
+ return this._config.baseUrl ?? SICREDI_URLS[this._config.environment];
1061
+ }
1062
+ async _ensureInit() {
1063
+ if (this._cob) return;
1064
+ if (!this._initPromise) {
1065
+ this._initPromise = this._initialize().catch((err) => {
1066
+ this._initPromise = null;
1067
+ throw err;
1068
+ });
1069
+ }
1070
+ await this._initPromise;
1071
+ }
1072
+ async _initialize() {
1073
+ const certManager = new CertificateManager(this._config.certificate);
1074
+ const certificates = certManager.resolve();
1075
+ const httpClient = await createHttpClient({
1076
+ certificates,
1077
+ timeout: this._config.timeout,
1078
+ debug: this._config.debug
1079
+ });
1080
+ const authManager = new AuthManager(
1081
+ this._config.clientId,
1082
+ this._config.clientSecret,
1083
+ this.baseUrl,
1084
+ httpClient
1085
+ );
1086
+ const resourceConfig = {
1087
+ baseUrl: this.baseUrl,
1088
+ httpClient,
1089
+ authManager,
1090
+ retryOptions: { maxRetries: this._config.maxRetries },
1091
+ debug: this._config.debug
1092
+ };
1093
+ this._cob = new CobResource(resourceConfig);
1094
+ this._cobv = new CobvResource(resourceConfig);
1095
+ this._pix = new PixResource(resourceConfig);
1096
+ this._lotecobv = new LoteCobvResource(resourceConfig);
1097
+ this._loc = new LocResource(resourceConfig);
1098
+ this._webhook = new WebhookResource(resourceConfig);
1099
+ }
1100
+ };
1101
+
1102
+ // src/errors/index.ts
1103
+ init_base();
1104
+ init_connection_error();
1105
+
1106
+ // src/utils/validators.ts
1107
+ function isValidCpf(cpf) {
1108
+ const stripped = cpf.replace(/\D/g, "");
1109
+ if (stripped.length !== 11) {
1110
+ return false;
1111
+ }
1112
+ if (/^(\d)\1{10}$/.test(stripped)) {
1113
+ return false;
1114
+ }
1115
+ let sum = 0;
1116
+ for (let i = 0; i < 9; i++) {
1117
+ sum += Number.parseInt(stripped[i], 10) * (10 - i);
1118
+ }
1119
+ let remainder = sum * 10 % 11;
1120
+ if (remainder === 10) remainder = 0;
1121
+ if (remainder !== Number.parseInt(stripped[9], 10)) {
1122
+ return false;
1123
+ }
1124
+ sum = 0;
1125
+ for (let i = 0; i < 10; i++) {
1126
+ sum += Number.parseInt(stripped[i], 10) * (11 - i);
1127
+ }
1128
+ remainder = sum * 10 % 11;
1129
+ if (remainder === 10) remainder = 0;
1130
+ if (remainder !== Number.parseInt(stripped[10], 10)) {
1131
+ return false;
1132
+ }
1133
+ return true;
1134
+ }
1135
+ function isValidCnpj(cnpj) {
1136
+ const stripped = cnpj.replace(/\D/g, "");
1137
+ if (stripped.length !== 14) {
1138
+ return false;
1139
+ }
1140
+ if (/^(\d)\1{13}$/.test(stripped)) {
1141
+ return false;
1142
+ }
1143
+ const weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
1144
+ let sum = 0;
1145
+ for (let i = 0; i < 12; i++) {
1146
+ sum += Number.parseInt(stripped[i], 10) * weights1[i];
1147
+ }
1148
+ let remainder = sum % 11;
1149
+ const digit1 = remainder < 2 ? 0 : 11 - remainder;
1150
+ if (digit1 !== Number.parseInt(stripped[12], 10)) {
1151
+ return false;
1152
+ }
1153
+ const weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
1154
+ sum = 0;
1155
+ for (let i = 0; i < 13; i++) {
1156
+ sum += Number.parseInt(stripped[i], 10) * weights2[i];
1157
+ }
1158
+ remainder = sum % 11;
1159
+ const digit2 = remainder < 2 ? 0 : 11 - remainder;
1160
+ if (digit2 !== Number.parseInt(stripped[13], 10)) {
1161
+ return false;
1162
+ }
1163
+ return true;
1164
+ }
1165
+ var EVP_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1166
+ var PHONE_PATTERN = /^\+55\d{10,11}$/;
1167
+ var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1168
+ function detectPixKeyType(key) {
1169
+ const digitsOnly = key.replace(/\D/g, "");
1170
+ if (EVP_PATTERN.test(key)) {
1171
+ return "evp";
1172
+ }
1173
+ if (PHONE_PATTERN.test(key)) {
1174
+ return "phone";
1175
+ }
1176
+ if (EMAIL_PATTERN.test(key)) {
1177
+ return "email";
1178
+ }
1179
+ if (digitsOnly.length === 11 && digitsOnly === key && isValidCpf(key)) {
1180
+ return "cpf";
1181
+ }
1182
+ if (digitsOnly.length === 14 && digitsOnly === key && isValidCnpj(key)) {
1183
+ return "cnpj";
1184
+ }
1185
+ return null;
1186
+ }
1187
+ function isValidPixKey(key) {
1188
+ return detectPixKeyType(key) !== null;
1189
+ }
1190
+ function isValidMonetaryValue(value) {
1191
+ return /^\d+\.\d{2}$/.test(value);
1192
+ }
1193
+
1194
+ // src/utils/qrcode.ts
1195
+ var ALIGNMENT_PATTERNS = {
1196
+ 2: [6, 18],
1197
+ 3: [6, 22],
1198
+ 4: [6, 26],
1199
+ 5: [6, 30],
1200
+ 6: [6, 34],
1201
+ 7: [6, 22, 38],
1202
+ 8: [6, 24, 42],
1203
+ 9: [6, 26, 46],
1204
+ 10: [6, 28, 50]
1205
+ };
1206
+ var MODE_BYTE = 4;
1207
+ var CAPACITY_M = {
1208
+ 1: 14,
1209
+ 2: 26,
1210
+ 3: 42,
1211
+ 4: 62,
1212
+ 5: 84,
1213
+ 6: 106,
1214
+ 7: 122,
1215
+ 8: 152,
1216
+ 9: 180,
1217
+ 10: 213
1218
+ };
1219
+ function getMinVersion(dataLength) {
1220
+ for (let v = 1; v <= 10; v++) {
1221
+ const cap = CAPACITY_M[v];
1222
+ if (cap !== void 0 && dataLength <= cap) {
1223
+ return v;
1224
+ }
1225
+ }
1226
+ throw new Error(`Data too long for QR code (max ~213 bytes). Got ${dataLength} bytes.`);
1227
+ }
1228
+ function getModuleCount(version) {
1229
+ return 17 + version * 4;
1230
+ }
1231
+ function generateQrCodeSvg(data, options = {}) {
1232
+ const { size = 256, margin = 4, darkColor = "#000000", lightColor = "#FFFFFF" } = options;
1233
+ const bytes = new TextEncoder().encode(data);
1234
+ const version = getMinVersion(bytes.length);
1235
+ const moduleCount = getModuleCount(version);
1236
+ const matrix = createQrMatrix(bytes, version, moduleCount);
1237
+ const cellSize = size / (moduleCount + margin * 2);
1238
+ let paths = "";
1239
+ for (let row = 0; row < moduleCount; row++) {
1240
+ for (let col = 0; col < moduleCount; col++) {
1241
+ if (matrix[row]?.[col]) {
1242
+ const x = (col + margin) * cellSize;
1243
+ const y = (row + margin) * cellSize;
1244
+ paths += `M${x},${y}h${cellSize}v${cellSize}h-${cellSize}z`;
1245
+ }
1246
+ }
1247
+ }
1248
+ const totalSize = (moduleCount + margin * 2) * cellSize;
1249
+ return [
1250
+ `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${totalSize} ${totalSize}" width="${size}" height="${size}">`,
1251
+ `<rect width="${totalSize}" height="${totalSize}" fill="${lightColor}"/>`,
1252
+ `<path d="${paths}" fill="${darkColor}"/>`,
1253
+ "</svg>"
1254
+ ].join("");
1255
+ }
1256
+ function generateQrCodeDataUrl(data, options) {
1257
+ const svg = generateQrCodeSvg(data, options);
1258
+ const base64 = btoa(svg);
1259
+ return `data:image/svg+xml;base64,${base64}`;
1260
+ }
1261
+ function createQrMatrix(data, version, size) {
1262
+ const matrix = Array.from({ length: size }, () => Array(size).fill(false));
1263
+ const reserved = Array.from({ length: size }, () => Array(size).fill(false));
1264
+ placeFinderPattern(matrix, reserved, 0, 0);
1265
+ placeFinderPattern(matrix, reserved, size - 7, 0);
1266
+ placeFinderPattern(matrix, reserved, 0, size - 7);
1267
+ for (let i = 8; i < size - 8; i++) {
1268
+ const bit = i % 2 === 0;
1269
+ matrix[6][i] = bit;
1270
+ reserved[6][i] = true;
1271
+ matrix[i][6] = bit;
1272
+ reserved[i][6] = true;
1273
+ }
1274
+ if (version >= 2) {
1275
+ const positions = ALIGNMENT_PATTERNS[version];
1276
+ if (positions) {
1277
+ for (const row of positions) {
1278
+ for (const col of positions) {
1279
+ if (reserved[row]?.[col]) continue;
1280
+ placeAlignmentPattern(matrix, reserved, row, col);
1281
+ }
1282
+ }
1283
+ }
1284
+ }
1285
+ reserveFormatAreas(reserved, size);
1286
+ const dataBits = encodeDataBits(data, version);
1287
+ placeDataBits(matrix, reserved, dataBits, size);
1288
+ applyMask(matrix, reserved, size);
1289
+ return matrix;
1290
+ }
1291
+ function placeFinderPattern(matrix, reserved, row, col) {
1292
+ for (let r = -1; r <= 7; r++) {
1293
+ for (let c = -1; c <= 7; c++) {
1294
+ const mr = row + r;
1295
+ const mc = col + c;
1296
+ if (mr < 0 || mc < 0 || mr >= matrix.length || mc >= matrix.length) continue;
1297
+ let dark = false;
1298
+ if (r >= 0 && r <= 6 && c >= 0 && c <= 6) {
1299
+ if (r === 0 || r === 6 || c === 0 || c === 6) dark = true;
1300
+ else if (r >= 2 && r <= 4 && c >= 2 && c <= 4) dark = true;
1301
+ }
1302
+ matrix[mr][mc] = dark;
1303
+ reserved[mr][mc] = true;
1304
+ }
1305
+ }
1306
+ }
1307
+ function placeAlignmentPattern(matrix, reserved, centerRow, centerCol) {
1308
+ for (let r = -2; r <= 2; r++) {
1309
+ for (let c = -2; c <= 2; c++) {
1310
+ const mr = centerRow + r;
1311
+ const mc = centerCol + c;
1312
+ const dark = Math.abs(r) === 2 || Math.abs(c) === 2 || r === 0 && c === 0;
1313
+ matrix[mr][mc] = dark;
1314
+ reserved[mr][mc] = true;
1315
+ }
1316
+ }
1317
+ }
1318
+ function reserveFormatAreas(reserved, size) {
1319
+ for (let i = 0; i < 9; i++) {
1320
+ reserved[8][i] = true;
1321
+ reserved[i][8] = true;
1322
+ }
1323
+ for (let i = 0; i < 8; i++) {
1324
+ reserved[8][size - 1 - i] = true;
1325
+ }
1326
+ for (let i = 0; i < 7; i++) {
1327
+ reserved[size - 1 - i][8] = true;
1328
+ }
1329
+ reserved[size - 8][8] = true;
1330
+ }
1331
+ function encodeDataBits(data, version) {
1332
+ const bits = [];
1333
+ pushBits(bits, MODE_BYTE, 4);
1334
+ const countBits = version <= 9 ? 8 : 16;
1335
+ pushBits(bits, data.length, countBits);
1336
+ for (const byte of data) {
1337
+ pushBits(bits, byte, 8);
1338
+ }
1339
+ const capacity = (CAPACITY_M[version] ?? 0) * 8;
1340
+ const terminatorLength = Math.min(4, capacity - bits.length);
1341
+ pushBits(bits, 0, terminatorLength);
1342
+ while (bits.length % 8 !== 0) {
1343
+ bits.push(0);
1344
+ }
1345
+ let padIndex = 0;
1346
+ const padBytes = [236, 17];
1347
+ while (bits.length < capacity) {
1348
+ pushBits(bits, padBytes[padIndex % 2], 8);
1349
+ padIndex++;
1350
+ }
1351
+ return bits;
1352
+ }
1353
+ function pushBits(bits, value, count) {
1354
+ for (let i = count - 1; i >= 0; i--) {
1355
+ bits.push(value >> i & 1);
1356
+ }
1357
+ }
1358
+ function placeDataBits(matrix, reserved, bits, size) {
1359
+ let bitIndex = 0;
1360
+ let upward = true;
1361
+ for (let col = size - 1; col >= 0; col -= 2) {
1362
+ if (col === 6) col = 5;
1363
+ const rows = upward ? Array.from({ length: size }, (_, i) => size - 1 - i) : Array.from({ length: size }, (_, i) => i);
1364
+ for (const row of rows) {
1365
+ for (const c of [col, col - 1]) {
1366
+ if (c < 0) continue;
1367
+ if (reserved[row]?.[c]) continue;
1368
+ if (bitIndex < bits.length) {
1369
+ matrix[row][c] = bits[bitIndex] === 1;
1370
+ bitIndex++;
1371
+ }
1372
+ }
1373
+ }
1374
+ upward = !upward;
1375
+ }
1376
+ }
1377
+ function applyMask(matrix, reserved, size) {
1378
+ for (let row = 0; row < size; row++) {
1379
+ for (let col = 0; col < size; col++) {
1380
+ if (reserved[row]?.[col]) continue;
1381
+ if ((row + col) % 2 === 0) {
1382
+ matrix[row][col] = !matrix[row]?.[col];
1383
+ }
1384
+ }
1385
+ }
1386
+ }
1387
+
1388
+ // src/utils/date.ts
1389
+ function toISOString(date) {
1390
+ return date.toISOString();
1391
+ }
1392
+ function createDateRange(startDaysAgo = 30) {
1393
+ const fim = /* @__PURE__ */ new Date();
1394
+ const inicio = /* @__PURE__ */ new Date();
1395
+ inicio.setDate(inicio.getDate() - startDaysAgo);
1396
+ return {
1397
+ inicio: inicio.toISOString(),
1398
+ fim: fim.toISOString()
1399
+ };
1400
+ }
1401
+ function parseDate(isoString) {
1402
+ const date = new Date(isoString);
1403
+ if (Number.isNaN(date.getTime())) {
1404
+ throw new Error(`Invalid date string: ${isoString}`);
1405
+ }
1406
+ return date;
1407
+ }
1408
+ function formatDateOnly(date) {
1409
+ return date.toISOString().split("T")[0];
1410
+ }
1411
+
1412
+ // src/types/common.ts
1413
+ function isDevedorCpf(devedor) {
1414
+ return "cpf" in devedor;
1415
+ }
1416
+ function isDevedorCnpj(devedor) {
1417
+ return "cnpj" in devedor;
1418
+ }
1419
+ function isPagadorCpf(pagador) {
1420
+ return "cpf" in pagador;
1421
+ }
1422
+ function isPagadorCnpj(pagador) {
1423
+ return "cnpj" in pagador;
1424
+ }
1425
+
1426
+ // src/webhook-handler/index.ts
1427
+ function parseWebhookPayload(body) {
1428
+ let parsed;
1429
+ if (typeof body === "string") {
1430
+ try {
1431
+ parsed = JSON.parse(body);
1432
+ } catch {
1433
+ return { valid: false, error: "Invalid JSON body" };
1434
+ }
1435
+ } else {
1436
+ parsed = body;
1437
+ }
1438
+ if (!parsed || typeof parsed !== "object") {
1439
+ return { valid: false, error: "Body is not an object" };
1440
+ }
1441
+ const data = parsed;
1442
+ if (!Array.isArray(data.pix)) {
1443
+ return { valid: false, error: 'Missing or invalid "pix" array in payload' };
1444
+ }
1445
+ for (const [i, item] of data.pix.entries()) {
1446
+ if (!item || typeof item !== "object") {
1447
+ return { valid: false, error: `pix[${i}] is not an object` };
1448
+ }
1449
+ const pix = item;
1450
+ if (typeof pix.endToEndId !== "string") {
1451
+ return { valid: false, error: `pix[${i}].endToEndId is required` };
1452
+ }
1453
+ if (typeof pix.chave !== "string") {
1454
+ return { valid: false, error: `pix[${i}].chave is required` };
1455
+ }
1456
+ if (typeof pix.valor !== "string") {
1457
+ return { valid: false, error: `pix[${i}].valor is required` };
1458
+ }
1459
+ if (typeof pix.horario !== "string") {
1460
+ return { valid: false, error: `pix[${i}].horario is required` };
1461
+ }
1462
+ }
1463
+ return {
1464
+ valid: true,
1465
+ payload: parsed
1466
+ };
1467
+ }
1468
+
1469
+ exports.SICREDI_ISPB = SICREDI_ISPB;
1470
+ exports.SICREDI_URLS = SICREDI_URLS;
1471
+ exports.Sicredi = Sicredi;
1472
+ exports.SicrediApiError = SicrediApiError;
1473
+ exports.SicrediAuthError = SicrediAuthError;
1474
+ exports.SicrediCertificateError = SicrediCertificateError;
1475
+ exports.SicrediValidationError = SicrediValidationError;
1476
+ exports.createDateRange = createDateRange;
1477
+ exports.detectPixKeyType = detectPixKeyType;
1478
+ exports.formatDateOnly = formatDateOnly;
1479
+ exports.generateQrCodeDataUrl = generateQrCodeDataUrl;
1480
+ exports.generateQrCodeSvg = generateQrCodeSvg;
1481
+ exports.generateTxId = generateTxId;
1482
+ exports.isDevedorCnpj = isDevedorCnpj;
1483
+ exports.isDevedorCpf = isDevedorCpf;
1484
+ exports.isPagadorCnpj = isPagadorCnpj;
1485
+ exports.isPagadorCpf = isPagadorCpf;
1486
+ exports.isValidCnpj = isValidCnpj;
1487
+ exports.isValidCpf = isValidCpf;
1488
+ exports.isValidMonetaryValue = isValidMonetaryValue;
1489
+ exports.isValidPixKey = isValidPixKey;
1490
+ exports.isValidTxId = isValidTxId;
1491
+ exports.parseDate = parseDate;
1492
+ exports.parseWebhookPayload = parseWebhookPayload;
1493
+ exports.toISOString = toISOString;
1494
+ //# sourceMappingURL=index.cjs.map
1495
+ //# sourceMappingURL=index.cjs.map