@neetru/sdk 3.5.0 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/CHANGELOG.md +71 -1
  2. package/dist/ai.cjs +254 -391
  3. package/dist/ai.d.cts +1 -1
  4. package/dist/ai.d.ts +1 -1
  5. package/dist/ai.mjs +254 -391
  6. package/dist/auth.cjs +3560 -4993
  7. package/dist/auth.d.cts +1 -1
  8. package/dist/auth.d.ts +1 -1
  9. package/dist/auth.mjs +3557 -4990
  10. package/dist/build-guard.cjs +101 -119
  11. package/dist/build-guard.mjs +91 -109
  12. package/dist/catalog.cjs +152 -224
  13. package/dist/catalog.d.cts +1 -1
  14. package/dist/catalog.d.ts +1 -1
  15. package/dist/catalog.mjs +152 -224
  16. package/dist/checkout.cjs +237 -320
  17. package/dist/checkout.d.cts +1 -1
  18. package/dist/checkout.d.ts +1 -1
  19. package/dist/checkout.mjs +236 -319
  20. package/dist/db-react.cjs +59 -87
  21. package/dist/db-react.d.cts +1 -1
  22. package/dist/db-react.d.ts +1 -1
  23. package/dist/db-react.mjs +56 -84
  24. package/dist/db.cjs +2055 -3013
  25. package/dist/db.d.cts +1 -1
  26. package/dist/db.d.ts +1 -1
  27. package/dist/db.mjs +2068 -3026
  28. package/dist/entitlements.cjs +12 -20
  29. package/dist/entitlements.d.cts +1 -1
  30. package/dist/entitlements.d.ts +1 -1
  31. package/dist/entitlements.mjs +12 -20
  32. package/dist/errors.cjs +9 -12
  33. package/dist/errors.d.cts +37 -2
  34. package/dist/errors.d.ts +37 -2
  35. package/dist/errors.mjs +8 -12
  36. package/dist/firestore-compat.cjs +241 -297
  37. package/dist/firestore-compat.d.cts +1 -1
  38. package/dist/firestore-compat.d.ts +1 -1
  39. package/dist/firestore-compat.mjs +215 -271
  40. package/dist/index.cjs +3627 -5135
  41. package/dist/index.d.cts +6 -4
  42. package/dist/index.d.ts +6 -4
  43. package/dist/index.mjs +3731 -5239
  44. package/dist/mobile.cjs +411 -0
  45. package/dist/mobile.d.cts +89 -0
  46. package/dist/mobile.d.ts +89 -0
  47. package/dist/mobile.mjs +409 -0
  48. package/dist/mocks.cjs +312 -447
  49. package/dist/mocks.d.cts +1 -1
  50. package/dist/mocks.d.ts +1 -1
  51. package/dist/mocks.mjs +306 -441
  52. package/dist/notifications.cjs +226 -314
  53. package/dist/notifications.d.cts +1 -1
  54. package/dist/notifications.d.ts +1 -1
  55. package/dist/notifications.mjs +225 -313
  56. package/dist/react.cjs +522 -693
  57. package/dist/react.d.cts +1 -1
  58. package/dist/react.d.ts +1 -1
  59. package/dist/react.mjs +512 -683
  60. package/dist/support.cjs +329 -325
  61. package/dist/support.d.cts +25 -3
  62. package/dist/support.d.ts +25 -3
  63. package/dist/support.mjs +328 -325
  64. package/dist/telemetry.cjs +197 -301
  65. package/dist/telemetry.d.cts +1 -1
  66. package/dist/telemetry.d.ts +1 -1
  67. package/dist/telemetry.mjs +197 -301
  68. package/dist/{types-Du_iioJ7.d.cts → types-Bx4kTLmk.d.cts} +26 -0
  69. package/dist/{types-BPATkXYu.d.ts → types-Dx0IrOSF.d.ts} +26 -0
  70. package/dist/usage.cjs +163 -227
  71. package/dist/usage.d.cts +1 -1
  72. package/dist/usage.d.ts +1 -1
  73. package/dist/usage.mjs +163 -227
  74. package/dist/webhooks.cjs +258 -359
  75. package/dist/webhooks.d.cts +1 -1
  76. package/dist/webhooks.d.ts +1 -1
  77. package/dist/webhooks.mjs +255 -356
  78. package/package.json +9 -3
  79. package/dist/ai.cjs.map +0 -1
  80. package/dist/ai.mjs.map +0 -1
  81. package/dist/auth.cjs.map +0 -1
  82. package/dist/auth.mjs.map +0 -1
  83. package/dist/build-guard.cjs.map +0 -1
  84. package/dist/build-guard.mjs.map +0 -1
  85. package/dist/catalog.cjs.map +0 -1
  86. package/dist/catalog.mjs.map +0 -1
  87. package/dist/checkout.cjs.map +0 -1
  88. package/dist/checkout.mjs.map +0 -1
  89. package/dist/db-react.cjs.map +0 -1
  90. package/dist/db-react.mjs.map +0 -1
  91. package/dist/db.cjs.map +0 -1
  92. package/dist/db.mjs.map +0 -1
  93. package/dist/entitlements.cjs.map +0 -1
  94. package/dist/entitlements.mjs.map +0 -1
  95. package/dist/errors.cjs.map +0 -1
  96. package/dist/errors.mjs.map +0 -1
  97. package/dist/firestore-compat.cjs.map +0 -1
  98. package/dist/firestore-compat.mjs.map +0 -1
  99. package/dist/index.cjs.map +0 -1
  100. package/dist/index.mjs.map +0 -1
  101. package/dist/mocks.cjs.map +0 -1
  102. package/dist/mocks.mjs.map +0 -1
  103. package/dist/notifications.cjs.map +0 -1
  104. package/dist/notifications.mjs.map +0 -1
  105. package/dist/react.cjs.map +0 -1
  106. package/dist/react.mjs.map +0 -1
  107. package/dist/support.cjs.map +0 -1
  108. package/dist/support.mjs.map +0 -1
  109. package/dist/telemetry.cjs.map +0 -1
  110. package/dist/telemetry.mjs.map +0 -1
  111. package/dist/usage.cjs.map +0 -1
  112. package/dist/usage.mjs.map +0 -1
  113. package/dist/webhooks.cjs.map +0 -1
  114. package/dist/webhooks.mjs.map +0 -1
package/dist/support.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  // src/errors.ts
4
- var NeetruError = class _NeetruError extends Error {
4
+ var o = class t extends Error {
5
5
  code;
6
6
  status;
7
7
  requestId;
@@ -14,293 +14,321 @@ 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
+ constructor(e, r, d, c, u) {
18
+ super(r), this.name = "NeetruError", this.code = e, this.status = d, this.requestId = c, this.reason = u, Object.setPrototypeOf(this, t.prototype);
19
+ }
20
+ }, _ = class t extends o {
21
+ constructor(e, r, d, c) {
22
+ super("auth_required", e, d, c, r), this.name = "NeetruAuthRequiredError", Object.setPrototypeOf(this, t.prototype);
25
23
  }
26
24
  };
27
25
 
28
26
  // 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(
27
+ function U() {
28
+ let t = typeof globalThis < "u" && "crypto" in globalThis ? globalThis.crypto : void 0;
29
+ if (t && typeof t.randomUUID == "function")
30
+ return t.randomUUID();
31
+ throw new o(
35
32
  "runtime_unsupported",
36
33
  "crypto.randomUUID not available in this runtime. SDK 3.0 requires Node \u226520 or modern browser/Edge."
37
34
  );
38
35
  }
39
36
 
40
37
  // src/http.ts
41
- var COMPAT_MATRIX = {
38
+ var H = {
42
39
  // SDK major 3.x requer Core ≥ 2026.05.1 (suporte a X-Neetru-Version header,
43
40
  // runTransaction write-after-read, verifyWebhookRequest, webhooks 3.0+)
44
41
  3: "2026.05.1"
45
42
  };
46
- function stripRevision(v) {
47
- return v.split("+")[0] ?? v;
43
+ function S(t) {
44
+ return t.split("+")[0] ?? t;
48
45
  }
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;
46
+ function G(t, e) {
47
+ let r = S(t).split(".").map(Number), d = S(e).split(".").map(Number), c = Math.max(r.length, d.length);
48
+ for (let u = 0; u < c; u++) {
49
+ let l = r[u] ?? 0, n = d[u] ?? 0;
50
+ if (l !== n) return l - n;
57
51
  }
58
52
  return 0;
59
53
  }
60
- function readInjectedSdkVersion() {
54
+ function M() {
61
55
  try {
62
- return "3.5.0";
56
+ return "3.7.0";
63
57
  } catch {
64
- return void 0;
58
+ return;
65
59
  }
66
60
  }
67
- function getSdkMajor() {
68
- const ver = readInjectedSdkVersion();
69
- if (ver) return parseInt(ver.split(".")[0] ?? "3", 10);
70
- return 3;
61
+ function z() {
62
+ let t = M();
63
+ return t ? parseInt(t.split(".")[0] ?? "3", 10) : 3;
71
64
  }
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
- }
65
+ var N = /* @__PURE__ */ new Set();
66
+ function B(t) {
67
+ if (!t) return;
68
+ let e = z(), r = H[e];
69
+ if (!r) return;
70
+ let d = S(t);
71
+ if (G(d, r) < 0) {
72
+ let c = `${e}:${d}`;
73
+ N.has(c) || (N.add(c), console.warn(
74
+ `[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.`
75
+ ));
87
76
  }
88
77
  }
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([
78
+ var X = 2, Y = 0, J = /* @__PURE__ */ new Set(["GET", "HEAD"]), W = /* @__PURE__ */ new Set([
93
79
  "rate_limited",
94
80
  "server_error",
95
81
  "network_error"
96
82
  ]);
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));
83
+ function C(t) {
84
+ let e = 200 * Math.pow(4, t), r = e * 0.2 * (Math.random() * 2 - 1);
85
+ return Math.max(50, Math.round(e + r));
101
86
  }
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);
87
+ var D = 6e4;
88
+ function Q(t) {
89
+ if (!t) return null;
90
+ let e = Number(t);
91
+ if (Number.isFinite(e) && e >= 0) return Math.min(Math.round(e * 1e3), D);
92
+ let r = Date.parse(t);
93
+ if (Number.isFinite(r)) {
94
+ let d = r - Date.now();
95
+ if (d > 0) return Math.min(d, D);
111
96
  }
112
97
  return null;
113
98
  }
114
- function sleep(ms) {
115
- return new Promise((resolve) => setTimeout(resolve, ms));
99
+ function x(t) {
100
+ return new Promise((e) => setTimeout(e, t));
116
101
  }
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";
102
+ function Z(t) {
103
+ 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";
126
104
  }
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));
135
- }
136
- }
137
- return url.toString();
105
+ function ee(t, e, r) {
106
+ let d = t.replace(/\/+$/, ""), c = e.startsWith("/") ? e : `/${e}`, u = new URL(`${d}${c}`);
107
+ if (r)
108
+ for (let [l, n] of Object.entries(r))
109
+ n !== void 0 && u.searchParams.set(l, String(n));
110
+ return u.toString();
138
111
  }
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;
146
- }
112
+ async function q(t) {
113
+ let e = await t.text();
114
+ if (e)
115
+ try {
116
+ return JSON.parse(e);
117
+ } catch {
118
+ return;
119
+ }
147
120
  }
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 = {
121
+ async function b(t, e) {
122
+ let r = e.method ?? "GET", d = ee(t.baseUrl, e.path, e.query), c = J.has(r) ? X : Y, u = e.retries ?? c, l = {
154
123
  accept: "application/json",
155
- ...opts.headers
156
- };
157
- const sdkVersion = readInjectedSdkVersion();
158
- if (sdkVersion) {
159
- headers["x-neetru-sdk-version"] = sdkVersion;
160
- }
161
- if (opts.requireAuth) {
162
- if (!config.apiKey) {
163
- throw new NeetruError(
124
+ ...e.headers
125
+ }, n = M();
126
+ if (n && (l["x-neetru-sdk-version"] = n), e.requireAuth) {
127
+ if (!t.apiKey)
128
+ throw new o(
164
129
  "missing_api_key",
165
130
  "This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var."
166
131
  );
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;
132
+ l.authorization = `Bearer ${t.apiKey}`;
173
133
  }
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";
134
+ if (e.idempotencyKey) {
135
+ let p = typeof e.idempotencyKey == "string" ? e.idempotencyKey : U();
136
+ l["idempotency-key"] = p;
177
137
  }
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;
138
+ let f = e.body !== void 0 && r !== "GET" && r !== "DELETE" ? JSON.stringify(e.body) : void 0;
139
+ f !== void 0 && (l["content-type"] = "application/json");
140
+ let i = null, s = e.deadlineMs != null ? Date.now() + e.deadlineMs : null;
141
+ for (let p = 0; p <= u; p++) {
142
+ if (s != null && Date.now() >= s)
143
+ throw i ?? new o("network_error", "Deadline excedido antes de completar a request");
144
+ let g = { method: r, headers: l };
145
+ f !== void 0 && (g.body = f);
146
+ let F = s != null ? Math.max(1, Math.min(3e4, s - Date.now())) : 3e4;
147
+ g.signal = AbortSignal.timeout(F);
148
+ let m;
184
149
  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;
150
+ m = await t.fetch(d, g);
151
+ } catch (a) {
152
+ let w = a instanceof DOMException && a.name === "TimeoutError" ? "Network error: timeout after 30s" : `Network error: ${a instanceof Error ? a.message : "fetch failed"}`;
153
+ if (i = new o("network_error", w), p < u) {
154
+ let R = C(p);
155
+ if (s == null || Date.now() + R < s) {
156
+ await x(R);
157
+ continue;
158
+ }
192
159
  }
193
- throw lastError;
160
+ throw i;
194
161
  }
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;
162
+ let V = m.headers.get("x-request-id") ?? m.headers.get("x-correlation-id") ?? void 0;
163
+ if (m.ok) {
164
+ let a = m.headers.get("x-neetru-version");
165
+ return a && B(a), await q(m);
201
166
  }
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;
167
+ let y = await q(m), k = Z(m.status), h = `HTTP ${m.status}`, v;
168
+ if (y && typeof y == "object") {
169
+ let a = y.error;
170
+ typeof a == "string" ? h = a : a && typeof a == "object" ? (typeof a.code == "string" && (k = a.code), typeof a.message == "string" && (h = a.message), typeof a.reason == "string" && (v = a.reason)) : (typeof y.code == "string" && (k = y.code), typeof y.message == "string" && (h = y.message)), typeof y.reason == "string" && (v = y.reason);
219
171
  }
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;
172
+ if (m.status === 410) {
173
+ let a = m.headers.get("x-neetru-replacement");
174
+ h === `HTTP ${m.status}` && (h = `Endpoint ${e.path} foi removido do Core (HTTP 410 Gone) \u2014 atualize o @neetru/sdk e migre para a API substituta.`), a && !h.includes(a) && (h += ` Substituto: ${a}.`);
228
175
  }
229
- throw err;
176
+ let I = new o(k, h, m.status, V, v);
177
+ if (i = I, W.has(k) && p < u) {
178
+ let w = Q(m.headers.get("retry-after")) ?? C(p);
179
+ if (s == null || Date.now() + w < s) {
180
+ await x(w);
181
+ continue;
182
+ }
183
+ }
184
+ throw I;
230
185
  }
231
- throw lastError ?? new NeetruError("unknown", "unexpected httpRequest exit");
186
+ throw i ?? new o("unknown", "unexpected httpRequest exit");
232
187
  }
233
188
 
234
189
  // src/validators.ts
235
- var SDK_ID_RE = /^[a-z0-9][a-z0-9_-]{0,62}$/i;
236
- function assertValidSdkId(field, value) {
237
- if (typeof value !== "string" || !SDK_ID_RE.test(value)) {
238
- throw new NeetruError(
190
+ var O = /^[a-z0-9][a-z0-9_-]{0,62}$/i;
191
+ function A(t, e) {
192
+ if (typeof e != "string" || !O.test(e))
193
+ throw new o(
239
194
  "validation_failed",
240
- `${field} must match ${SDK_ID_RE.source} (lowercase alphanumeric, _, -; first char must be alphanumeric; max 63 chars)`
195
+ `${t} must match ${O.source} (lowercase alphanumeric, _, -; first char must be alphanumeric; max 63 chars)`
241
196
  );
242
- }
243
197
  }
244
198
 
245
199
  // src/support.ts
246
- var VALID_SEVERITIES = ["low", "normal", "high", "urgent"];
247
- var VALID_STATUSES = ["open", "pending", "resolved", "closed"];
248
- function toTicket(raw) {
249
- if (!raw || typeof raw !== "object") {
250
- throw new NeetruError("invalid_response", "Ticket response is not an object");
251
- }
252
- const r = raw;
253
- if (typeof r.id !== "string") {
254
- throw new NeetruError("invalid_response", "Ticket missing id");
255
- }
256
- const firstAttachment = Array.isArray(r.attachments) && typeof r.attachments[0] === "string" ? r.attachments[0] : void 0;
200
+ var T = ["low", "normal", "high", "urgent"], te = ["open", "pending", "resolved", "closed"], j = 50;
201
+ function P(t) {
202
+ if (!t || typeof t != "object")
203
+ throw new o("invalid_response", "Ticket response is not an object");
204
+ let e = t;
205
+ if (typeof e.id != "string")
206
+ throw new o("invalid_response", "Ticket missing id");
207
+ let r = Array.isArray(e.attachments) && typeof e.attachments[0] == "string" ? e.attachments[0] : void 0, d = typeof e.screenshotUrl == "string" ? e.screenshotUrl : r ?? null;
257
208
  return {
258
- id: r.id,
259
- subject: typeof r.subject === "string" ? r.subject : "",
260
- message: typeof r.message === "string" ? r.message : "",
261
- severity: VALID_SEVERITIES.includes(r.severity) ? r.severity : "normal",
262
- status: VALID_STATUSES.includes(r.status) ? r.status : "open",
263
- createdAt: typeof r.createdAt === "string" ? r.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
264
- updatedAt: typeof r.updatedAt === "string" ? r.updatedAt : void 0,
265
- productSlug: typeof r.productId === "string" ? r.productId : typeof r.productSlug === "string" ? r.productSlug : void 0,
266
- pageUrl: typeof r.pageUrl === "string" ? r.pageUrl : null,
267
- screenshotUrl: typeof r.screenshotUrl === "string" ? r.screenshotUrl : firstAttachment ?? null,
268
- resolvedAt: typeof r.resolvedAt === "string" ? r.resolvedAt : null,
269
- resolvedNotifiedAt: typeof r.resolvedNotifiedAt === "string" ? r.resolvedNotifiedAt : null,
270
- satisfactionAttempts: typeof r.satisfactionAttempts === "number" && Number.isFinite(r.satisfactionAttempts) ? r.satisfactionAttempts : 0,
271
- lastSatisfactionAttemptAt: typeof r.lastSatisfactionAttemptAt === "string" ? r.lastSatisfactionAttemptAt : null,
272
- satisfiedAt: typeof r.satisfiedAt === "string" ? r.satisfiedAt : null,
273
- rating: typeof r.rating === "number" && Number.isFinite(r.rating) ? r.rating : null,
274
- satisfactionComment: typeof r.satisfactionComment === "string" ? r.satisfactionComment : null
209
+ id: e.id,
210
+ subject: typeof e.subject == "string" ? e.subject : "",
211
+ message: typeof e.message == "string" ? e.message : "",
212
+ severity: T.includes(e.severity) ? e.severity : "normal",
213
+ status: te.includes(e.status) ? e.status : "open",
214
+ createdAt: typeof e.createdAt == "string" ? e.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
215
+ updatedAt: typeof e.updatedAt == "string" ? e.updatedAt : void 0,
216
+ productSlug: typeof e.productId == "string" ? e.productId : typeof e.productSlug == "string" ? e.productSlug : void 0,
217
+ pageUrl: typeof e.pageUrl == "string" ? e.pageUrl : null,
218
+ screenshotUrl: d,
219
+ // 3.7.0: a listagem do Core não traz mais `attachments` (screenshotUrl vem
220
+ // null) — `screenshotAttached` diz se o ticket tem print. Fallback: há URL.
221
+ screenshotAttached: typeof e.screenshotAttached == "boolean" ? e.screenshotAttached : d !== null,
222
+ resolvedAt: typeof e.resolvedAt == "string" ? e.resolvedAt : null,
223
+ resolvedNotifiedAt: typeof e.resolvedNotifiedAt == "string" ? e.resolvedNotifiedAt : null,
224
+ satisfactionAttempts: typeof e.satisfactionAttempts == "number" && Number.isFinite(e.satisfactionAttempts) ? e.satisfactionAttempts : 0,
225
+ lastSatisfactionAttemptAt: typeof e.lastSatisfactionAttemptAt == "string" ? e.lastSatisfactionAttemptAt : null,
226
+ satisfiedAt: typeof e.satisfiedAt == "string" ? e.satisfiedAt : null,
227
+ rating: typeof e.rating == "number" && Number.isFinite(e.rating) ? e.rating : null,
228
+ satisfactionComment: typeof e.satisfactionComment == "string" ? e.satisfactionComment : null
275
229
  };
276
230
  }
277
- function assertTicketId(ticketId) {
278
- if (!ticketId || typeof ticketId !== "string") {
279
- throw new NeetruError("validation_failed", "ticketId is required");
280
- }
231
+ function E(t) {
232
+ if (!t || typeof t != "string")
233
+ throw new o("validation_failed", "ticketId is required");
281
234
  }
282
- function assertValidComment(comment) {
283
- if (typeof comment === "string" && comment.length > 2e3) {
284
- throw new NeetruError("validation_failed", "comment max 2000 chars");
285
- }
235
+ function $(t) {
236
+ if (typeof t == "string" && t.length > 2e3)
237
+ throw new o("validation_failed", "comment max 2000 chars");
286
238
  }
287
- function resolveProductId(config, ...candidates) {
288
- for (const c of candidates) {
289
- if (typeof c === "string" && c.length > 0) {
290
- assertValidSdkId("productSlug", c);
291
- return c;
292
- }
293
- }
294
- if (config.productId) {
295
- assertValidSdkId("productId", config.productId);
296
- return config.productId;
297
- }
298
- throw new NeetruError(
239
+ function K(t, ...e) {
240
+ for (let r of e)
241
+ if (typeof r == "string" && r.length > 0)
242
+ return A("productSlug", r), r;
243
+ if (t.productId)
244
+ return A("productId", t.productId), t.productId;
245
+ throw new o(
299
246
  "validation_failed",
300
247
  "productId required (pass to input.productSlug or set on createNeetruClient)"
301
248
  );
302
249
  }
303
- function createSupportNamespace(config) {
250
+ var ne = "X-Neetru-End-User-Token", re = "Esta opera\xE7\xE3o de suporte exige um usu\xE1rio final logado: o Core s\xF3 mostra/altera os tickets do pr\xF3prio usu\xE1rio (header X-Neetru-End-User-Token com o id_token OIDC). Fa\xE7a login com client.auth.signIn() e tente de novo.", oe = "O Core exige a identidade do usu\xE1rio final para esta opera\xE7\xE3o (403 end_user_token_required) e nenhum id_token foi aceito. Fa\xE7a login com client.auth.signIn() e tente de novo.", ie = "O Core recusou o token do usu\xE1rio final (401 invalid_end_user_token \u2014 sess\xE3o expirada, usu\xE1rio inativo ou token que n\xE3o \xE9 id_token) e a renova\xE7\xE3o autom\xE1tica n\xE3o resolveu. Fa\xE7a login novamente com client.auth.signIn() e tente de novo.", se = "O id_token do usu\xE1rio final foi emitido para o client OIDC de OUTRO produto (403 end_user_token_product_mismatch). Confira se o login (client.auth / clientId OIDC) e a apiKey/productId do createNeetruClient s\xE3o do MESMO produto.";
251
+ function L(t) {
252
+ if (t instanceof o && !(t instanceof _)) {
253
+ if (t.code === "end_user_token_required")
254
+ throw new _(
255
+ oe,
256
+ "end_user_token_required",
257
+ t.status,
258
+ t.requestId
259
+ );
260
+ if (t.code === "invalid_end_user_token")
261
+ throw new _(
262
+ ie,
263
+ "invalid_end_user_token",
264
+ t.status,
265
+ t.requestId
266
+ );
267
+ if (t.code === "end_user_token_product_mismatch")
268
+ throw new o(
269
+ "forbidden",
270
+ se,
271
+ t.status,
272
+ t.requestId,
273
+ "end_user_token_product_mismatch"
274
+ );
275
+ }
276
+ throw t;
277
+ }
278
+ function ae(t) {
279
+ return t instanceof o && t.code === "invalid_end_user_token";
280
+ }
281
+ function ke(t, e = {}) {
282
+ function r() {
283
+ try {
284
+ let n = e.getEndUserToken?.();
285
+ return typeof n == "string" && n.length > 0 ? n : null;
286
+ } catch {
287
+ return null;
288
+ }
289
+ }
290
+ async function d() {
291
+ if (!e.refreshEndUserToken) return false;
292
+ try {
293
+ return await e.refreshEndUserToken() === !0;
294
+ } catch {
295
+ return false;
296
+ }
297
+ }
298
+ function c(n) {
299
+ return n ? { [ne]: n } : {};
300
+ }
301
+ async function u(n, f) {
302
+ let i = r();
303
+ if (!i && n && await d() && (i = r()), !i && n)
304
+ throw new _(re, "no_signed_in_user");
305
+ try {
306
+ return await f(c(i));
307
+ } catch (s) {
308
+ if (i && ae(s) && await d()) {
309
+ let p = r();
310
+ if (p)
311
+ try {
312
+ return await f(c(p));
313
+ } catch (g) {
314
+ L(g);
315
+ }
316
+ }
317
+ L(s);
318
+ }
319
+ }
320
+ async function l(n, f = {}) {
321
+ await u(
322
+ true,
323
+ (i) => b(t, {
324
+ method: "POST",
325
+ path: n,
326
+ requireAuth: !0,
327
+ headers: i,
328
+ ...f
329
+ })
330
+ );
331
+ }
304
332
  return {
305
333
  /**
306
334
  * Cria um ticket de suporte. Requer Bearer auth. `productSlug` no input
@@ -308,85 +336,75 @@ function createSupportNamespace(config) {
308
336
  *
309
337
  * Endpoint canonical: `POST /api/sdk/v1/support/tickets`.
310
338
  */
311
- async createTicket(input) {
312
- if (!input || typeof input !== "object") {
313
- throw new NeetruError("validation_failed", "input is required");
314
- }
315
- if (!input.subject || typeof input.subject !== "string") {
316
- throw new NeetruError("validation_failed", "subject is required");
317
- }
318
- if (input.subject.length > 200) {
319
- throw new NeetruError("validation_failed", "subject max 200 chars");
320
- }
321
- if (!input.message || typeof input.message !== "string") {
322
- throw new NeetruError("validation_failed", "message is required");
323
- }
324
- if (input.message.length > 1e4) {
325
- throw new NeetruError("validation_failed", "message max 10000 chars");
326
- }
327
- if (input.severity && !VALID_SEVERITIES.includes(input.severity)) {
328
- throw new NeetruError(
339
+ async createTicket(n) {
340
+ if (!n || typeof n != "object")
341
+ throw new o("validation_failed", "input is required");
342
+ if (!n.subject || typeof n.subject != "string")
343
+ throw new o("validation_failed", "subject is required");
344
+ if (n.subject.length > 200)
345
+ throw new o("validation_failed", "subject max 200 chars");
346
+ if (!n.message || typeof n.message != "string")
347
+ throw new o("validation_failed", "message is required");
348
+ if (n.message.length > 1e4)
349
+ throw new o("validation_failed", "message max 10000 chars");
350
+ if (n.severity && !T.includes(n.severity))
351
+ throw new o(
329
352
  "validation_failed",
330
- `severity must be one of ${VALID_SEVERITIES.join(", ")}`
353
+ `severity must be one of ${T.join(", ")}`
331
354
  );
332
- }
333
- const productId = resolveProductId(config, input.productSlug);
334
- const body = {
335
- productId,
336
- subject: input.subject,
337
- message: input.message,
338
- severity: input.severity ?? "normal"
355
+ let i = {
356
+ productId: K(t, n.productSlug),
357
+ subject: n.subject,
358
+ message: n.message,
359
+ severity: n.severity ?? "normal"
339
360
  };
340
- if (input.metadata && typeof input.metadata === "object") {
341
- body.metadata = input.metadata;
342
- }
343
- if (typeof input.pageUrl === "string") {
344
- body.pageUrl = input.pageUrl;
345
- }
346
- if (typeof input.screenshotBase64 === "string") {
347
- body.screenshotBase64 = input.screenshotBase64;
348
- }
349
- if (typeof input.consoleLogs === "string") {
350
- body.consoleLogs = input.consoleLogs;
351
- }
352
- const raw = await httpRequest(config, {
353
- method: "POST",
354
- path: "/api/sdk/v1/support/tickets",
355
- body,
356
- requireAuth: true,
357
- idempotencyKey: true
358
- });
359
- const candidate = raw && typeof raw === "object" && "ticket" in raw ? raw.ticket : raw;
360
- return toTicket(candidate);
361
+ n.metadata && typeof n.metadata == "object" && (i.metadata = n.metadata), typeof n.pageUrl == "string" && (i.pageUrl = n.pageUrl), typeof n.screenshotBase64 == "string" && (i.screenshotBase64 = n.screenshotBase64), typeof n.consoleLogs == "string" && (i.consoleLogs = n.consoleLogs);
362
+ let s = await u(
363
+ false,
364
+ (g) => b(t, {
365
+ method: "POST",
366
+ path: "/api/sdk/v1/support/tickets",
367
+ body: i,
368
+ requireAuth: !0,
369
+ idempotencyKey: !0,
370
+ headers: g
371
+ })
372
+ ), p = s && typeof s == "object" && "ticket" in s ? s.ticket : s;
373
+ return P(p);
361
374
  },
362
375
  /**
363
376
  * Lista tickets do customer no produto atual. `productSlug` no contexto.
364
377
  *
365
378
  * Endpoint canonical: `GET /api/sdk/v1/support/tickets?productId=...`.
366
379
  */
367
- async listMyTickets(options) {
368
- const productId = resolveProductId(config, options?.productSlug);
369
- const raw = await httpRequest(config, {
370
- method: "GET",
371
- path: "/api/sdk/v1/support/tickets",
372
- query: { productId },
373
- requireAuth: true
374
- });
375
- const list = Array.isArray(raw) ? raw : raw && typeof raw === "object" && "tickets" in raw ? raw.tickets ?? [] : [];
376
- return list.map(toTicket);
380
+ async listMyTickets(n) {
381
+ let f = K(t, n?.productSlug), i = n?.limit;
382
+ if (i !== void 0 && (!Number.isInteger(i) || i < 1 || i > j))
383
+ throw new o(
384
+ "validation_failed",
385
+ `limit must be an integer 1-${j} (Core default 20)`
386
+ );
387
+ let s = await u(
388
+ true,
389
+ (g) => b(t, {
390
+ method: "GET",
391
+ path: "/api/sdk/v1/support/tickets",
392
+ query: { productId: f, limit: i },
393
+ requireAuth: !0,
394
+ headers: g
395
+ })
396
+ );
397
+ return (Array.isArray(s) ? s : s && typeof s == "object" && "tickets" in s ? s.tickets ?? [] : []).map(P);
377
398
  },
378
399
  /**
379
400
  * 3.4: marca a notificação de resolução como vista (`resolvedNotifiedAt`,
380
401
  * idempotente no Core). Endpoint canonical:
381
402
  * `POST /api/sdk/v1/support/tickets/{id}/resolved-seen`.
382
403
  */
383
- async markResolvedSeen(ticketId) {
384
- assertTicketId(ticketId);
385
- await httpRequest(config, {
386
- method: "POST",
387
- path: `/api/sdk/v1/support/tickets/${encodeURIComponent(ticketId)}/resolved-seen`,
388
- requireAuth: true
389
- });
404
+ async markResolvedSeen(n) {
405
+ E(n), await l(
406
+ `/api/sdk/v1/support/tickets/${encodeURIComponent(n)}/resolved-seen`
407
+ );
390
408
  },
391
409
  /**
392
410
  * 3.4: registra uma tentativa de exibição do modal de satisfação
@@ -394,61 +412,47 @@ function createSupportNamespace(config) {
394
412
  * resposta. Endpoint canonical:
395
413
  * `POST /api/sdk/v1/support/tickets/{id}/satisfaction-attempt`.
396
414
  */
397
- async recordSatisfactionAttempt(ticketId) {
398
- assertTicketId(ticketId);
399
- await httpRequest(config, {
400
- method: "POST",
401
- path: `/api/sdk/v1/support/tickets/${encodeURIComponent(ticketId)}/satisfaction-attempt`,
402
- requireAuth: true,
415
+ async recordSatisfactionAttempt(n) {
416
+ E(n), await l(
417
+ `/api/sdk/v1/support/tickets/${encodeURIComponent(n)}/satisfaction-attempt`,
403
418
  // Incrementa satisfactionAttempts += 1 no Core — sem idempotencyKey,
404
419
  // um retry de rede infla o contador (mesmo padrão de createTicket acima).
405
- idempotencyKey: true
406
- });
420
+ { idempotencyKey: true }
421
+ );
407
422
  },
408
423
  /**
409
424
  * 3.4: envia (ou pula) a avaliação de satisfação (CSAT 1-5). Endpoint
410
425
  * canonical: `POST /api/sdk/v1/support/tickets/{id}/satisfaction`.
411
426
  */
412
- async submitSatisfaction(input) {
413
- if (!input || typeof input !== "object") {
414
- throw new NeetruError("validation_failed", "input is required");
415
- }
416
- assertTicketId(input.ticketId);
417
- if (input.rating !== null && input.rating !== void 0) {
418
- if (!Number.isInteger(input.rating) || input.rating < 1 || input.rating > 5) {
419
- throw new NeetruError("validation_failed", "rating must be an integer 1-5 or null");
427
+ async submitSatisfaction(n) {
428
+ if (!n || typeof n != "object")
429
+ throw new o("validation_failed", "input is required");
430
+ if (E(n.ticketId), n.rating !== null && n.rating !== void 0 && (!Number.isInteger(n.rating) || n.rating < 1 || n.rating > 5))
431
+ throw new o("validation_failed", "rating must be an integer 1-5 or null");
432
+ $(n.comment), await l(
433
+ `/api/sdk/v1/support/tickets/${encodeURIComponent(n.ticketId)}/satisfaction`,
434
+ {
435
+ body: {
436
+ rating: n.rating ?? null,
437
+ comment: n.comment ?? null,
438
+ skipped: n.skipped
439
+ }
420
440
  }
421
- }
422
- assertValidComment(input.comment);
423
- await httpRequest(config, {
424
- method: "POST",
425
- path: `/api/sdk/v1/support/tickets/${encodeURIComponent(input.ticketId)}/satisfaction`,
426
- body: {
427
- rating: input.rating ?? null,
428
- comment: input.comment ?? null,
429
- skipped: input.skipped
430
- },
431
- requireAuth: true
432
- });
441
+ );
433
442
  },
434
443
  /**
435
444
  * 3.4: contesta um ticket resolvido — reabre e zera o ciclo de
436
445
  * satisfação/notificação. Endpoint canonical:
437
446
  * `POST /api/sdk/v1/support/tickets/{id}/contest`.
438
447
  */
439
- async contestTicket(ticketId, opts) {
440
- assertTicketId(ticketId);
441
- assertValidComment(opts?.comment);
442
- await httpRequest(config, {
443
- method: "POST",
444
- path: `/api/sdk/v1/support/tickets/${encodeURIComponent(ticketId)}/contest`,
445
- body: { comment: opts?.comment ?? void 0 },
446
- requireAuth: true
447
- });
448
+ async contestTicket(n, f) {
449
+ E(n), $(f?.comment), await l(
450
+ `/api/sdk/v1/support/tickets/${encodeURIComponent(n)}/contest`,
451
+ { body: { comment: f?.comment ?? void 0 } }
452
+ );
448
453
  }
449
454
  };
450
455
  }
451
456
 
452
- exports.createSupportNamespace = createSupportNamespace;
453
- //# sourceMappingURL=support.cjs.map
454
- //# sourceMappingURL=support.cjs.map
457
+ exports.END_USER_TOKEN_HEADER = ne;
458
+ exports.createSupportNamespace = ke;