@neetru/sdk 3.5.0 → 3.7.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 (114) hide show
  1. package/CHANGELOG.md +71 -1
  2. package/dist/ai.cjs +254 -391
  3. package/dist/ai.d.cts +1 -1
  4. package/dist/ai.d.ts +1 -1
  5. package/dist/ai.mjs +254 -391
  6. package/dist/auth.cjs +3560 -4993
  7. package/dist/auth.d.cts +1 -1
  8. package/dist/auth.d.ts +1 -1
  9. package/dist/auth.mjs +3557 -4990
  10. package/dist/build-guard.cjs +101 -119
  11. package/dist/build-guard.mjs +91 -109
  12. package/dist/catalog.cjs +152 -224
  13. package/dist/catalog.d.cts +1 -1
  14. package/dist/catalog.d.ts +1 -1
  15. package/dist/catalog.mjs +152 -224
  16. package/dist/checkout.cjs +237 -320
  17. package/dist/checkout.d.cts +1 -1
  18. package/dist/checkout.d.ts +1 -1
  19. package/dist/checkout.mjs +236 -319
  20. package/dist/db-react.cjs +59 -87
  21. package/dist/db-react.d.cts +1 -1
  22. package/dist/db-react.d.ts +1 -1
  23. package/dist/db-react.mjs +56 -84
  24. package/dist/db.cjs +2055 -3013
  25. package/dist/db.d.cts +1 -1
  26. package/dist/db.d.ts +1 -1
  27. package/dist/db.mjs +2068 -3026
  28. package/dist/entitlements.cjs +12 -20
  29. package/dist/entitlements.d.cts +1 -1
  30. package/dist/entitlements.d.ts +1 -1
  31. package/dist/entitlements.mjs +12 -20
  32. package/dist/errors.cjs +9 -12
  33. package/dist/errors.d.cts +37 -2
  34. package/dist/errors.d.ts +37 -2
  35. package/dist/errors.mjs +8 -12
  36. package/dist/firestore-compat.cjs +241 -297
  37. package/dist/firestore-compat.d.cts +1 -1
  38. package/dist/firestore-compat.d.ts +1 -1
  39. package/dist/firestore-compat.mjs +215 -271
  40. package/dist/index.cjs +3627 -5135
  41. package/dist/index.d.cts +6 -4
  42. package/dist/index.d.ts +6 -4
  43. package/dist/index.mjs +3731 -5239
  44. package/dist/mobile.cjs +411 -0
  45. package/dist/mobile.d.cts +89 -0
  46. package/dist/mobile.d.ts +89 -0
  47. package/dist/mobile.mjs +409 -0
  48. package/dist/mocks.cjs +312 -447
  49. package/dist/mocks.d.cts +1 -1
  50. package/dist/mocks.d.ts +1 -1
  51. package/dist/mocks.mjs +306 -441
  52. package/dist/notifications.cjs +226 -314
  53. package/dist/notifications.d.cts +1 -1
  54. package/dist/notifications.d.ts +1 -1
  55. package/dist/notifications.mjs +225 -313
  56. package/dist/react.cjs +522 -693
  57. package/dist/react.d.cts +1 -1
  58. package/dist/react.d.ts +1 -1
  59. package/dist/react.mjs +512 -683
  60. package/dist/support.cjs +329 -325
  61. package/dist/support.d.cts +25 -3
  62. package/dist/support.d.ts +25 -3
  63. package/dist/support.mjs +328 -325
  64. package/dist/telemetry.cjs +197 -301
  65. package/dist/telemetry.d.cts +1 -1
  66. package/dist/telemetry.d.ts +1 -1
  67. package/dist/telemetry.mjs +197 -301
  68. package/dist/{types-Du_iioJ7.d.cts → types-Bx4kTLmk.d.cts} +26 -0
  69. package/dist/{types-BPATkXYu.d.ts → types-Dx0IrOSF.d.ts} +26 -0
  70. package/dist/usage.cjs +163 -227
  71. package/dist/usage.d.cts +1 -1
  72. package/dist/usage.d.ts +1 -1
  73. package/dist/usage.mjs +163 -227
  74. package/dist/webhooks.cjs +258 -359
  75. package/dist/webhooks.d.cts +1 -1
  76. package/dist/webhooks.d.ts +1 -1
  77. package/dist/webhooks.mjs +255 -356
  78. package/package.json +9 -3
  79. package/dist/ai.cjs.map +0 -1
  80. package/dist/ai.mjs.map +0 -1
  81. package/dist/auth.cjs.map +0 -1
  82. package/dist/auth.mjs.map +0 -1
  83. package/dist/build-guard.cjs.map +0 -1
  84. package/dist/build-guard.mjs.map +0 -1
  85. package/dist/catalog.cjs.map +0 -1
  86. package/dist/catalog.mjs.map +0 -1
  87. package/dist/checkout.cjs.map +0 -1
  88. package/dist/checkout.mjs.map +0 -1
  89. package/dist/db-react.cjs.map +0 -1
  90. package/dist/db-react.mjs.map +0 -1
  91. package/dist/db.cjs.map +0 -1
  92. package/dist/db.mjs.map +0 -1
  93. package/dist/entitlements.cjs.map +0 -1
  94. package/dist/entitlements.mjs.map +0 -1
  95. package/dist/errors.cjs.map +0 -1
  96. package/dist/errors.mjs.map +0 -1
  97. package/dist/firestore-compat.cjs.map +0 -1
  98. package/dist/firestore-compat.mjs.map +0 -1
  99. package/dist/index.cjs.map +0 -1
  100. package/dist/index.mjs.map +0 -1
  101. package/dist/mocks.cjs.map +0 -1
  102. package/dist/mocks.mjs.map +0 -1
  103. package/dist/notifications.cjs.map +0 -1
  104. package/dist/notifications.mjs.map +0 -1
  105. package/dist/react.cjs.map +0 -1
  106. package/dist/react.mjs.map +0 -1
  107. package/dist/support.cjs.map +0 -1
  108. package/dist/support.mjs.map +0 -1
  109. package/dist/telemetry.cjs.map +0 -1
  110. package/dist/telemetry.mjs.map +0 -1
  111. package/dist/usage.cjs.map +0 -1
  112. package/dist/usage.mjs.map +0 -1
  113. package/dist/webhooks.cjs.map +0 -1
  114. 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,247 @@ 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
+ constructor(e, r, n, i, o) {
16
+ super(r), this.name = "NeetruError", this.code = e, this.status = n, this.requestId = i, this.reason = o, Object.setPrototypeOf(this, t.prototype);
23
17
  }
24
18
  };
25
19
 
26
20
  // 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(
21
+ function S() {
22
+ let t = typeof globalThis < "u" && "crypto" in globalThis ? globalThis.crypto : void 0;
23
+ if (t && typeof t.randomUUID == "function")
24
+ return t.randomUUID();
25
+ throw new s(
33
26
  "runtime_unsupported",
34
27
  "crypto.randomUUID not available in this runtime. SDK 3.0 requires Node \u226520 or modern browser/Edge."
35
28
  );
36
29
  }
37
30
 
38
31
  // src/http.ts
39
- var COMPAT_MATRIX = {
32
+ var H = {
40
33
  // SDK major 3.x requer Core ≥ 2026.05.1 (suporte a X-Neetru-Version header,
41
34
  // runTransaction write-after-read, verifyWebhookRequest, webhooks 3.0+)
42
35
  3: "2026.05.1"
43
36
  };
44
- function stripRevision(v) {
45
- return v.split("+")[0] ?? v;
37
+ function A(t) {
38
+ return t.split("+")[0] ?? t;
46
39
  }
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;
40
+ function j(t, e) {
41
+ let r = A(t).split(".").map(Number), n = A(e).split(".").map(Number), i = Math.max(r.length, n.length);
42
+ for (let o = 0; o < i; o++) {
43
+ let d = r[o] ?? 0, c = n[o] ?? 0;
44
+ if (d !== c) return d - c;
55
45
  }
56
46
  return 0;
57
47
  }
58
- function readInjectedSdkVersion() {
48
+ function q() {
59
49
  try {
60
- return "3.5.0";
50
+ return "3.7.0";
61
51
  } catch {
62
- return void 0;
52
+ return;
63
53
  }
64
54
  }
65
- function getSdkMajor() {
66
- const ver = readInjectedSdkVersion();
67
- if (ver) return parseInt(ver.split(".")[0] ?? "3", 10);
68
- return 3;
55
+ function V() {
56
+ let t = q();
57
+ return t ? parseInt(t.split(".")[0] ?? "3", 10) : 3;
69
58
  }
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
- }
59
+ var W = /* @__PURE__ */ new Set();
60
+ function B(t) {
61
+ if (!t) return;
62
+ let e = V(), r = H[e];
63
+ if (!r) return;
64
+ let n = A(t);
65
+ if (j(n, r) < 0) {
66
+ let i = `${e}:${n}`;
67
+ W.has(i) || (W.add(i), console.warn(
68
+ `[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.`
69
+ ));
85
70
  }
86
71
  }
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([
72
+ var L = 2, F = 0, z = /* @__PURE__ */ new Set(["GET", "HEAD"]), G = /* @__PURE__ */ new Set([
91
73
  "rate_limited",
92
74
  "server_error",
93
75
  "network_error"
94
76
  ]);
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));
77
+ function N(t) {
78
+ let e = 200 * Math.pow(4, t), r = e * 0.2 * (Math.random() * 2 - 1);
79
+ return Math.max(50, Math.round(e + r));
99
80
  }
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);
81
+ var C = 6e4;
82
+ function J(t) {
83
+ if (!t) return null;
84
+ let e = Number(t);
85
+ if (Number.isFinite(e) && e >= 0) return Math.min(Math.round(e * 1e3), C);
86
+ let r = Date.parse(t);
87
+ if (Number.isFinite(r)) {
88
+ let n = r - Date.now();
89
+ if (n > 0) return Math.min(n, C);
109
90
  }
110
91
  return null;
111
92
  }
112
- function sleep(ms) {
113
- return new Promise((resolve) => setTimeout(resolve, ms));
93
+ function D(t) {
94
+ return new Promise((e) => setTimeout(e, t));
114
95
  }
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";
96
+ function Y(t) {
97
+ 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
98
  }
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();
99
+ function X(t, e, r) {
100
+ let n = t.replace(/\/+$/, ""), i = e.startsWith("/") ? e : `/${e}`, o = new URL(`${n}${i}`);
101
+ if (r)
102
+ for (let [d, c] of Object.entries(r))
103
+ c !== void 0 && o.searchParams.set(d, String(c));
104
+ return o.toString();
136
105
  }
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
- }
106
+ async function M(t) {
107
+ let e = await t.text();
108
+ if (e)
109
+ try {
110
+ return JSON.parse(e);
111
+ } catch {
112
+ return;
113
+ }
145
114
  }
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 = {
115
+ async function _(t, e) {
116
+ let r = e.method ?? "GET", n = X(t.baseUrl, e.path, e.query), i = z.has(r) ? L : F, o = e.retries ?? i, d = {
152
117
  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(
118
+ ...e.headers
119
+ }, c = q();
120
+ if (c && (d["x-neetru-sdk-version"] = c), e.requireAuth) {
121
+ if (!t.apiKey)
122
+ throw new s(
162
123
  "missing_api_key",
163
124
  "This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var."
164
125
  );
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;
126
+ d.authorization = `Bearer ${t.apiKey}`;
127
+ }
128
+ if (e.idempotencyKey) {
129
+ let l = typeof e.idempotencyKey == "string" ? e.idempotencyKey : S();
130
+ d["idempotency-key"] = l;
131
+ }
132
+ let y = e.body !== void 0 && r !== "GET" && r !== "DELETE" ? JSON.stringify(e.body) : void 0;
133
+ y !== void 0 && (d["content-type"] = "application/json");
134
+ let h = null, f = e.deadlineMs != null ? Date.now() + e.deadlineMs : null;
135
+ for (let l = 0; l <= o; l++) {
136
+ if (f != null && Date.now() >= f)
137
+ throw h ?? new s("network_error", "Deadline excedido antes de completar a request");
138
+ let m = { method: r, headers: d };
139
+ y !== void 0 && (m.body = y);
140
+ let k = f != null ? Math.max(1, Math.min(3e4, f - Date.now())) : 3e4;
141
+ m.signal = AbortSignal.timeout(k);
142
+ let u;
182
143
  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;
144
+ u = await t.fetch(n, m);
145
+ } catch (a) {
146
+ let w = a instanceof DOMException && a.name === "TimeoutError" ? "Network error: timeout after 30s" : `Network error: ${a instanceof Error ? a.message : "fetch failed"}`;
147
+ if (h = new s("network_error", w), l < o) {
148
+ let x = N(l);
149
+ if (f == null || Date.now() + x < f) {
150
+ await D(x);
151
+ continue;
152
+ }
190
153
  }
191
- throw lastError;
154
+ throw h;
192
155
  }
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;
156
+ let g = u.headers.get("x-request-id") ?? u.headers.get("x-correlation-id") ?? void 0;
157
+ if (u.ok) {
158
+ let a = u.headers.get("x-neetru-version");
159
+ return a && B(a), await M(u);
199
160
  }
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;
161
+ let p = await M(u), v = Y(u.status), b = `HTTP ${u.status}`, R;
162
+ if (p && typeof p == "object") {
163
+ let a = p.error;
164
+ typeof a == "string" ? b = a : a && typeof a == "object" ? (typeof a.code == "string" && (v = a.code), typeof a.message == "string" && (b = a.message), typeof a.reason == "string" && (R = a.reason)) : (typeof p.code == "string" && (v = p.code), typeof p.message == "string" && (b = p.message)), typeof p.reason == "string" && (R = p.reason);
165
+ }
166
+ if (u.status === 410) {
167
+ let a = u.headers.get("x-neetru-replacement");
168
+ b === `HTTP ${u.status}` && (b = `Endpoint ${e.path} foi removido do Core (HTTP 410 Gone) \u2014 atualize o @neetru/sdk e migre para a API substituta.`), a && !b.includes(a) && (b += ` Substituto: ${a}.`);
217
169
  }
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;
170
+ let T = new s(v, b, u.status, g, R);
171
+ if (h = T, G.has(v) && l < o) {
172
+ let w = J(u.headers.get("retry-after")) ?? N(l);
173
+ if (f == null || Date.now() + w < f) {
174
+ await D(w);
175
+ continue;
176
+ }
226
177
  }
227
- throw err;
178
+ throw T;
228
179
  }
229
- throw lastError ?? new NeetruError("unknown", "unexpected httpRequest exit");
180
+ throw h ?? new s("unknown", "unexpected httpRequest exit");
230
181
  }
231
182
 
232
183
  // 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(
184
+ var O = /^[a-z0-9][a-z0-9_-]{0,62}$/i;
185
+ function I(t, e) {
186
+ if (typeof e != "string" || !O.test(e))
187
+ throw new s(
237
188
  "validation_failed",
238
- `${field} must match ${SDK_ID_RE.source} (lowercase alphanumeric, _, -; first char must be alphanumeric; max 63 chars)`
189
+ `${t} must match ${O.source} (lowercase alphanumeric, _, -; first char must be alphanumeric; max 63 chars)`
239
190
  );
240
- }
241
191
  }
242
192
 
243
193
  // 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(
194
+ async function Q(t, e, r, n) {
195
+ if (!e || !r) return false;
196
+ let i = e.startsWith("sha256=") ? e.slice(7) : e;
197
+ if (!/^[0-9a-f]+$/i.test(i)) return false;
198
+ let o = typeof globalThis < "u" && "crypto" in globalThis ? globalThis.crypto?.subtle : void 0;
199
+ if (!o)
200
+ throw new s(
251
201
  "runtime_unsupported",
252
202
  "verifyWebhookSignature requires globalThis.crypto.subtle (Node \u226520, modern browser, or Edge runtime)."
253
203
  );
204
+ let d = new TextEncoder(), c = d.encode(r), y = typeof t == "string" ? d.encode(t) : t, h = y;
205
+ if (n !== void 0) {
206
+ let g = d.encode(`${n}.`), p = new Uint8Array(g.length + y.length);
207
+ p.set(g, 0), p.set(y, g.length), h = p;
254
208
  }
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(
209
+ let f = await o.importKey(
267
210
  "raw",
268
- keyBytes,
211
+ c,
269
212
  { name: "HMAC", hash: "SHA-256" },
270
213
  false,
271
214
  ["sign"]
272
- );
273
- const macBuffer = await subtle.sign(
215
+ ), l = await o.sign(
274
216
  "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;
217
+ f,
218
+ h
219
+ ), m = new Uint8Array(l), k = Z(i.toLowerCase());
220
+ if (!k || k.length !== m.length) return false;
221
+ let u = 0;
222
+ for (let g = 0; g < m.length; g++)
223
+ u |= m[g] ^ k[g];
224
+ return u === 0;
286
225
  }
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
- }
226
+ async function pe(t, e, r, n = {}) {
227
+ let i = n.toleranceMs ?? 3e5, o = (l) => {
228
+ if (typeof e.get == "function")
229
+ return e.get(l);
230
+ let m = e, k = l.toLowerCase();
231
+ for (let u of Object.keys(m))
232
+ if (u.toLowerCase() === k) return m[u] ?? null;
298
233
  return null;
299
- };
300
- const tsHeader = getHeader("x-neetru-timestamp");
301
- if (!tsHeader) {
234
+ }, d = o("x-neetru-timestamp");
235
+ if (!d)
302
236
  return { ok: false, reason: "timestamp_missing" };
303
- }
304
- const tsMs = Number(tsHeader);
305
- if (!Number.isFinite(tsMs)) {
237
+ let c = Number(d);
238
+ if (!Number.isFinite(c))
306
239
  return { ok: false, reason: "timestamp_missing" };
307
- }
308
- const skewMs = Math.abs(Date.now() - tsMs);
309
- if (skewMs > toleranceMs) {
240
+ if (Math.abs(Date.now() - c) > i)
310
241
  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 };
242
+ let h = o("x-neetru-signature");
243
+ return await Q(t, h, r, d) ? { ok: true } : { ok: false, reason: "invalid_signature" };
318
244
  }
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;
245
+ function Z(t) {
246
+ if (t.length % 2 !== 0) return null;
247
+ let e = new Uint8Array(t.length / 2);
248
+ for (let r = 0; r < e.length; r++) {
249
+ let n = parseInt(t[r * 2], 16), i = parseInt(t[r * 2 + 1], 16);
250
+ if (Number.isNaN(n) || Number.isNaN(i)) return null;
251
+ e[r] = n << 4 | i;
252
+ }
253
+ return e;
329
254
  }
330
- var VALID_EVENTS = [
255
+ var $ = [
331
256
  "subscription.activated",
332
257
  "subscription.cancelled",
333
258
  "subscription.payment_failed",
@@ -337,80 +262,66 @@ var VALID_EVENTS = [
337
262
  "account.reactivated",
338
263
  "support.ticket_replied"
339
264
  ];
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
- }
265
+ function U(t) {
266
+ if (!t || typeof t != "object")
267
+ throw new s("invalid_response", "Webhook response is not an object");
268
+ let e = t;
269
+ if (typeof e.id != "string")
270
+ throw new s("invalid_response", "Webhook missing id");
348
271
  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)
272
+ id: e.id,
273
+ url: typeof e.url == "string" ? e.url : "",
274
+ events: Array.isArray(e.events) ? e.events.filter(
275
+ (r) => $.includes(r)
353
276
  ) : [],
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()
277
+ hasSecret: e.hasSecret === true,
278
+ status: e.status === "active" || e.status === "degraded" || e.status === "disabled" ? e.status : "active",
279
+ lastDeliveryAt: typeof e.lastDeliveryAt == "string" ? e.lastDeliveryAt : void 0,
280
+ consecutiveFailures: typeof e.consecutiveFailures == "number" ? e.consecutiveFailures : void 0,
281
+ createdAt: typeof e.createdAt == "string" ? e.createdAt : (/* @__PURE__ */ new Date()).toISOString()
359
282
  };
360
283
  }
361
- function validateInput(input) {
362
- if (!input.url || typeof input.url !== "string") {
363
- throw new NeetruError("validation_failed", "url \xE9 obrigat\xF3ria");
364
- }
284
+ function K(t) {
285
+ if (!t.url || typeof t.url != "string")
286
+ throw new s("validation_failed", "url \xE9 obrigat\xF3ria");
365
287
  try {
366
- const parsed = new URL(input.url);
367
- if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
288
+ let e = new URL(t.url);
289
+ if (e.protocol !== "https:" && e.protocol !== "http:")
368
290
  throw new Error("invalid protocol");
369
- }
370
291
  } 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
- }
292
+ throw new s("validation_failed", `url inv\xE1lida: ${t.url}`);
293
+ }
294
+ if (!Array.isArray(t.events) || t.events.length === 0)
295
+ throw new s("validation_failed", "events deve ter pelo menos 1 evento");
296
+ for (let e of t.events)
297
+ if (!$.includes(e))
298
+ throw new s("validation_failed", `evento desconhecido: ${e}`);
299
+ if (t.secret !== void 0 && t.secret.length < 16)
300
+ throw new s("validation_failed", "secret deve ter \u226516 chars (recomendado 32+)");
384
301
  }
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(
302
+ function E(t, ...e) {
303
+ for (let r of e)
304
+ if (typeof r == "string" && r.length > 0)
305
+ return I("productId", r), r;
306
+ if (t.productId)
307
+ return I("productId", t.productId), t.productId;
308
+ throw new s(
397
309
  "validation_failed",
398
310
  "productId required (pass to options/input or set on createNeetruClient)"
399
311
  );
400
312
  }
401
- function createWebhooksNamespace(config) {
313
+ function fe(t) {
402
314
  return {
403
- async register(input) {
404
- validateInput(input);
405
- const productId = resolveProductId(config, input.productId);
406
- const raw = await httpRequest(config, {
315
+ async register(e) {
316
+ K(e);
317
+ let r = E(t, e.productId), n = await _(t, {
407
318
  method: "POST",
408
319
  path: "/api/sdk/v1/webhooks",
409
320
  body: {
410
- productId,
411
- url: input.url,
412
- events: input.events,
413
- ...input.secret ? { secret: input.secret } : {}
321
+ productId: r,
322
+ url: e.url,
323
+ events: e.events,
324
+ ...e.secret ? { secret: e.secret } : {}
414
325
  },
415
326
  requireAuth: true,
416
327
  // Sem isso, um retry de rede (app-level; SDK default é 0 retries em
@@ -419,88 +330,76 @@ function createWebhooksNamespace(config) {
419
330
  // dedup TTL 24h (mesmo padrão de usage.report/support.createTicket).
420
331
  idempotencyKey: true
421
332
  });
422
- return toEndpoint(raw);
333
+ return U(n);
423
334
  },
424
- async list(options) {
425
- const productId = resolveProductId(config, options?.productId);
426
- const raw = await httpRequest(config, {
335
+ async list(e) {
336
+ let r = E(t, e?.productId), n = await _(t, {
427
337
  method: "GET",
428
338
  path: "/api/sdk/v1/webhooks",
429
- query: { productId },
339
+ query: { productId: r },
430
340
  requireAuth: true
431
341
  });
432
- const list = Array.isArray(raw?.endpoints) ? raw.endpoints : [];
433
- return list.map(toEndpoint);
342
+ return (Array.isArray(n?.endpoints) ? n.endpoints : []).map(U);
434
343
  },
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, {
344
+ async unregister(e, r) {
345
+ if (!e) throw new s("validation_failed", "id obrigat\xF3rio");
346
+ let n = E(t, r?.productId);
347
+ return await _(t, {
439
348
  method: "DELETE",
440
- path: `/api/sdk/v1/webhooks/${encodeURIComponent(id)}`,
441
- query: { productId },
349
+ path: `/api/sdk/v1/webhooks/${encodeURIComponent(e)}`,
350
+ query: { productId: n },
442
351
  requireAuth: true
443
- });
444
- return { ok: true };
352
+ }), { ok: true };
445
353
  },
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, {
354
+ async test(e, r) {
355
+ if (!e) throw new s("validation_failed", "id obrigat\xF3rio");
356
+ let n = E(t, r?.productId), i = await _(t, {
450
357
  method: "POST",
451
- path: `/api/sdk/v1/webhooks/${encodeURIComponent(id)}/test`,
452
- query: { productId },
358
+ path: `/api/sdk/v1/webhooks/${encodeURIComponent(e)}/test`,
359
+ query: { productId: n },
453
360
  requireAuth: true,
454
361
  idempotencyKey: true
455
362
  });
456
- if (!raw || typeof raw !== "object") {
363
+ if (!i || typeof i != "object")
457
364
  return { ok: false, error: "invalid response" };
458
- }
459
- const r = raw;
365
+ let o = i;
460
366
  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
367
+ ok: o.ok === true,
368
+ statusCode: typeof o.statusCode == "number" ? o.statusCode : void 0,
369
+ durationMs: typeof o.durationMs == "number" ? o.durationMs : void 0,
370
+ error: typeof o.error == "string" ? o.error : void 0
465
371
  };
466
372
  }
467
373
  };
468
374
  }
469
- var MockWebhooks = class {
375
+ var P = class {
470
376
  endpoints = /* @__PURE__ */ new Map();
471
377
  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,
378
+ async register(e) {
379
+ K(e);
380
+ let r = `mock_wh_${this.nextId++}`, n = {
381
+ id: r,
382
+ url: e.url,
383
+ events: e.events,
384
+ hasSecret: !!e.secret,
480
385
  status: "active",
481
386
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
482
387
  };
483
- this.endpoints.set(id, endpoint);
484
- return endpoint;
388
+ return this.endpoints.set(r, n), n;
485
389
  }
486
- async list(_options) {
390
+ async list(e) {
487
391
  return [...this.endpoints.values()];
488
392
  }
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 };
393
+ async unregister(e, r) {
394
+ if (!this.endpoints.has(e))
395
+ throw new s("not_found", `Webhook ${e} n\xE3o encontrado`);
396
+ return this.endpoints.delete(e), { ok: true };
495
397
  }
496
- async test(id, _options) {
497
- if (!this.endpoints.has(id)) {
498
- throw new NeetruError("not_found", `Webhook ${id} n\xE3o encontrado`);
499
- }
398
+ async test(e, r) {
399
+ if (!this.endpoints.has(e))
400
+ throw new s("not_found", `Webhook ${e} n\xE3o encontrado`);
500
401
  return { ok: true, statusCode: 200, durationMs: 42 };
501
402
  }
502
403
  };
503
404
 
504
- export { MockWebhooks, createWebhooksNamespace, verifyWebhookRequest, verifyWebhookSignature };
505
- //# sourceMappingURL=webhooks.mjs.map
506
- //# sourceMappingURL=webhooks.mjs.map
405
+ export { P as MockWebhooks, fe as createWebhooksNamespace, pe as verifyWebhookRequest, Q as verifyWebhookSignature };