@neetru/sdk 3.6.0 → 3.8.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.
Files changed (117) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +66 -1
  3. package/dist/ai.cjs +298 -391
  4. package/dist/ai.d.cts +1 -1
  5. package/dist/ai.d.ts +1 -1
  6. package/dist/ai.mjs +298 -391
  7. package/dist/auth.cjs +3717 -5005
  8. package/dist/auth.d.cts +1 -1
  9. package/dist/auth.d.ts +1 -1
  10. package/dist/auth.mjs +3714 -5002
  11. package/dist/build-guard.cjs +101 -119
  12. package/dist/build-guard.mjs +91 -109
  13. package/dist/catalog.cjs +220 -225
  14. package/dist/catalog.d.cts +1 -1
  15. package/dist/catalog.d.ts +1 -1
  16. package/dist/catalog.mjs +220 -225
  17. package/dist/checkout.cjs +307 -323
  18. package/dist/checkout.d.cts +1 -1
  19. package/dist/checkout.d.ts +1 -1
  20. package/dist/checkout.mjs +306 -322
  21. package/dist/db-react.cjs +59 -87
  22. package/dist/db-react.d.cts +1 -1
  23. package/dist/db-react.d.ts +1 -1
  24. package/dist/db-react.mjs +56 -84
  25. package/dist/db.cjs +2128 -3014
  26. package/dist/db.d.cts +1 -1
  27. package/dist/db.d.ts +1 -1
  28. package/dist/db.mjs +2141 -3027
  29. package/dist/entitlements.cjs +19 -20
  30. package/dist/entitlements.d.cts +1 -1
  31. package/dist/entitlements.d.ts +1 -1
  32. package/dist/entitlements.mjs +19 -20
  33. package/dist/errors.cjs +16 -12
  34. package/dist/errors.d.cts +59 -3
  35. package/dist/errors.d.ts +59 -3
  36. package/dist/errors.mjs +15 -12
  37. package/dist/firestore-compat.cjs +241 -297
  38. package/dist/firestore-compat.d.cts +1 -1
  39. package/dist/firestore-compat.d.ts +1 -1
  40. package/dist/firestore-compat.mjs +215 -271
  41. package/dist/index.cjs +3942 -5134
  42. package/dist/index.d.cts +181 -5
  43. package/dist/index.d.ts +181 -5
  44. package/dist/index.mjs +4040 -5239
  45. package/dist/mobile.cjs +459 -344
  46. package/dist/mobile.d.cts +59 -4
  47. package/dist/mobile.d.ts +59 -4
  48. package/dist/mobile.mjs +459 -344
  49. package/dist/mocks.cjs +319 -447
  50. package/dist/mocks.d.cts +1 -1
  51. package/dist/mocks.d.ts +1 -1
  52. package/dist/mocks.mjs +313 -441
  53. package/dist/notifications.cjs +296 -317
  54. package/dist/notifications.d.cts +1 -1
  55. package/dist/notifications.d.ts +1 -1
  56. package/dist/notifications.mjs +295 -316
  57. package/dist/react.cjs +557 -707
  58. package/dist/react.d.cts +1 -1
  59. package/dist/react.d.ts +1 -1
  60. package/dist/react.mjs +547 -697
  61. package/dist/support.cjs +402 -328
  62. package/dist/support.d.cts +29 -3
  63. package/dist/support.d.ts +29 -3
  64. package/dist/support.mjs +401 -328
  65. package/dist/telemetry.cjs +267 -304
  66. package/dist/telemetry.d.cts +1 -1
  67. package/dist/telemetry.d.ts +1 -1
  68. package/dist/telemetry.mjs +267 -304
  69. package/dist/{types-Du_iioJ7.d.cts → types-D-9bjlM0.d.cts} +74 -1
  70. package/dist/{types-BPATkXYu.d.ts → types-bVztFQTI.d.ts} +74 -1
  71. package/dist/usage.cjs +233 -230
  72. package/dist/usage.d.cts +1 -1
  73. package/dist/usage.d.ts +1 -1
  74. package/dist/usage.mjs +233 -230
  75. package/dist/webhooks.cjs +328 -362
  76. package/dist/webhooks.d.cts +1 -1
  77. package/dist/webhooks.d.ts +1 -1
  78. package/dist/webhooks.mjs +325 -359
  79. package/package.json +5 -3
  80. package/dist/ai.cjs.map +0 -1
  81. package/dist/ai.mjs.map +0 -1
  82. package/dist/auth.cjs.map +0 -1
  83. package/dist/auth.mjs.map +0 -1
  84. package/dist/build-guard.cjs.map +0 -1
  85. package/dist/build-guard.mjs.map +0 -1
  86. package/dist/catalog.cjs.map +0 -1
  87. package/dist/catalog.mjs.map +0 -1
  88. package/dist/checkout.cjs.map +0 -1
  89. package/dist/checkout.mjs.map +0 -1
  90. package/dist/db-react.cjs.map +0 -1
  91. package/dist/db-react.mjs.map +0 -1
  92. package/dist/db.cjs.map +0 -1
  93. package/dist/db.mjs.map +0 -1
  94. package/dist/entitlements.cjs.map +0 -1
  95. package/dist/entitlements.mjs.map +0 -1
  96. package/dist/errors.cjs.map +0 -1
  97. package/dist/errors.mjs.map +0 -1
  98. package/dist/firestore-compat.cjs.map +0 -1
  99. package/dist/firestore-compat.mjs.map +0 -1
  100. package/dist/index.cjs.map +0 -1
  101. package/dist/index.mjs.map +0 -1
  102. package/dist/mobile.cjs.map +0 -1
  103. package/dist/mobile.mjs.map +0 -1
  104. package/dist/mocks.cjs.map +0 -1
  105. package/dist/mocks.mjs.map +0 -1
  106. package/dist/notifications.cjs.map +0 -1
  107. package/dist/notifications.mjs.map +0 -1
  108. package/dist/react.cjs.map +0 -1
  109. package/dist/react.mjs.map +0 -1
  110. package/dist/support.cjs.map +0 -1
  111. package/dist/support.mjs.map +0 -1
  112. package/dist/telemetry.cjs.map +0 -1
  113. package/dist/telemetry.mjs.map +0 -1
  114. package/dist/usage.cjs.map +0 -1
  115. package/dist/usage.mjs.map +0 -1
  116. package/dist/webhooks.cjs.map +0 -1
  117. package/dist/webhooks.mjs.map +0 -1
package/dist/webhooks.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  // src/errors.ts
4
- var NeetruError = class _NeetruError extends Error {
4
+ var s = class t extends Error {
5
5
  code;
6
6
  status;
7
7
  requestId;
@@ -14,322 +14,314 @@ var NeetruError = class _NeetruError extends Error {
14
14
  * para um `NeetruDbErrorCode` mais específico (recuperável vs não).
15
15
  */
16
16
  reason;
17
- constructor(code, message, status, requestId, reason) {
18
- super(message);
19
- this.name = "NeetruError";
20
- this.code = code;
21
- this.status = status;
22
- this.requestId = requestId;
23
- this.reason = reason;
24
- Object.setPrototypeOf(this, _NeetruError.prototype);
17
+ /**
18
+ * 3.8.0: `x-correlation-id` da requisição que falhou. O SDK gera um UUID por
19
+ * chamada (ou usa o que o chamador passou) e manda no header; o Core grava o
20
+ * mesmo id nos logs/auditoria — cite-o ao abrir um ticket de suporte.
21
+ * `undefined` em erros que acontecem antes de qualquer requisição.
22
+ */
23
+ correlationId;
24
+ constructor(e, r, n, o, i, a) {
25
+ super(r), this.name = "NeetruError", this.code = e, this.status = n, this.requestId = o, this.reason = i, this.correlationId = a, Object.setPrototypeOf(this, t.prototype);
25
26
  }
26
27
  };
27
28
 
28
29
  // src/idempotency.ts
29
- function generateIdempotencyKey() {
30
- const cryptoObj = typeof globalThis !== "undefined" && "crypto" in globalThis ? globalThis.crypto : void 0;
31
- if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
32
- return cryptoObj.randomUUID();
33
- }
34
- throw new NeetruError(
30
+ function N() {
31
+ let t = typeof globalThis < "u" && "crypto" in globalThis ? globalThis.crypto : void 0;
32
+ if (t && typeof t.randomUUID == "function")
33
+ return t.randomUUID();
34
+ throw new s(
35
35
  "runtime_unsupported",
36
36
  "crypto.randomUUID not available in this runtime. SDK 3.0 requires Node \u226520 or modern browser/Edge."
37
37
  );
38
38
  }
39
39
 
40
+ // src/correlation.ts
41
+ var D = "x-correlation-id";
42
+ var F = /^[A-Za-z0-9._:\-]+$/;
43
+ function C(t) {
44
+ return typeof t == "string" && t.length > 0 && t.length <= 128 && F.test(t);
45
+ }
46
+ function z() {
47
+ let t = globalThis.crypto;
48
+ try {
49
+ if (t && typeof t.randomUUID == "function") return t.randomUUID();
50
+ } catch {
51
+ }
52
+ let e = new Uint8Array(16), r = false;
53
+ try {
54
+ t && typeof t.getRandomValues == "function" && (t.getRandomValues(e), r = !0);
55
+ } catch {
56
+ r = false;
57
+ }
58
+ if (!r)
59
+ for (let o = 0; o < e.length; o++) e[o] = Math.floor(Math.random() * 256);
60
+ e[6] = e[6] & 15 | 64, e[8] = e[8] & 63 | 128;
61
+ let n = Array.from(e, (o) => o.toString(16).padStart(2, "0")).join("");
62
+ return `${n.slice(0, 8)}-${n.slice(8, 12)}-${n.slice(12, 16)}-${n.slice(16, 20)}-${n.slice(20)}`;
63
+ }
64
+ function O(t, e) {
65
+ let r, n = {};
66
+ for (let [i, a] of Object.entries(t)) {
67
+ if (i.toLowerCase() === D) {
68
+ C(a) && (r = a);
69
+ continue;
70
+ }
71
+ n[i] = a;
72
+ }
73
+ let o = r ?? (C(e) ? e : void 0) ?? z();
74
+ return n[D] = o, { headers: n, correlationId: o };
75
+ }
76
+
77
+ // src/server-only-key.ts
78
+ function M() {
79
+ try {
80
+ let t = globalThis.navigator;
81
+ if (t && t.product === "ReactNative") return "react-native";
82
+ } catch {
83
+ }
84
+ try {
85
+ let t = globalThis;
86
+ if (typeof t.window < "u" && typeof t.document < "u") return "browser";
87
+ } catch {
88
+ }
89
+ return null;
90
+ }
91
+
40
92
  // src/http.ts
41
- var COMPAT_MATRIX = {
93
+ var G = {
42
94
  // SDK major 3.x requer Core ≥ 2026.05.1 (suporte a X-Neetru-Version header,
43
95
  // runTransaction write-after-read, verifyWebhookRequest, webhooks 3.0+)
44
96
  3: "2026.05.1"
45
97
  };
46
- function stripRevision(v) {
47
- return v.split("+")[0] ?? v;
98
+ function A(t) {
99
+ return t.split("+")[0] ?? t;
48
100
  }
49
- function compareCalVer(a, b) {
50
- const partsA = stripRevision(a).split(".").map(Number);
51
- const partsB = stripRevision(b).split(".").map(Number);
52
- const len = Math.max(partsA.length, partsB.length);
53
- for (let i = 0; i < len; i++) {
54
- const pa = partsA[i] ?? 0;
55
- const pb = partsB[i] ?? 0;
56
- if (pa !== pb) return pa - pb;
101
+ function X(t, e) {
102
+ let r = A(t).split(".").map(Number), n = A(e).split(".").map(Number), o = Math.max(r.length, n.length);
103
+ for (let i = 0; i < o; i++) {
104
+ let a = r[i] ?? 0, c = n[i] ?? 0;
105
+ if (a !== c) return a - c;
57
106
  }
58
107
  return 0;
59
108
  }
60
- function readInjectedSdkVersion() {
109
+ function $() {
61
110
  try {
62
- return "3.6.0";
111
+ return "3.8.0";
63
112
  } catch {
64
- return void 0;
113
+ return;
65
114
  }
66
115
  }
67
- function getSdkMajor() {
68
- const ver = readInjectedSdkVersion();
69
- if (ver) return parseInt(ver.split(".")[0] ?? "3", 10);
70
- return 3;
116
+ function Y() {
117
+ let t = $();
118
+ return t ? parseInt(t.split(".")[0] ?? "3", 10) : 3;
71
119
  }
72
- var _warnedCoreTooOld = /* @__PURE__ */ new Set();
73
- function checkCoreVersionCompat(coreVersion) {
74
- if (!coreVersion) return;
75
- const sdkMajor = getSdkMajor();
76
- const minCore = COMPAT_MATRIX[sdkMajor];
77
- if (!minCore) return;
78
- const stripped = stripRevision(coreVersion);
79
- if (compareCalVer(stripped, minCore) < 0) {
80
- const key = `${sdkMajor}:${stripped}`;
81
- if (!_warnedCoreTooOld.has(key)) {
82
- _warnedCoreTooOld.add(key);
83
- console.warn(
84
- `[Neetru SDK] Aten\xE7\xE3o: Core vers\xE3o "${coreVersion}" \xE9 anterior ao m\xEDnimo recomendado "${minCore}" para SDK major ${sdkMajor}. Alguns recursos podem n\xE3o funcionar corretamente. Atualize o Core para a vers\xE3o mais recente.`
85
- );
86
- }
120
+ var W = /* @__PURE__ */ new Set();
121
+ function J(t) {
122
+ if (!t) return;
123
+ let e = Y(), r = G[e];
124
+ if (!r) return;
125
+ let n = A(t);
126
+ if (X(n, r) < 0) {
127
+ let o = `${e}:${n}`;
128
+ W.has(o) || (W.add(o), console.warn(
129
+ `[Neetru SDK] Aten\xE7\xE3o: Core vers\xE3o "${t}" \xE9 anterior ao m\xEDnimo recomendado "${r}" para SDK major ${e}. Alguns recursos podem n\xE3o funcionar corretamente. Atualize o Core para a vers\xE3o mais recente.`
130
+ ));
87
131
  }
88
132
  }
89
- var DEFAULT_RETRIES_READ = 2;
90
- var DEFAULT_RETRIES_WRITE = 0;
91
- var READ_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD"]);
92
- var RETRYABLE_CODES = /* @__PURE__ */ new Set([
133
+ function Z() {
134
+ let t = "This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var.";
135
+ return M() ? "Esta opera\xE7\xE3o exige a credencial nrt_ do produto, que \xE9 S\xD3 DE SERVIDOR. No navegador/app, chame a API do seu produto (ex.: https://<produto>.neetru.com/api/v1) com o token do usu\xE1rio \u2014 o backend do produto faz esta chamada com o SDK e a chave. (" + t + ")" : t;
136
+ }
137
+ var Q = 2, ee = 0, te = /* @__PURE__ */ new Set(["GET", "HEAD"]), re = /* @__PURE__ */ new Set([
93
138
  "rate_limited",
94
139
  "server_error",
95
140
  "network_error"
96
141
  ]);
97
- function backoffMs(attempt) {
98
- const base = 200 * Math.pow(4, attempt);
99
- const jitter = base * 0.2 * (Math.random() * 2 - 1);
100
- return Math.max(50, Math.round(base + jitter));
142
+ function U(t) {
143
+ let e = 200 * Math.pow(4, t), r = e * 0.2 * (Math.random() * 2 - 1);
144
+ return Math.max(50, Math.round(e + r));
101
145
  }
102
- var MAX_RETRY_AFTER_MS = 6e4;
103
- function parseRetryAfter(value) {
104
- if (!value) return null;
105
- const secs = Number(value);
106
- if (Number.isFinite(secs) && secs >= 0) return Math.min(Math.round(secs * 1e3), MAX_RETRY_AFTER_MS);
107
- const dateMs = Date.parse(value);
108
- if (Number.isFinite(dateMs)) {
109
- const delta = dateMs - Date.now();
110
- if (delta > 0) return Math.min(delta, MAX_RETRY_AFTER_MS);
146
+ var q = 6e4;
147
+ function ne(t) {
148
+ if (!t) return null;
149
+ let e = Number(t);
150
+ if (Number.isFinite(e) && e >= 0) return Math.min(Math.round(e * 1e3), q);
151
+ let r = Date.parse(t);
152
+ if (Number.isFinite(r)) {
153
+ let n = r - Date.now();
154
+ if (n > 0) return Math.min(n, q);
111
155
  }
112
156
  return null;
113
157
  }
114
- function sleep(ms) {
115
- return new Promise((resolve) => setTimeout(resolve, ms));
158
+ function P(t) {
159
+ return new Promise((e) => setTimeout(e, t));
116
160
  }
117
- function statusToCode(status) {
118
- if (status === 401) return "unauthorized";
119
- if (status === 403) return "forbidden";
120
- if (status === 404) return "not_found";
121
- if (status === 409) return "conflict";
122
- if (status === 422 || status === 400) return "validation_failed";
123
- if (status === 429) return "rate_limited";
124
- if (status >= 500) return "server_error";
125
- return "unknown";
161
+ function oe(t) {
162
+ return t === 401 ? "unauthorized" : t === 403 ? "forbidden" : t === 404 ? "not_found" : t === 409 ? "conflict" : t === 410 ? "gone" : t === 422 || t === 400 ? "validation_failed" : t === 429 ? "rate_limited" : t >= 500 ? "server_error" : "unknown";
126
163
  }
127
- function buildUrl(baseUrl, path, query) {
128
- const base = baseUrl.replace(/\/+$/, "");
129
- const p = path.startsWith("/") ? path : `/${path}`;
130
- const url = new URL(`${base}${p}`);
131
- if (query) {
132
- for (const [k, v] of Object.entries(query)) {
133
- if (v === void 0) continue;
134
- url.searchParams.set(k, String(v));
135
- }
136
- }
137
- return url.toString();
164
+ function ie(t, e, r) {
165
+ let n = t.replace(/\/+$/, ""), o = e.startsWith("/") ? e : `/${e}`, i = new URL(`${n}${o}`);
166
+ if (r)
167
+ for (let [a, c] of Object.entries(r))
168
+ c !== void 0 && i.searchParams.set(a, String(c));
169
+ return i.toString();
138
170
  }
139
- async function safeJson(res) {
140
- const text = await res.text();
141
- if (!text) return void 0;
142
- try {
143
- return JSON.parse(text);
144
- } catch {
145
- return void 0;
146
- }
171
+ async function K(t) {
172
+ let e = await t.text();
173
+ if (e)
174
+ try {
175
+ return JSON.parse(e);
176
+ } catch {
177
+ return;
178
+ }
147
179
  }
148
- async function httpRequest(config, opts) {
149
- const method = opts.method ?? "GET";
150
- const url = buildUrl(config.baseUrl, opts.path, opts.query);
151
- const defaultRetries = READ_METHODS.has(method) ? DEFAULT_RETRIES_READ : DEFAULT_RETRIES_WRITE;
152
- const maxRetries = opts.retries ?? defaultRetries;
153
- const headers = {
154
- accept: "application/json",
155
- ...opts.headers
156
- };
157
- const sdkVersion = readInjectedSdkVersion();
158
- if (sdkVersion) {
159
- headers["x-neetru-sdk-version"] = sdkVersion;
160
- }
161
- if (opts.requireAuth) {
162
- if (!config.apiKey) {
163
- throw new NeetruError(
164
- "missing_api_key",
165
- "This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var."
180
+ async function k(t, e) {
181
+ let r = e.method ?? "GET", n = ie(t.baseUrl, e.path, e.query), o = te.has(r) ? Q : ee, i = e.retries ?? o, { headers: a, correlationId: c } = O(
182
+ { accept: "application/json", ...e.headers },
183
+ e.correlationId
184
+ ), b = $();
185
+ if (b && (a["x-neetru-sdk-version"] = b), e.requireAuth) {
186
+ if (!t.apiKey)
187
+ throw new s("missing_api_key", Z());
188
+ a.authorization = `Bearer ${t.apiKey}`;
189
+ }
190
+ if (e.idempotencyKey) {
191
+ let l = typeof e.idempotencyKey == "string" ? e.idempotencyKey : N();
192
+ a["idempotency-key"] = l;
193
+ }
194
+ let h = e.body !== void 0 && r !== "GET" && r !== "DELETE" ? JSON.stringify(e.body) : void 0;
195
+ h !== void 0 && (a["content-type"] = "application/json");
196
+ let g = null, p = e.deadlineMs != null ? Date.now() + e.deadlineMs : null;
197
+ for (let l = 0; l <= i; l++) {
198
+ if (p != null && Date.now() >= p)
199
+ throw g ?? new s(
200
+ "network_error",
201
+ "Deadline excedido antes de completar a request",
202
+ void 0,
203
+ void 0,
204
+ void 0,
205
+ c
166
206
  );
167
- }
168
- headers.authorization = `Bearer ${config.apiKey}`;
169
- }
170
- if (opts.idempotencyKey) {
171
- const key = typeof opts.idempotencyKey === "string" ? opts.idempotencyKey : generateIdempotencyKey();
172
- headers["idempotency-key"] = key;
173
- }
174
- const bodyString = opts.body !== void 0 && method !== "GET" && method !== "DELETE" ? JSON.stringify(opts.body) : void 0;
175
- if (bodyString !== void 0) {
176
- headers["content-type"] = "application/json";
177
- }
178
- let lastError = null;
179
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
180
- const init = { method, headers };
181
- if (bodyString !== void 0) init.body = bodyString;
182
- init.signal = AbortSignal.timeout(3e4);
183
- let res;
207
+ let f = { method: r, headers: a };
208
+ h !== void 0 && (f.body = h);
209
+ let v = p != null ? Math.max(1, Math.min(3e4, p - Date.now())) : 3e4;
210
+ f.signal = AbortSignal.timeout(v);
211
+ let d;
184
212
  try {
185
- res = await config.fetch(url, init);
186
- } catch (err2) {
187
- const message2 = err2 instanceof DOMException && err2.name === "TimeoutError" ? "Network error: timeout after 30s" : `Network error: ${err2 instanceof Error ? err2.message : "fetch failed"}`;
188
- lastError = new NeetruError("network_error", message2);
189
- if (attempt < maxRetries) {
190
- await sleep(backoffMs(attempt));
191
- continue;
213
+ d = await t.fetch(n, f);
214
+ } catch (u) {
215
+ let _ = u instanceof DOMException && u.name === "TimeoutError" ? "Network error: timeout after 30s" : `Network error: ${u instanceof Error ? u.message : "fetch failed"}`;
216
+ if (g = new s("network_error", _, void 0, void 0, void 0, c), l < i) {
217
+ let T = U(l);
218
+ if (p == null || Date.now() + T < p) {
219
+ await P(T);
220
+ continue;
221
+ }
192
222
  }
193
- throw lastError;
223
+ throw g;
194
224
  }
195
- const requestId = res.headers.get("x-request-id") ?? res.headers.get("x-correlation-id") ?? void 0;
196
- if (res.ok) {
197
- const coreVersion = res.headers.get("x-neetru-version");
198
- if (coreVersion) checkCoreVersionCompat(coreVersion);
199
- const parsed = await safeJson(res);
200
- return parsed;
225
+ let w = d.headers.get("x-request-id") ?? d.headers.get("x-correlation-id") ?? void 0;
226
+ if (d.ok) {
227
+ let u = d.headers.get("x-neetru-version");
228
+ return u && J(u), await K(d);
201
229
  }
202
- const body = await safeJson(res);
203
- let code = statusToCode(res.status);
204
- let message = `HTTP ${res.status}`;
205
- let reason;
206
- if (body && typeof body === "object") {
207
- const errField = body.error;
208
- if (typeof errField === "string") {
209
- message = errField;
210
- } else if (errField && typeof errField === "object") {
211
- if (typeof errField.code === "string") code = errField.code;
212
- if (typeof errField.message === "string") message = errField.message;
213
- if (typeof errField.reason === "string") reason = errField.reason;
214
- } else {
215
- if (typeof body.code === "string") code = body.code;
216
- if (typeof body.message === "string") message = body.message;
217
- }
218
- if (typeof body.reason === "string") reason = body.reason;
230
+ let m = await K(d), E = oe(d.status), y = `HTTP ${d.status}`, I;
231
+ if (m && typeof m == "object") {
232
+ let u = m.error;
233
+ typeof u == "string" ? y = u : u && typeof u == "object" ? (typeof u.code == "string" && (E = u.code), typeof u.message == "string" && (y = u.message), typeof u.reason == "string" && (I = u.reason)) : (typeof m.code == "string" && (E = m.code), typeof m.message == "string" && (y = m.message)), typeof m.reason == "string" && (I = m.reason);
219
234
  }
220
- const err = new NeetruError(code, message, res.status, requestId, reason);
221
- lastError = err;
222
- const isRetryable = RETRYABLE_CODES.has(code);
223
- if (isRetryable && attempt < maxRetries) {
224
- const retryAfter = parseRetryAfter(res.headers.get("retry-after"));
225
- const delay = retryAfter ?? backoffMs(attempt);
226
- await sleep(delay);
227
- continue;
235
+ if (d.status === 410) {
236
+ let u = d.headers.get("x-neetru-replacement");
237
+ y === `HTTP ${d.status}` && (y = `Endpoint ${e.path} foi removido do Core (HTTP 410 Gone) \u2014 atualize o @neetru/sdk e migre para a API substituta.`), u && !y.includes(u) && (y += ` Substituto: ${u}.`);
228
238
  }
229
- throw err;
239
+ let x = new s(E, y, d.status, w, I, c);
240
+ if (g = x, re.has(E) && l < i) {
241
+ let _ = ne(d.headers.get("retry-after")) ?? U(l);
242
+ if (p == null || Date.now() + _ < p) {
243
+ await P(_);
244
+ continue;
245
+ }
246
+ }
247
+ throw x;
230
248
  }
231
- throw lastError ?? new NeetruError("unknown", "unexpected httpRequest exit");
249
+ throw g ?? new s("unknown", "unexpected httpRequest exit", void 0, void 0, void 0, c);
232
250
  }
233
251
 
234
252
  // src/validators.ts
235
- var SDK_ID_RE = /^[a-z0-9][a-z0-9_-]{0,62}$/i;
236
- function assertValidSdkId(field, value) {
237
- if (typeof value !== "string" || !SDK_ID_RE.test(value)) {
238
- throw new NeetruError(
253
+ var L = /^[a-z0-9][a-z0-9_-]{0,62}$/i;
254
+ function S(t, e) {
255
+ if (typeof e != "string" || !L.test(e))
256
+ throw new s(
239
257
  "validation_failed",
240
- `${field} must match ${SDK_ID_RE.source} (lowercase alphanumeric, _, -; first char must be alphanumeric; max 63 chars)`
258
+ `${t} must match ${L.source} (lowercase alphanumeric, _, -; first char must be alphanumeric; max 63 chars)`
241
259
  );
242
- }
243
260
  }
244
261
 
245
262
  // src/webhooks.ts
246
- async function verifyWebhookSignature(payload, signature, secret, timestamp) {
247
- if (!signature || !secret) return false;
248
- const sigHex = signature.startsWith("sha256=") ? signature.slice(7) : signature;
249
- if (!/^[0-9a-f]+$/i.test(sigHex)) return false;
250
- const subtle = typeof globalThis !== "undefined" && "crypto" in globalThis ? globalThis.crypto?.subtle : void 0;
251
- if (!subtle) {
252
- throw new NeetruError(
263
+ async function se(t, e, r, n) {
264
+ if (!e || !r) return false;
265
+ let o = e.startsWith("sha256=") ? e.slice(7) : e;
266
+ if (!/^[0-9a-f]+$/i.test(o)) return false;
267
+ let i = typeof globalThis < "u" && "crypto" in globalThis ? globalThis.crypto?.subtle : void 0;
268
+ if (!i)
269
+ throw new s(
253
270
  "runtime_unsupported",
254
271
  "verifyWebhookSignature requires globalThis.crypto.subtle (Node \u226520, modern browser, or Edge runtime)."
255
272
  );
273
+ let a = new TextEncoder(), c = a.encode(r), b = typeof t == "string" ? a.encode(t) : t, h = b;
274
+ if (n !== void 0) {
275
+ let d = a.encode(`${n}.`), w = new Uint8Array(d.length + b.length);
276
+ w.set(d, 0), w.set(b, d.length), h = w;
256
277
  }
257
- const encoder = new TextEncoder();
258
- const keyBytes = encoder.encode(secret);
259
- const rawBytes = typeof payload === "string" ? encoder.encode(payload) : payload;
260
- let payloadBytes = rawBytes;
261
- if (timestamp !== void 0) {
262
- const prefix = encoder.encode(`${timestamp}.`);
263
- const merged = new Uint8Array(prefix.length + rawBytes.length);
264
- merged.set(prefix, 0);
265
- merged.set(rawBytes, prefix.length);
266
- payloadBytes = merged;
267
- }
268
- const key = await subtle.importKey(
278
+ let g = await i.importKey(
269
279
  "raw",
270
- keyBytes,
280
+ c,
271
281
  { name: "HMAC", hash: "SHA-256" },
272
282
  false,
273
283
  ["sign"]
274
- );
275
- const macBuffer = await subtle.sign(
284
+ ), p = await i.sign(
276
285
  "HMAC",
277
- key,
278
- payloadBytes
279
- );
280
- const macBytes = new Uint8Array(macBuffer);
281
- const sigBytes = hexToBytes(sigHex.toLowerCase());
282
- if (!sigBytes || sigBytes.length !== macBytes.length) return false;
283
- let diff = 0;
284
- for (let i = 0; i < macBytes.length; i++) {
285
- diff |= macBytes[i] ^ sigBytes[i];
286
- }
287
- return diff === 0;
286
+ g,
287
+ h
288
+ ), l = new Uint8Array(p), f = ae(o.toLowerCase());
289
+ if (!f || f.length !== l.length) return false;
290
+ let v = 0;
291
+ for (let d = 0; d < l.length; d++)
292
+ v |= l[d] ^ f[d];
293
+ return v === 0;
288
294
  }
289
- async function verifyWebhookRequest(payload, headers, secret, options = {}) {
290
- const toleranceMs = options.toleranceMs ?? 3e5;
291
- const getHeader = (name) => {
292
- if (typeof headers.get === "function") {
293
- return headers.get(name);
294
- }
295
- const rec = headers;
296
- const lower = name.toLowerCase();
297
- for (const key of Object.keys(rec)) {
298
- if (key.toLowerCase() === lower) return rec[key] ?? null;
299
- }
295
+ async function Re(t, e, r, n = {}) {
296
+ let o = n.toleranceMs ?? 3e5, i = (p) => {
297
+ if (typeof e.get == "function")
298
+ return e.get(p);
299
+ let l = e, f = p.toLowerCase();
300
+ for (let v of Object.keys(l))
301
+ if (v.toLowerCase() === f) return l[v] ?? null;
300
302
  return null;
301
- };
302
- const tsHeader = getHeader("x-neetru-timestamp");
303
- if (!tsHeader) {
303
+ }, a = i("x-neetru-timestamp");
304
+ if (!a)
304
305
  return { ok: false, reason: "timestamp_missing" };
305
- }
306
- const tsMs = Number(tsHeader);
307
- if (!Number.isFinite(tsMs)) {
306
+ let c = Number(a);
307
+ if (!Number.isFinite(c))
308
308
  return { ok: false, reason: "timestamp_missing" };
309
- }
310
- const skewMs = Math.abs(Date.now() - tsMs);
311
- if (skewMs > toleranceMs) {
309
+ if (Math.abs(Date.now() - c) > o)
312
310
  return { ok: false, reason: "timestamp_expired" };
313
- }
314
- const sig = getHeader("x-neetru-signature");
315
- const valid = await verifyWebhookSignature(payload, sig, secret, tsHeader);
316
- if (!valid) {
317
- return { ok: false, reason: "invalid_signature" };
318
- }
319
- return { ok: true };
311
+ let h = i("x-neetru-signature");
312
+ return await se(t, h, r, a) ? { ok: true } : { ok: false, reason: "invalid_signature" };
320
313
  }
321
- function hexToBytes(hex) {
322
- if (hex.length % 2 !== 0) return null;
323
- const bytes = new Uint8Array(hex.length / 2);
324
- for (let i = 0; i < bytes.length; i++) {
325
- const high = parseInt(hex[i * 2], 16);
326
- const low = parseInt(hex[i * 2 + 1], 16);
327
- if (Number.isNaN(high) || Number.isNaN(low)) return null;
328
- bytes[i] = high << 4 | low;
329
- }
330
- return bytes;
314
+ function ae(t) {
315
+ if (t.length % 2 !== 0) return null;
316
+ let e = new Uint8Array(t.length / 2);
317
+ for (let r = 0; r < e.length; r++) {
318
+ let n = parseInt(t[r * 2], 16), o = parseInt(t[r * 2 + 1], 16);
319
+ if (Number.isNaN(n) || Number.isNaN(o)) return null;
320
+ e[r] = n << 4 | o;
321
+ }
322
+ return e;
331
323
  }
332
- var VALID_EVENTS = [
324
+ var V = [
333
325
  "subscription.activated",
334
326
  "subscription.cancelled",
335
327
  "subscription.payment_failed",
@@ -339,80 +331,66 @@ var VALID_EVENTS = [
339
331
  "account.reactivated",
340
332
  "support.ticket_replied"
341
333
  ];
342
- function toEndpoint(raw) {
343
- if (!raw || typeof raw !== "object") {
344
- throw new NeetruError("invalid_response", "Webhook response is not an object");
345
- }
346
- const r = raw;
347
- if (typeof r.id !== "string") {
348
- throw new NeetruError("invalid_response", "Webhook missing id");
349
- }
334
+ function H(t) {
335
+ if (!t || typeof t != "object")
336
+ throw new s("invalid_response", "Webhook response is not an object");
337
+ let e = t;
338
+ if (typeof e.id != "string")
339
+ throw new s("invalid_response", "Webhook missing id");
350
340
  return {
351
- id: r.id,
352
- url: typeof r.url === "string" ? r.url : "",
353
- events: Array.isArray(r.events) ? r.events.filter(
354
- (e) => VALID_EVENTS.includes(e)
341
+ id: e.id,
342
+ url: typeof e.url == "string" ? e.url : "",
343
+ events: Array.isArray(e.events) ? e.events.filter(
344
+ (r) => V.includes(r)
355
345
  ) : [],
356
- hasSecret: r.hasSecret === true,
357
- status: r.status === "active" || r.status === "degraded" || r.status === "disabled" ? r.status : "active",
358
- lastDeliveryAt: typeof r.lastDeliveryAt === "string" ? r.lastDeliveryAt : void 0,
359
- consecutiveFailures: typeof r.consecutiveFailures === "number" ? r.consecutiveFailures : void 0,
360
- createdAt: typeof r.createdAt === "string" ? r.createdAt : (/* @__PURE__ */ new Date()).toISOString()
346
+ hasSecret: e.hasSecret === true,
347
+ status: e.status === "active" || e.status === "degraded" || e.status === "disabled" ? e.status : "active",
348
+ lastDeliveryAt: typeof e.lastDeliveryAt == "string" ? e.lastDeliveryAt : void 0,
349
+ consecutiveFailures: typeof e.consecutiveFailures == "number" ? e.consecutiveFailures : void 0,
350
+ createdAt: typeof e.createdAt == "string" ? e.createdAt : (/* @__PURE__ */ new Date()).toISOString()
361
351
  };
362
352
  }
363
- function validateInput(input) {
364
- if (!input.url || typeof input.url !== "string") {
365
- throw new NeetruError("validation_failed", "url \xE9 obrigat\xF3ria");
366
- }
353
+ function B(t) {
354
+ if (!t.url || typeof t.url != "string")
355
+ throw new s("validation_failed", "url \xE9 obrigat\xF3ria");
367
356
  try {
368
- const parsed = new URL(input.url);
369
- if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
357
+ let e = new URL(t.url);
358
+ if (e.protocol !== "https:" && e.protocol !== "http:")
370
359
  throw new Error("invalid protocol");
371
- }
372
360
  } catch {
373
- throw new NeetruError("validation_failed", `url inv\xE1lida: ${input.url}`);
374
- }
375
- if (!Array.isArray(input.events) || input.events.length === 0) {
376
- throw new NeetruError("validation_failed", "events deve ter pelo menos 1 evento");
377
- }
378
- for (const ev of input.events) {
379
- if (!VALID_EVENTS.includes(ev)) {
380
- throw new NeetruError("validation_failed", `evento desconhecido: ${ev}`);
381
- }
382
- }
383
- if (input.secret !== void 0 && input.secret.length < 16) {
384
- throw new NeetruError("validation_failed", "secret deve ter \u226516 chars (recomendado 32+)");
385
- }
361
+ throw new s("validation_failed", `url inv\xE1lida: ${t.url}`);
362
+ }
363
+ if (!Array.isArray(t.events) || t.events.length === 0)
364
+ throw new s("validation_failed", "events deve ter pelo menos 1 evento");
365
+ for (let e of t.events)
366
+ if (!V.includes(e))
367
+ throw new s("validation_failed", `evento desconhecido: ${e}`);
368
+ if (t.secret !== void 0 && t.secret.length < 16)
369
+ throw new s("validation_failed", "secret deve ter \u226516 chars (recomendado 32+)");
386
370
  }
387
- function resolveProductId(config, ...candidates) {
388
- for (const c of candidates) {
389
- if (typeof c === "string" && c.length > 0) {
390
- assertValidSdkId("productId", c);
391
- return c;
392
- }
393
- }
394
- if (config.productId) {
395
- assertValidSdkId("productId", config.productId);
396
- return config.productId;
397
- }
398
- throw new NeetruError(
371
+ function R(t, ...e) {
372
+ for (let r of e)
373
+ if (typeof r == "string" && r.length > 0)
374
+ return S("productId", r), r;
375
+ if (t.productId)
376
+ return S("productId", t.productId), t.productId;
377
+ throw new s(
399
378
  "validation_failed",
400
379
  "productId required (pass to options/input or set on createNeetruClient)"
401
380
  );
402
381
  }
403
- function createWebhooksNamespace(config) {
382
+ function Ie(t) {
404
383
  return {
405
- async register(input) {
406
- validateInput(input);
407
- const productId = resolveProductId(config, input.productId);
408
- const raw = await httpRequest(config, {
384
+ async register(e) {
385
+ B(e);
386
+ let r = R(t, e.productId), n = await k(t, {
409
387
  method: "POST",
410
388
  path: "/api/sdk/v1/webhooks",
411
389
  body: {
412
- productId,
413
- url: input.url,
414
- events: input.events,
415
- ...input.secret ? { secret: input.secret } : {}
390
+ productId: r,
391
+ url: e.url,
392
+ events: e.events,
393
+ ...e.secret ? { secret: e.secret } : {}
416
394
  },
417
395
  requireAuth: true,
418
396
  // Sem isso, um retry de rede (app-level; SDK default é 0 retries em
@@ -421,91 +399,79 @@ function createWebhooksNamespace(config) {
421
399
  // dedup TTL 24h (mesmo padrão de usage.report/support.createTicket).
422
400
  idempotencyKey: true
423
401
  });
424
- return toEndpoint(raw);
402
+ return H(n);
425
403
  },
426
- async list(options) {
427
- const productId = resolveProductId(config, options?.productId);
428
- const raw = await httpRequest(config, {
404
+ async list(e) {
405
+ let r = R(t, e?.productId), n = await k(t, {
429
406
  method: "GET",
430
407
  path: "/api/sdk/v1/webhooks",
431
- query: { productId },
408
+ query: { productId: r },
432
409
  requireAuth: true
433
410
  });
434
- const list = Array.isArray(raw?.endpoints) ? raw.endpoints : [];
435
- return list.map(toEndpoint);
411
+ return (Array.isArray(n?.endpoints) ? n.endpoints : []).map(H);
436
412
  },
437
- async unregister(id, options) {
438
- if (!id) throw new NeetruError("validation_failed", "id obrigat\xF3rio");
439
- const productId = resolveProductId(config, options?.productId);
440
- await httpRequest(config, {
413
+ async unregister(e, r) {
414
+ if (!e) throw new s("validation_failed", "id obrigat\xF3rio");
415
+ let n = R(t, r?.productId);
416
+ return await k(t, {
441
417
  method: "DELETE",
442
- path: `/api/sdk/v1/webhooks/${encodeURIComponent(id)}`,
443
- query: { productId },
418
+ path: `/api/sdk/v1/webhooks/${encodeURIComponent(e)}`,
419
+ query: { productId: n },
444
420
  requireAuth: true
445
- });
446
- return { ok: true };
421
+ }), { ok: true };
447
422
  },
448
- async test(id, options) {
449
- if (!id) throw new NeetruError("validation_failed", "id obrigat\xF3rio");
450
- const productId = resolveProductId(config, options?.productId);
451
- const raw = await httpRequest(config, {
423
+ async test(e, r) {
424
+ if (!e) throw new s("validation_failed", "id obrigat\xF3rio");
425
+ let n = R(t, r?.productId), o = await k(t, {
452
426
  method: "POST",
453
- path: `/api/sdk/v1/webhooks/${encodeURIComponent(id)}/test`,
454
- query: { productId },
427
+ path: `/api/sdk/v1/webhooks/${encodeURIComponent(e)}/test`,
428
+ query: { productId: n },
455
429
  requireAuth: true,
456
430
  idempotencyKey: true
457
431
  });
458
- if (!raw || typeof raw !== "object") {
432
+ if (!o || typeof o != "object")
459
433
  return { ok: false, error: "invalid response" };
460
- }
461
- const r = raw;
434
+ let i = o;
462
435
  return {
463
- ok: r.ok === true,
464
- statusCode: typeof r.statusCode === "number" ? r.statusCode : void 0,
465
- durationMs: typeof r.durationMs === "number" ? r.durationMs : void 0,
466
- error: typeof r.error === "string" ? r.error : void 0
436
+ ok: i.ok === true,
437
+ statusCode: typeof i.statusCode == "number" ? i.statusCode : void 0,
438
+ durationMs: typeof i.durationMs == "number" ? i.durationMs : void 0,
439
+ error: typeof i.error == "string" ? i.error : void 0
467
440
  };
468
441
  }
469
442
  };
470
443
  }
471
- var MockWebhooks = class {
444
+ var j = class {
472
445
  endpoints = /* @__PURE__ */ new Map();
473
446
  nextId = 1;
474
- async register(input) {
475
- validateInput(input);
476
- const id = `mock_wh_${this.nextId++}`;
477
- const endpoint = {
478
- id,
479
- url: input.url,
480
- events: input.events,
481
- hasSecret: !!input.secret,
447
+ async register(e) {
448
+ B(e);
449
+ let r = `mock_wh_${this.nextId++}`, n = {
450
+ id: r,
451
+ url: e.url,
452
+ events: e.events,
453
+ hasSecret: !!e.secret,
482
454
  status: "active",
483
455
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
484
456
  };
485
- this.endpoints.set(id, endpoint);
486
- return endpoint;
457
+ return this.endpoints.set(r, n), n;
487
458
  }
488
- async list(_options) {
459
+ async list(e) {
489
460
  return [...this.endpoints.values()];
490
461
  }
491
- async unregister(id, _options) {
492
- if (!this.endpoints.has(id)) {
493
- throw new NeetruError("not_found", `Webhook ${id} n\xE3o encontrado`);
494
- }
495
- this.endpoints.delete(id);
496
- return { ok: true };
462
+ async unregister(e, r) {
463
+ if (!this.endpoints.has(e))
464
+ throw new s("not_found", `Webhook ${e} n\xE3o encontrado`);
465
+ return this.endpoints.delete(e), { ok: true };
497
466
  }
498
- async test(id, _options) {
499
- if (!this.endpoints.has(id)) {
500
- throw new NeetruError("not_found", `Webhook ${id} n\xE3o encontrado`);
501
- }
467
+ async test(e, r) {
468
+ if (!this.endpoints.has(e))
469
+ throw new s("not_found", `Webhook ${e} n\xE3o encontrado`);
502
470
  return { ok: true, statusCode: 200, durationMs: 42 };
503
471
  }
504
472
  };
505
473
 
506
- exports.MockWebhooks = MockWebhooks;
507
- exports.createWebhooksNamespace = createWebhooksNamespace;
508
- exports.verifyWebhookRequest = verifyWebhookRequest;
509
- exports.verifyWebhookSignature = verifyWebhookSignature;
510
- //# sourceMappingURL=webhooks.cjs.map
511
- //# sourceMappingURL=webhooks.cjs.map
474
+ exports.MockWebhooks = j;
475
+ exports.createWebhooksNamespace = Ie;
476
+ exports.verifyWebhookRequest = Re;
477
+ exports.verifyWebhookSignature = se;