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