@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 d = class e extends Error {
3
3
  code;
4
4
  status;
5
5
  requestId;
@@ -12,233 +12,251 @@ 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(t, n, o, i, u, r) {
23
+ super(n), this.name = "NeetruError", this.code = t, this.status = o, this.requestId = i, this.reason = u, this.correlationId = r, Object.setPrototypeOf(this, e.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 I() {
29
+ let e = typeof globalThis < "u" && "crypto" in globalThis ? globalThis.crypto : void 0;
30
+ if (e && typeof e.randomUUID == "function")
31
+ return e.randomUUID();
32
+ throw new d(
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 A = "x-correlation-id";
40
+ var j = /^[A-Za-z0-9._:\-]+$/;
41
+ function S(e) {
42
+ return typeof e == "string" && e.length > 0 && e.length <= 128 && j.test(e);
43
+ }
44
+ function H() {
45
+ let e = globalThis.crypto;
46
+ try {
47
+ if (e && typeof e.randomUUID == "function") return e.randomUUID();
48
+ } catch {
49
+ }
50
+ let t = new Uint8Array(16), n = false;
51
+ try {
52
+ e && typeof e.getRandomValues == "function" && (e.getRandomValues(t), n = !0);
53
+ } catch {
54
+ n = false;
55
+ }
56
+ if (!n)
57
+ for (let i = 0; i < t.length; i++) t[i] = Math.floor(Math.random() * 256);
58
+ t[6] = t[6] & 15 | 64, t[8] = t[8] & 63 | 128;
59
+ let o = Array.from(t, (i) => i.toString(16).padStart(2, "0")).join("");
60
+ return `${o.slice(0, 8)}-${o.slice(8, 12)}-${o.slice(12, 16)}-${o.slice(16, 20)}-${o.slice(20)}`;
61
+ }
62
+ function N(e, t) {
63
+ let n, o = {};
64
+ for (let [u, r] of Object.entries(e)) {
65
+ if (u.toLowerCase() === A) {
66
+ S(r) && (n = r);
67
+ continue;
68
+ }
69
+ o[u] = r;
70
+ }
71
+ let i = n ?? (S(t) ? t : void 0) ?? H();
72
+ return o[A] = i, { headers: o, correlationId: i };
73
+ }
74
+
75
+ // src/server-only-key.ts
76
+ function x() {
77
+ try {
78
+ let e = globalThis.navigator;
79
+ if (e && e.product === "ReactNative") return "react-native";
80
+ } catch {
81
+ }
82
+ try {
83
+ let e = globalThis;
84
+ if (typeof e.window < "u" && typeof e.document < "u") return "browser";
85
+ } catch {
86
+ }
87
+ return null;
88
+ }
89
+
38
90
  // src/http.ts
39
- var COMPAT_MATRIX = {
91
+ var F = {
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 R(e) {
97
+ return e.split("+")[0] ?? e;
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 V(e, t) {
100
+ let n = R(e).split(".").map(Number), o = R(t).split(".").map(Number), i = Math.max(n.length, o.length);
101
+ for (let u = 0; u < i; u++) {
102
+ let r = n[u] ?? 0, a = o[u] ?? 0;
103
+ if (r !== a) return r - a;
55
104
  }
56
105
  return 0;
57
106
  }
58
- function readInjectedSdkVersion() {
107
+ function L() {
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 B() {
115
+ let e = L();
116
+ return e ? parseInt(e.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 D = /* @__PURE__ */ new Set();
119
+ function z(e) {
120
+ if (!e) return;
121
+ let t = B(), n = F[t];
122
+ if (!n) return;
123
+ let o = R(e);
124
+ if (V(o, n) < 0) {
125
+ let i = `${t}:${o}`;
126
+ D.has(i) || (D.add(i), console.warn(
127
+ `[Neetru SDK] Aten\xE7\xE3o: Core vers\xE3o "${e}" \xE9 anterior ao m\xEDnimo recomendado "${n}" para SDK major ${t}. 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 G() {
132
+ let e = "This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var.";
133
+ return x() ? "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. (" + e + ")" : e;
134
+ }
135
+ var X = 2, Y = 0, J = /* @__PURE__ */ new Set(["GET", "HEAD"]), W = /* @__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 C(e) {
141
+ let t = 200 * Math.pow(4, e), n = t * 0.2 * (Math.random() * 2 - 1);
142
+ return Math.max(50, Math.round(t + n));
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 O = 6e4;
145
+ function Q(e) {
146
+ if (!e) return null;
147
+ let t = Number(e);
148
+ if (Number.isFinite(t) && t >= 0) return Math.min(Math.round(t * 1e3), O);
149
+ let n = Date.parse(e);
150
+ if (Number.isFinite(n)) {
151
+ let o = n - Date.now();
152
+ if (o > 0) return Math.min(o, O);
109
153
  }
110
154
  return null;
111
155
  }
112
- function sleep(ms) {
113
- return new Promise((resolve) => setTimeout(resolve, ms));
156
+ function q(e) {
157
+ return new Promise((t) => setTimeout(t, e));
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 Z(e) {
160
+ return e === 401 ? "unauthorized" : e === 403 ? "forbidden" : e === 404 ? "not_found" : e === 409 ? "conflict" : e === 410 ? "gone" : e === 422 || e === 400 ? "validation_failed" : e === 429 ? "rate_limited" : e >= 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 ee(e, t, n) {
163
+ let o = e.replace(/\/+$/, ""), i = t.startsWith("/") ? t : `/${t}`, u = new URL(`${o}${i}`);
164
+ if (n)
165
+ for (let [r, a] of Object.entries(n))
166
+ a !== void 0 && u.searchParams.set(r, String(a));
167
+ return u.toString();
168
+ }
169
+ async function K(e) {
170
+ let t = await e.text();
171
+ if (t)
172
+ try {
173
+ return JSON.parse(t);
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 v(e, t) {
179
+ let n = t.method ?? "GET", o = ee(e.baseUrl, t.path, t.query), i = J.has(n) ? X : Y, u = t.retries ?? i, { headers: r, correlationId: a } = N(
180
+ { accept: "application/json", ...t.headers },
181
+ t.correlationId
182
+ ), l = L();
183
+ if (l && (r["x-neetru-sdk-version"] = l), t.requireAuth) {
184
+ if (!e.apiKey)
185
+ throw new d("missing_api_key", G());
186
+ r.authorization = `Bearer ${e.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 (t.idempotencyKey) {
189
+ let g = typeof t.idempotencyKey == "string" ? t.idempotencyKey : I();
190
+ r["idempotency-key"] = g;
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 c = t.body !== void 0 && n !== "GET" && n !== "DELETE" ? JSON.stringify(t.body) : void 0;
193
+ c !== void 0 && (r["content-type"] = "application/json");
194
+ let f = null, m = t.deadlineMs != null ? Date.now() + t.deadlineMs : null;
195
+ for (let g = 0; g <= u; g++) {
196
+ if (m != null && Date.now() >= m)
197
+ throw f ?? new d(
198
+ "network_error",
199
+ "Deadline excedido antes de completar a request",
200
+ void 0,
201
+ void 0,
202
+ void 0,
203
+ a
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 b = { method: n, headers: r };
206
+ c !== void 0 && (b.body = c);
207
+ let U = m != null ? Math.max(1, Math.min(3e4, m - Date.now())) : 3e4;
208
+ b.signal = AbortSignal.timeout(U);
209
+ let p;
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
+ p = await e.fetch(o, b);
212
+ } catch (s) {
213
+ let _ = s instanceof DOMException && s.name === "TimeoutError" ? "Network error: timeout after 30s" : `Network error: ${s instanceof Error ? s.message : "fetch failed"}`;
214
+ if (f = new d("network_error", _, void 0, void 0, void 0, a), g < u) {
215
+ let k = C(g);
216
+ if (m == null || Date.now() + k < m) {
217
+ await q(k);
218
+ continue;
219
+ }
190
220
  }
191
- throw lastError;
221
+ throw f;
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 $ = p.headers.get("x-request-id") ?? p.headers.get("x-correlation-id") ?? void 0;
224
+ if (p.ok) {
225
+ let s = p.headers.get("x-neetru-version");
226
+ return s && z(s), await K(p);
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 y = await K(p), w = Z(p.status), h = `HTTP ${p.status}`, E;
229
+ if (y && typeof y == "object") {
230
+ let s = y.error;
231
+ typeof s == "string" ? h = s : s && typeof s == "object" ? (typeof s.code == "string" && (w = s.code), typeof s.message == "string" && (h = s.message), typeof s.reason == "string" && (E = s.reason)) : (typeof y.code == "string" && (w = y.code), typeof y.message == "string" && (h = y.message)), typeof y.reason == "string" && (E = y.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 (p.status === 410) {
234
+ let s = p.headers.get("x-neetru-replacement");
235
+ h === `HTTP ${p.status}` && (h = `Endpoint ${t.path} foi removido do Core (HTTP 410 Gone) \u2014 atualize o @neetru/sdk e migre para a API substituta.`), s && !h.includes(s) && (h += ` Substituto: ${s}.`);
226
236
  }
227
- throw err;
237
+ let T = new d(w, h, p.status, $, E, a);
238
+ if (f = T, W.has(w) && g < u) {
239
+ let _ = Q(p.headers.get("retry-after")) ?? C(g);
240
+ if (m == null || Date.now() + _ < m) {
241
+ await q(_);
242
+ continue;
243
+ }
244
+ }
245
+ throw T;
228
246
  }
229
- throw lastError ?? new NeetruError("unknown", "unexpected httpRequest exit");
247
+ throw f ?? new d("unknown", "unexpected httpRequest exit", void 0, void 0, void 0, a);
230
248
  }
231
249
 
232
250
  // src/telemetry.ts
233
- var VALID_LOG_LEVELS = ["debug", "info", "warn", "error", "fatal"];
234
- function isBrowserContext() {
235
- return typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined";
251
+ var P = ["debug", "info", "warn", "error", "fatal"];
252
+ function te() {
253
+ return typeof globalThis < "u" && typeof globalThis.window < "u";
236
254
  }
237
- function resolveEventTransport() {
238
- return isBrowserContext() ? { path: "/api/sdk/v1/telemetry/event/public", requireAuth: false } : { path: "/api/sdk/v1/telemetry/event", requireAuth: true };
255
+ function M() {
256
+ return te() ? { path: "/api/sdk/v1/telemetry/event/public", requireAuth: false } : { path: "/api/sdk/v1/telemetry/event", requireAuth: true };
239
257
  }
240
- function consoleFor(level) {
241
- switch (level) {
258
+ function re(e) {
259
+ switch (e) {
242
260
  case "debug":
243
261
  return console.debug.bind(console);
244
262
  case "info":
@@ -253,58 +271,41 @@ function consoleFor(level) {
253
271
  return console.log.bind(console);
254
272
  }
255
273
  }
256
- var TRACK_FLUSH_MS = 500;
257
- var TRACK_MAX_QUEUE = 50;
258
- function createTelemetryNamespace(config) {
259
- const queue = [];
260
- let flushTimer = null;
261
- let _inflightDrain = null;
262
- async function drainQueue() {
263
- if (queue.length === 0) return;
264
- const batch = queue.splice(0, queue.length);
265
- const work = Promise.allSettled(
266
- batch.map(async (ev) => {
274
+ var ne = 500, oe = 50;
275
+ function _e(e) {
276
+ let t = [], n = null, o = null;
277
+ async function i() {
278
+ if (t.length === 0) return;
279
+ let r = t.splice(0, t.length), a = Promise.allSettled(
280
+ r.map(async (l) => {
267
281
  try {
268
- const body = { name: ev.name };
269
- const productSlug = ev.productSlug ?? config.productId;
270
- if (productSlug) body.productSlug = productSlug;
271
- if (ev.properties && typeof ev.properties === "object") {
272
- body.properties = ev.properties;
273
- }
274
- if (ev.timestamp) body.timestamp = ev.timestamp;
275
- const transport = resolveEventTransport();
276
- await httpRequest(config, {
282
+ let c = { name: l.name }, f = l.productSlug ?? e.productId;
283
+ f && (c.productSlug = f), l.properties && typeof l.properties == "object" && (c.properties = l.properties), l.timestamp && (c.timestamp = l.timestamp);
284
+ let m = M();
285
+ await v(e, {
277
286
  method: "POST",
278
- path: transport.path,
279
- body,
280
- requireAuth: transport.requireAuth,
287
+ path: m.path,
288
+ body: c,
289
+ requireAuth: m.requireAuth,
281
290
  retries: 1,
282
291
  // caça-bruxas: retry sem Idempotency-Key duplicava o evento se o
283
292
  // servidor já tinha persistido antes da falha transiente. Mesmo
284
293
  // padrão do usage.report (key estável por chamada, reusada no retry).
285
- idempotencyKey: true
294
+ idempotencyKey: !0
286
295
  });
287
- } catch (err) {
288
- if (typeof console !== "undefined") {
289
- console.warn("[neetru-sdk] telemetry.track flush failed for event", ev.name, err);
290
- }
296
+ } catch (c) {
297
+ typeof console < "u" && console.warn("[neetru-sdk] telemetry.track flush failed for event", l.name, c);
291
298
  }
292
299
  })
293
300
  );
294
- _inflightDrain = work.then(() => {
295
- _inflightDrain = null;
296
- });
297
- await work;
298
- flushTimer = null;
299
- if (queue.length > 0) {
300
- scheduleFlush();
301
- }
301
+ o = a.then(() => {
302
+ o = null;
303
+ }), await a, n = null, t.length > 0 && u();
302
304
  }
303
- function scheduleFlush() {
304
- if (flushTimer) return;
305
- flushTimer = setTimeout(() => {
306
- void drainQueue();
307
- }, TRACK_FLUSH_MS);
305
+ function u() {
306
+ n || (n = setTimeout(() => {
307
+ i();
308
+ }, ne));
308
309
  }
309
310
  return {
310
311
  /**
@@ -319,34 +320,24 @@ function createTelemetryNamespace(config) {
319
320
  * });
320
321
  * ```
321
322
  */
322
- async event(input) {
323
- if (!input || typeof input !== "object") {
324
- throw new NeetruError("validation_failed", "event input is required");
325
- }
326
- if (typeof input.name !== "string" || input.name.length === 0) {
327
- throw new NeetruError("validation_failed", "event.name is required");
328
- }
329
- if (input.name.length > 128) {
330
- throw new NeetruError("validation_failed", "event.name max 128 chars");
331
- }
332
- const body = { name: input.name };
333
- const productSlug = input.productSlug ?? config.productId;
334
- if (productSlug) body.productSlug = productSlug;
335
- if (input.properties && typeof input.properties === "object") {
336
- body.properties = input.properties;
337
- }
338
- if (input.timestamp) body.timestamp = input.timestamp;
339
- const transport = resolveEventTransport();
340
- const raw = await httpRequest(config, {
323
+ async event(r) {
324
+ if (!r || typeof r != "object")
325
+ throw new d("validation_failed", "event input is required");
326
+ if (typeof r.name != "string" || r.name.length === 0)
327
+ throw new d("validation_failed", "event.name is required");
328
+ if (r.name.length > 128)
329
+ throw new d("validation_failed", "event.name max 128 chars");
330
+ let a = { name: r.name }, l = r.productSlug ?? e.productId;
331
+ l && (a.productSlug = l), r.properties && typeof r.properties == "object" && (a.properties = r.properties), r.timestamp && (a.timestamp = r.timestamp);
332
+ let c = M(), f = await v(e, {
341
333
  method: "POST",
342
- path: transport.path,
343
- body,
344
- requireAuth: transport.requireAuth
334
+ path: c.path,
335
+ body: a,
336
+ requireAuth: c.requireAuth
345
337
  });
346
- if (!raw || raw.ok !== true || typeof raw.eventId !== "string") {
347
- throw new NeetruError("invalid_response", "Telemetry response missing eventId");
348
- }
349
- return { ok: true, eventId: raw.eventId };
338
+ if (!f || f.ok !== true || typeof f.eventId != "string")
339
+ throw new d("invalid_response", "Telemetry response missing eventId");
340
+ return { ok: true, eventId: f.eventId };
350
341
  },
351
342
  /**
352
343
  * Fire-and-forget: enqueue + flush 500ms debounce. Não retorna `eventId`
@@ -358,32 +349,15 @@ function createTelemetryNamespace(config) {
358
349
  * // segue execução; flush async em background
359
350
  * ```
360
351
  */
361
- track(input) {
362
- if (!input || typeof input !== "object") return;
363
- if (typeof input.name !== "string" || input.name.length === 0) return;
364
- if (input.name.length > 128) return;
365
- queue.push(input);
366
- if (queue.length >= TRACK_MAX_QUEUE) {
367
- if (flushTimer) {
368
- clearTimeout(flushTimer);
369
- flushTimer = null;
370
- }
371
- void drainQueue();
372
- } else {
373
- scheduleFlush();
374
- }
352
+ track(r) {
353
+ !r || typeof r != "object" || typeof r.name != "string" || r.name.length === 0 || r.name.length > 128 || (t.push(r), t.length >= oe ? (n && (clearTimeout(n), n = null), i()) : u());
375
354
  },
376
355
  /**
377
356
  * Força flush imediato da queue de `track()`. Resolva antes de
378
357
  * page unload / SSR boundary pra não perder eventos.
379
358
  */
380
359
  async flush() {
381
- if (flushTimer) {
382
- clearTimeout(flushTimer);
383
- flushTimer = null;
384
- }
385
- if (_inflightDrain) await _inflightDrain;
386
- await drainQueue();
360
+ n && (clearTimeout(n), n = null), o && await o, await i();
387
361
  },
388
362
  /**
389
363
  * Registra um log estruturado per-product (Sprint 6).
@@ -400,60 +374,49 @@ function createTelemetryNamespace(config) {
400
374
  * });
401
375
  * ```
402
376
  */
403
- async log(input) {
404
- if (!input || typeof input !== "object") {
405
- throw new NeetruError("validation_failed", "log input is required");
406
- }
407
- if (!VALID_LOG_LEVELS.includes(input.level)) {
408
- throw new NeetruError("validation_failed", `level must be one of ${VALID_LOG_LEVELS.join(", ")}`);
409
- }
410
- if (typeof input.message !== "string" || input.message.length === 0) {
411
- throw new NeetruError("validation_failed", "message is required");
412
- }
413
- if (input.message.length > 4e3) {
414
- throw new NeetruError("validation_failed", "message max 4000 chars");
415
- }
416
- if (config.env === "dev") {
417
- const fn = consoleFor(input.level);
418
- fn(`[neetru-sdk] ${input.level}: ${input.message}`, input.metadata ?? {});
419
- return { ok: true, mode: "mock" };
420
- }
421
- const body = {
422
- level: input.level,
423
- message: input.message
377
+ async log(r) {
378
+ if (!r || typeof r != "object")
379
+ throw new d("validation_failed", "log input is required");
380
+ if (!P.includes(r.level))
381
+ throw new d("validation_failed", `level must be one of ${P.join(", ")}`);
382
+ if (typeof r.message != "string" || r.message.length === 0)
383
+ throw new d("validation_failed", "message is required");
384
+ if (r.message.length > 4e3)
385
+ throw new d("validation_failed", "message max 4000 chars");
386
+ if (e.env === "dev")
387
+ return re(r.level)(`[neetru-sdk] ${r.level}: ${r.message}`, r.metadata ?? {}), { ok: true, mode: "mock" };
388
+ let a = {
389
+ level: r.level,
390
+ message: r.message
424
391
  };
425
- if (input.metadata) body.metadata = input.metadata;
426
- const productSlug = input.productSlug ?? config.productId;
427
- if (productSlug) body.productSlug = productSlug;
428
- let cid = input.correlationId;
429
- if (!cid) {
392
+ r.metadata && (a.metadata = r.metadata);
393
+ let l = r.productSlug ?? e.productId;
394
+ l && (a.productSlug = l);
395
+ let c = r.correlationId;
396
+ if (!c)
430
397
  try {
431
- const g = globalThis.NEETRU_CORRELATION_ID;
432
- if (typeof g === "string" && g.length > 0) cid = g;
398
+ let g = globalThis.NEETRU_CORRELATION_ID;
399
+ typeof g == "string" && g.length > 0 && (c = g);
433
400
  } catch {
434
401
  }
435
- }
436
- const headers = {};
437
- if (cid) headers["x-correlation-id"] = cid;
438
- const raw = await httpRequest(config, {
402
+ let f = {};
403
+ c && (f["x-correlation-id"] = c);
404
+ let m = await v(e, {
439
405
  method: "POST",
440
406
  path: "/api/sdk/v1/telemetry/log",
441
- body,
407
+ body: a,
442
408
  requireAuth: true,
443
- headers
409
+ headers: f
444
410
  });
445
- if (!raw || raw.ok !== true) {
446
- throw new NeetruError("invalid_response", "Telemetry log response missing ok");
447
- }
411
+ if (!m || m.ok !== true)
412
+ throw new d("invalid_response", "Telemetry log response missing ok");
448
413
  return {
449
414
  ok: true,
450
- logId: typeof raw.logId === "string" ? raw.logId : void 0,
415
+ logId: typeof m.logId == "string" ? m.logId : void 0,
451
416
  mode: "http"
452
417
  };
453
418
  }
454
419
  };
455
420
  }
456
421
 
457
- export { createTelemetryNamespace };
458
- //# sourceMappingURL=telemetry.mjs.map
459
- //# sourceMappingURL=telemetry.mjs.map
422
+ export { _e as createTelemetryNamespace };