@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
@@ -1,5 +1,5 @@
1
1
  // src/errors.ts
2
- var NeetruError = class _NeetruError extends Error {
2
+ var i = class t extends Error {
3
3
  code;
4
4
  status;
5
5
  requestId;
@@ -12,420 +12,399 @@ 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, s, d) {
23
+ super(r), this.name = "NeetruError", this.code = e, this.status = n, this.requestId = o, this.reason = s, this.correlationId = d, 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 x() {
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 i(
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 B = /^[A-Za-z0-9._:\-]+$/;
41
+ function T(t) {
42
+ return typeof t == "string" && t.length > 0 && t.length <= 128 && B.test(t);
43
+ }
44
+ function G() {
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 [s, d] of Object.entries(t)) {
65
+ if (s.toLowerCase() === D) {
66
+ T(d) && (r = d);
67
+ continue;
68
+ }
69
+ n[s] = d;
70
+ }
71
+ let o = r ?? (T(e) ? e : void 0) ?? G();
72
+ return n[D] = o, { headers: n, correlationId: o };
73
+ }
74
+
75
+ // src/server-only-key.ts
76
+ function P() {
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 X = {
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 k(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 Y(t, e) {
100
+ let r = k(t).split(".").map(Number), n = k(e).split(".").map(Number), o = Math.max(r.length, n.length);
101
+ for (let s = 0; s < o; s++) {
102
+ let d = r[s] ?? 0, u = n[s] ?? 0;
103
+ if (d !== u) return d - u;
55
104
  }
56
105
  return 0;
57
106
  }
58
- function readInjectedSdkVersion() {
107
+ function q() {
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 J() {
115
+ let t = q();
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 C = /* @__PURE__ */ new Set();
119
+ function W(t) {
120
+ if (!t) return;
121
+ let e = J(), r = X[e];
122
+ if (!r) return;
123
+ let n = k(t);
124
+ if (Y(n, r) < 0) {
125
+ let o = `${e}:${n}`;
126
+ C.has(o) || (C.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 P() ? "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 M = 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), M);
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, M);
109
153
  }
110
154
  return null;
111
155
  }
112
- function sleep(ms) {
113
- return new Promise((resolve) => setTimeout(resolve, ms));
156
+ function $(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));
162
+ function ie(t, e, r) {
163
+ let n = t.replace(/\/+$/, ""), o = e.startsWith("/") ? e : `/${e}`, s = new URL(`${n}${o}`);
164
+ if (r)
165
+ for (let [d, u] of Object.entries(r))
166
+ u !== void 0 && s.searchParams.set(d, String(u));
167
+ return s.toString();
168
+ }
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;
133
176
  }
134
- }
135
- return url.toString();
136
177
  }
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;
178
+ async function h(t, e) {
179
+ let r = e.method ?? "GET", n = ie(t.baseUrl, e.path, e.query), o = te.has(r) ? Q : ee, s = e.retries ?? o, { headers: d, correlationId: u } = O(
180
+ { accept: "application/json", ...e.headers },
181
+ e.correlationId
182
+ ), E = q();
183
+ if (E && (d["x-neetru-sdk-version"] = E), e.requireAuth) {
184
+ if (!t.apiKey)
185
+ throw new i("missing_api_key", Z());
186
+ d.authorization = `Bearer ${t.apiKey}`;
144
187
  }
145
- }
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;
188
+ if (e.idempotencyKey) {
189
+ let p = typeof e.idempotencyKey == "string" ? e.idempotencyKey : x();
190
+ d["idempotency-key"] = p;
158
191
  }
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."
192
+ let b = e.body !== void 0 && r !== "GET" && r !== "DELETE" ? JSON.stringify(e.body) : void 0;
193
+ b !== void 0 && (d["content-type"] = "application/json");
194
+ let g = null, l = e.deadlineMs != null ? Date.now() + e.deadlineMs : null;
195
+ for (let p = 0; p <= s; p++) {
196
+ if (l != null && Date.now() >= l)
197
+ throw g ?? new i(
198
+ "network_error",
199
+ "Deadline excedido antes de completar a request",
200
+ void 0,
201
+ void 0,
202
+ void 0,
203
+ u
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 v = { method: r, headers: d };
206
+ b !== void 0 && (v.body = b);
207
+ let z = l != null ? Math.max(1, Math.min(3e4, l - Date.now())) : 3e4;
208
+ v.signal = AbortSignal.timeout(z);
209
+ let c;
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
+ c = await t.fetch(n, v);
212
+ } catch (a) {
213
+ let y = a instanceof DOMException && a.name === "TimeoutError" ? "Network error: timeout after 30s" : `Network error: ${a instanceof Error ? a.message : "fetch failed"}`;
214
+ if (g = new i("network_error", y, void 0, void 0, void 0, u), p < s) {
215
+ let A = U(p);
216
+ if (l == null || Date.now() + A < l) {
217
+ await $(A);
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 F = c.headers.get("x-request-id") ?? c.headers.get("x-correlation-id") ?? void 0;
224
+ if (c.ok) {
225
+ let a = c.headers.get("x-neetru-version");
226
+ return a && W(a), await K(c);
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 f = await K(c), _ = oe(c.status), m = `HTTP ${c.status}`, I;
229
+ if (f && typeof f == "object") {
230
+ let a = f.error;
231
+ typeof a == "string" ? m = a : a && typeof a == "object" ? (typeof a.code == "string" && (_ = a.code), typeof a.message == "string" && (m = a.message), typeof a.reason == "string" && (I = a.reason)) : (typeof f.code == "string" && (_ = f.code), typeof f.message == "string" && (m = f.message)), typeof f.reason == "string" && (I = f.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 (c.status === 410) {
234
+ let a = c.headers.get("x-neetru-replacement");
235
+ m === `HTTP ${c.status}` && (m = `Endpoint ${e.path} foi removido do Core (HTTP 410 Gone) \u2014 atualize o @neetru/sdk e migre para a API substituta.`), a && !m.includes(a) && (m += ` Substituto: ${a}.`);
226
236
  }
227
- throw err;
237
+ let S = new i(_, m, c.status, F, I, u);
238
+ if (g = S, re.has(_) && p < s) {
239
+ let y = ne(c.headers.get("retry-after")) ?? U(p);
240
+ if (l == null || Date.now() + y < l) {
241
+ await $(y);
242
+ continue;
243
+ }
244
+ }
245
+ throw S;
228
246
  }
229
- throw lastError ?? new NeetruError("unknown", "unexpected httpRequest exit");
247
+ throw g ?? new i("unknown", "unexpected httpRequest exit", void 0, void 0, void 0, u);
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 N(t, e) {
253
+ if (typeof e != "string" || !L.test(e))
254
+ throw new i(
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/notifications.ts
244
- var VALID_SEVERITIES = [
261
+ var R = [
245
262
  "info",
246
263
  "success",
247
264
  "warning",
248
265
  "error"
249
266
  ];
250
- function toNotification(raw) {
251
- if (!raw || typeof raw !== "object") {
252
- throw new NeetruError("invalid_response", "Notification response is not an object");
253
- }
254
- const r = raw;
255
- if (typeof r.id !== "string") {
256
- throw new NeetruError("invalid_response", "Notification missing id");
257
- }
258
- const sev = VALID_SEVERITIES.includes(r.severity) ? r.severity : "info";
267
+ function j(t) {
268
+ if (!t || typeof t != "object")
269
+ throw new i("invalid_response", "Notification response is not an object");
270
+ let e = t;
271
+ if (typeof e.id != "string")
272
+ throw new i("invalid_response", "Notification missing id");
273
+ let r = R.includes(e.severity) ? e.severity : "info";
259
274
  return {
260
- id: r.id,
261
- userId: typeof r.userId === "string" ? r.userId : "",
262
- kind: typeof r.kind === "string" ? r.kind : "unknown",
263
- severity: sev,
264
- title: typeof r.title === "string" ? r.title : "",
265
- body: typeof r.body === "string" ? r.body : void 0,
266
- link: typeof r.link === "string" ? r.link : void 0,
267
- metadata: r.metadata && typeof r.metadata === "object" ? r.metadata : void 0,
268
- createdAt: typeof r.createdAt === "string" ? r.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
269
- readAt: typeof r.readAt === "string" ? r.readAt : void 0,
270
- dismissedAt: typeof r.dismissedAt === "string" ? r.dismissedAt : void 0
275
+ id: e.id,
276
+ userId: typeof e.userId == "string" ? e.userId : "",
277
+ kind: typeof e.kind == "string" ? e.kind : "unknown",
278
+ severity: r,
279
+ title: typeof e.title == "string" ? e.title : "",
280
+ body: typeof e.body == "string" ? e.body : void 0,
281
+ link: typeof e.link == "string" ? e.link : void 0,
282
+ metadata: e.metadata && typeof e.metadata == "object" ? e.metadata : void 0,
283
+ createdAt: typeof e.createdAt == "string" ? e.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
284
+ readAt: typeof e.readAt == "string" ? e.readAt : void 0,
285
+ dismissedAt: typeof e.dismissedAt == "string" ? e.dismissedAt : void 0
271
286
  };
272
287
  }
273
- function validateInput(input) {
274
- if (!input.userId) throw new NeetruError("validation_failed", "userId obrigat\xF3rio");
275
- if (!input.kind) throw new NeetruError("validation_failed", "kind obrigat\xF3rio");
276
- if (!input.title) throw new NeetruError("validation_failed", "title obrigat\xF3rio");
277
- if (input.severity && !VALID_SEVERITIES.includes(input.severity)) {
278
- throw new NeetruError(
288
+ function H(t) {
289
+ if (!t.userId) throw new i("validation_failed", "userId obrigat\xF3rio");
290
+ if (!t.kind) throw new i("validation_failed", "kind obrigat\xF3rio");
291
+ if (!t.title) throw new i("validation_failed", "title obrigat\xF3rio");
292
+ if (t.severity && !R.includes(t.severity))
293
+ throw new i(
279
294
  "validation_failed",
280
- `severity inv\xE1lida: ${input.severity} (use ${VALID_SEVERITIES.join("|")})`
295
+ `severity inv\xE1lida: ${t.severity} (use ${R.join("|")})`
281
296
  );
282
- }
283
- if (input.title.length > 200) {
284
- throw new NeetruError("validation_failed", "title m\xE1x 200 chars");
285
- }
286
- if (input.body && input.body.length > 2e3) {
287
- throw new NeetruError("validation_failed", "body m\xE1x 2000 chars");
288
- }
297
+ if (t.title.length > 200)
298
+ throw new i("validation_failed", "title m\xE1x 200 chars");
299
+ if (t.body && t.body.length > 2e3)
300
+ throw new i("validation_failed", "body m\xE1x 2000 chars");
289
301
  }
290
- function resolveProductId(config, ...candidates) {
291
- for (const c of candidates) {
292
- if (typeof c === "string" && c.length > 0) {
293
- assertValidSdkId("productId", c);
294
- return c;
295
- }
296
- }
297
- if (config.productId) {
298
- assertValidSdkId("productId", config.productId);
299
- return config.productId;
300
- }
301
- throw new NeetruError(
302
+ function w(t, ...e) {
303
+ for (let r of e)
304
+ if (typeof r == "string" && r.length > 0)
305
+ return N("productId", r), r;
306
+ if (t.productId)
307
+ return N("productId", t.productId), t.productId;
308
+ throw new i(
302
309
  "validation_failed",
303
310
  "productId required (pass to options/input or set on createNeetruClient)"
304
311
  );
305
312
  }
306
- function createNotificationsNamespace(config) {
313
+ function Ie(t) {
307
314
  return {
308
- async send(input) {
309
- validateInput(input);
310
- const productId = resolveProductId(config, input.productId);
311
- const body = {
312
- productId,
313
- userId: input.userId,
314
- kind: input.kind,
315
- title: input.title,
316
- severity: input.severity ?? "info"
315
+ async send(e) {
316
+ H(e);
317
+ let n = {
318
+ productId: w(t, e.productId),
319
+ userId: e.userId,
320
+ kind: e.kind,
321
+ title: e.title,
322
+ severity: e.severity ?? "info"
317
323
  };
318
- if (input.body !== void 0) body.body = input.body;
319
- if (input.link !== void 0) body.link = input.link;
320
- if (input.metadata !== void 0) body.metadata = input.metadata;
321
- if (input.fingerprint !== void 0) body.fingerprint = input.fingerprint;
322
- const raw = await httpRequest(config, {
324
+ e.body !== void 0 && (n.body = e.body), e.link !== void 0 && (n.link = e.link), e.metadata !== void 0 && (n.metadata = e.metadata), e.fingerprint !== void 0 && (n.fingerprint = e.fingerprint);
325
+ let o = await h(t, {
323
326
  method: "POST",
324
327
  path: "/api/sdk/v1/notifications",
325
- body,
328
+ body: n,
326
329
  requireAuth: true,
327
330
  idempotencyKey: true
328
331
  });
329
- return toNotification(raw);
332
+ return j(o);
330
333
  },
331
- async list(userId, options) {
332
- if (!userId) throw new NeetruError("validation_failed", "userId obrigat\xF3rio");
333
- const productId = resolveProductId(config, options?.productId);
334
- const query = {
335
- productId
334
+ async list(e, r) {
335
+ if (!e) throw new i("validation_failed", "userId obrigat\xF3rio");
336
+ let o = {
337
+ productId: w(t, r?.productId)
336
338
  };
337
- if (options?.includeDismissed) query.includeDismissed = true;
338
- if (options?.onlyUnread) query.onlyUnread = true;
339
- if (options?.limit) {
340
- query.limit = Math.min(Math.max(1, options.limit), 200);
341
- }
342
- const raw = await httpRequest(config, {
339
+ r?.includeDismissed && (o.includeDismissed = true), r?.onlyUnread && (o.onlyUnread = true), r?.limit && (o.limit = Math.min(Math.max(1, r.limit), 200));
340
+ let s = await h(t, {
343
341
  method: "GET",
344
- path: `/api/sdk/v1/notifications/user/${encodeURIComponent(userId)}`,
345
- query,
342
+ path: `/api/sdk/v1/notifications/user/${encodeURIComponent(e)}`,
343
+ query: o,
346
344
  requireAuth: true
347
345
  });
348
- const list = Array.isArray(raw?.notifications) ? raw.notifications : [];
349
- return list.map(toNotification);
346
+ return (Array.isArray(s?.notifications) ? s.notifications : []).map(j);
350
347
  },
351
- async markRead(id, options) {
352
- if (!id) throw new NeetruError("validation_failed", "id obrigat\xF3rio");
353
- const productId = resolveProductId(config, options?.productId);
354
- await httpRequest(config, {
348
+ async markRead(e, r) {
349
+ if (!e) throw new i("validation_failed", "id obrigat\xF3rio");
350
+ let n = w(t, r?.productId);
351
+ return await h(t, {
355
352
  method: "POST",
356
- path: `/api/sdk/v1/notifications/${encodeURIComponent(id)}/read`,
357
- query: { productId },
353
+ path: `/api/sdk/v1/notifications/${encodeURIComponent(e)}/read`,
354
+ query: { productId: n },
358
355
  requireAuth: true
359
- });
360
- return { ok: true };
356
+ }), { ok: true };
361
357
  },
362
- async dismiss(id, options) {
363
- if (!id) throw new NeetruError("validation_failed", "id obrigat\xF3rio");
364
- const productId = resolveProductId(config, options?.productId);
365
- await httpRequest(config, {
358
+ async dismiss(e, r) {
359
+ if (!e) throw new i("validation_failed", "id obrigat\xF3rio");
360
+ let n = w(t, r?.productId);
361
+ return await h(t, {
366
362
  method: "POST",
367
- path: `/api/sdk/v1/notifications/${encodeURIComponent(id)}/dismiss`,
368
- query: { productId },
363
+ path: `/api/sdk/v1/notifications/${encodeURIComponent(e)}/dismiss`,
364
+ query: { productId: n },
369
365
  requireAuth: true
370
- });
371
- return { ok: true };
366
+ }), { ok: true };
372
367
  }
373
368
  };
374
369
  }
375
- var MockNotifications = class {
370
+ var V = class {
376
371
  notifications = /* @__PURE__ */ new Map();
377
372
  nextId = 1;
378
- async send(input) {
379
- validateInput(input);
380
- if (input.fingerprint) {
381
- const dayAgo = Date.now() - 864e5;
382
- for (const existing of this.notifications.values()) {
383
- const meta = existing.metadata ?? {};
384
- if (meta.fingerprint === input.fingerprint && existing.userId === input.userId && new Date(existing.createdAt).getTime() > dayAgo) {
385
- return existing;
386
- }
387
- }
373
+ async send(e) {
374
+ if (H(e), e.fingerprint) {
375
+ let o = Date.now() - 864e5;
376
+ for (let s of this.notifications.values())
377
+ if ((s.metadata ?? {}).fingerprint === e.fingerprint && s.userId === e.userId && new Date(s.createdAt).getTime() > o)
378
+ return s;
388
379
  }
389
- const id = `mock_notif_${this.nextId++}`;
390
- const notif = {
391
- id,
392
- userId: input.userId,
393
- kind: input.kind,
394
- severity: input.severity ?? "info",
395
- title: input.title,
396
- body: input.body,
397
- link: input.link,
398
- metadata: input.fingerprint ? { ...input.metadata ?? {}, fingerprint: input.fingerprint } : input.metadata,
380
+ let r = `mock_notif_${this.nextId++}`, n = {
381
+ id: r,
382
+ userId: e.userId,
383
+ kind: e.kind,
384
+ severity: e.severity ?? "info",
385
+ title: e.title,
386
+ body: e.body,
387
+ link: e.link,
388
+ metadata: e.fingerprint ? { ...e.metadata ?? {}, fingerprint: e.fingerprint } : e.metadata,
399
389
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
400
390
  };
401
- this.notifications.set(id, notif);
402
- return notif;
391
+ return this.notifications.set(r, n), n;
403
392
  }
404
- async list(userId, options) {
405
- if (!userId) throw new NeetruError("validation_failed", "userId obrigat\xF3rio");
406
- const limit = Math.min(Math.max(1, options?.limit ?? 50), 200);
407
- return [...this.notifications.values()].filter((n) => n.userId === userId).filter((n) => options?.includeDismissed || !n.dismissedAt).filter((n) => !options?.onlyUnread || !n.readAt).sort((a, b) => b.createdAt.localeCompare(a.createdAt)).slice(0, limit);
393
+ async list(e, r) {
394
+ if (!e) throw new i("validation_failed", "userId obrigat\xF3rio");
395
+ let n = Math.min(Math.max(1, r?.limit ?? 50), 200);
396
+ return [...this.notifications.values()].filter((o) => o.userId === e).filter((o) => r?.includeDismissed || !o.dismissedAt).filter((o) => !r?.onlyUnread || !o.readAt).sort((o, s) => s.createdAt.localeCompare(o.createdAt)).slice(0, n);
408
397
  }
409
- async markRead(id, _options) {
410
- const n = this.notifications.get(id);
411
- if (!n) throw new NeetruError("not_found", `Notification ${id} n\xE3o encontrada`);
412
- if (!n.readAt) {
413
- n.readAt = (/* @__PURE__ */ new Date()).toISOString();
414
- this.notifications.set(id, n);
415
- }
416
- return { ok: true };
398
+ async markRead(e, r) {
399
+ let n = this.notifications.get(e);
400
+ if (!n) throw new i("not_found", `Notification ${e} n\xE3o encontrada`);
401
+ return n.readAt || (n.readAt = (/* @__PURE__ */ new Date()).toISOString(), this.notifications.set(e, n)), { ok: true };
417
402
  }
418
- async dismiss(id, _options) {
419
- const n = this.notifications.get(id);
420
- if (!n) throw new NeetruError("not_found", `Notification ${id} n\xE3o encontrada`);
421
- if (!n.dismissedAt) {
422
- n.dismissedAt = (/* @__PURE__ */ new Date()).toISOString();
423
- this.notifications.set(id, n);
424
- }
425
- return { ok: true };
403
+ async dismiss(e, r) {
404
+ let n = this.notifications.get(e);
405
+ if (!n) throw new i("not_found", `Notification ${e} n\xE3o encontrada`);
406
+ return n.dismissedAt || (n.dismissedAt = (/* @__PURE__ */ new Date()).toISOString(), this.notifications.set(e, n)), { ok: true };
426
407
  }
427
408
  };
428
409
 
429
- export { MockNotifications, createNotificationsNamespace };
430
- //# sourceMappingURL=notifications.mjs.map
431
- //# sourceMappingURL=notifications.mjs.map
410
+ export { V as MockNotifications, Ie as createNotificationsNamespace };