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