@neetru/sdk 3.1.11 → 3.1.13

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 (72) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/ai.cjs.map +1 -1
  3. package/dist/ai.d.cts +1 -1
  4. package/dist/ai.d.ts +1 -1
  5. package/dist/ai.mjs.map +1 -1
  6. package/dist/auth.cjs +154 -65
  7. package/dist/auth.cjs.map +1 -1
  8. package/dist/auth.d.cts +1 -1
  9. package/dist/auth.d.ts +1 -1
  10. package/dist/auth.mjs +154 -65
  11. package/dist/auth.mjs.map +1 -1
  12. package/dist/catalog.cjs.map +1 -1
  13. package/dist/catalog.d.cts +1 -1
  14. package/dist/catalog.d.ts +1 -1
  15. package/dist/catalog.mjs.map +1 -1
  16. package/dist/checkout.cjs.map +1 -1
  17. package/dist/checkout.d.cts +1 -1
  18. package/dist/checkout.d.ts +1 -1
  19. package/dist/checkout.mjs.map +1 -1
  20. package/dist/db-react.d.cts +1 -1
  21. package/dist/db-react.d.ts +1 -1
  22. package/dist/db.cjs.map +1 -1
  23. package/dist/db.d.cts +1 -1
  24. package/dist/db.d.ts +1 -1
  25. package/dist/db.mjs.map +1 -1
  26. package/dist/entitlements.cjs.map +1 -1
  27. package/dist/entitlements.d.cts +1 -1
  28. package/dist/entitlements.d.ts +1 -1
  29. package/dist/entitlements.mjs.map +1 -1
  30. package/dist/errors.cjs.map +1 -1
  31. package/dist/errors.d.cts +12 -0
  32. package/dist/errors.d.ts +12 -0
  33. package/dist/errors.mjs.map +1 -1
  34. package/dist/firestore-compat.d.cts +1 -1
  35. package/dist/firestore-compat.d.ts +1 -1
  36. package/dist/index.cjs +155 -66
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.cts +2 -2
  39. package/dist/index.d.ts +2 -2
  40. package/dist/index.mjs +155 -66
  41. package/dist/index.mjs.map +1 -1
  42. package/dist/mocks.cjs +9 -0
  43. package/dist/mocks.cjs.map +1 -1
  44. package/dist/mocks.d.cts +8 -1
  45. package/dist/mocks.d.ts +8 -1
  46. package/dist/mocks.mjs +9 -0
  47. package/dist/mocks.mjs.map +1 -1
  48. package/dist/notifications.cjs.map +1 -1
  49. package/dist/notifications.d.cts +1 -1
  50. package/dist/notifications.d.ts +1 -1
  51. package/dist/notifications.mjs.map +1 -1
  52. package/dist/react.d.cts +1 -1
  53. package/dist/react.d.ts +1 -1
  54. package/dist/support.cjs.map +1 -1
  55. package/dist/support.d.cts +1 -1
  56. package/dist/support.d.ts +1 -1
  57. package/dist/support.mjs.map +1 -1
  58. package/dist/telemetry.cjs.map +1 -1
  59. package/dist/telemetry.d.cts +1 -1
  60. package/dist/telemetry.d.ts +1 -1
  61. package/dist/telemetry.mjs.map +1 -1
  62. package/dist/{types-dagUxKYz.d.ts → types-BtQv-s0m.d.ts} +40 -3
  63. package/dist/{types-Cog9S-tC.d.cts → types-DJAGWjf0.d.cts} +40 -3
  64. package/dist/usage.cjs.map +1 -1
  65. package/dist/usage.d.cts +1 -1
  66. package/dist/usage.d.ts +1 -1
  67. package/dist/usage.mjs.map +1 -1
  68. package/dist/webhooks.cjs.map +1 -1
  69. package/dist/webhooks.d.cts +1 -1
  70. package/dist/webhooks.d.ts +1 -1
  71. package/dist/webhooks.mjs.map +1 -1
  72. package/package.json +161 -161
package/dist/auth.cjs CHANGED
@@ -5835,6 +5835,15 @@ var MockAuth = class {
5835
5835
  async handleRedirectCallback(_currentUrl) {
5836
5836
  return this._pendingCallback;
5837
5837
  }
5838
+ /**
5839
+ * Mock de `completeSignIn` (3.1.12) — em dev não há redirect real pro IdP,
5840
+ * então não existe callback a completar: retorna `null` sempre (mesmo
5841
+ * contrato "no-op seguro em todo page load" da implementação real). O login
5842
+ * mock acontece direto via `signIn()`.
5843
+ */
5844
+ async completeSignIn(_currentUrl) {
5845
+ return null;
5846
+ }
5838
5847
  /**
5839
5848
  * Mock de `getIdToken` (Bug 2 / 3.1.3). Retorna `null` por default; use
5840
5849
  * `__setIdToken(token)` pra injetar um token cru em testes.
@@ -6263,22 +6272,155 @@ function createOidcAuthNamespace(config) {
6263
6272
  loadCachedUser();
6264
6273
  }, msUntilExpiry + 1);
6265
6274
  }
6275
+ function resolveClientId() {
6276
+ let clientId = config.oidcClientId;
6277
+ if (!clientId && config.apiKey) {
6278
+ clientId = parseApiKey(config.apiKey).keyId;
6279
+ }
6280
+ if (!clientId) {
6281
+ throw new NeetruError(
6282
+ "invalid_config",
6283
+ "auth OIDC requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
6284
+ );
6285
+ }
6286
+ return clientId;
6287
+ }
6288
+ async function handleRedirectCallback(currentUrl) {
6289
+ const href = currentUrl ?? (typeof globalThis.location !== "undefined" ? globalThis.location.href : void 0);
6290
+ if (!href) return null;
6291
+ let parsed;
6292
+ try {
6293
+ parsed = new URL(href);
6294
+ } catch {
6295
+ return null;
6296
+ }
6297
+ const params = parsed.searchParams;
6298
+ const idpError = params.get("error");
6299
+ if (idpError) {
6300
+ const desc = params.get("error_description") ?? idpError;
6301
+ getSessionStorage()?.removeItem(OIDC_TX_KEY);
6302
+ cleanCallbackUrl(parsed);
6303
+ throw new NeetruError(idpError, `OIDC authorize falhou: ${desc}`);
6304
+ }
6305
+ const code = params.get("code");
6306
+ if (!code) return null;
6307
+ const returnedState = params.get("state");
6308
+ const session = getSessionStorage();
6309
+ const txRaw = session?.getItem(OIDC_TX_KEY) ?? null;
6310
+ let tx = null;
6311
+ if (txRaw) {
6312
+ try {
6313
+ tx = JSON.parse(txRaw);
6314
+ } catch {
6315
+ tx = null;
6316
+ }
6317
+ }
6318
+ if (!tx) {
6319
+ throw new NeetruError(
6320
+ "oidc_state_mismatch",
6321
+ "Callback OIDC sem transa\xE7\xE3o pendente \u2014 `signIn` n\xE3o foi iniciado nesta sess\xE3o (ou j\xE1 consumido)."
6322
+ );
6323
+ }
6324
+ if (!returnedState || returnedState !== tx.state) {
6325
+ session?.removeItem(OIDC_TX_KEY);
6326
+ cleanCallbackUrl(parsed);
6327
+ throw new NeetruError(
6328
+ "oidc_state_mismatch",
6329
+ "state do callback OIDC n\xE3o confere com o da transa\xE7\xE3o (poss\xEDvel CSRF)."
6330
+ );
6331
+ }
6332
+ session?.removeItem(OIDC_TX_KEY);
6333
+ cleanCallbackUrl(parsed);
6334
+ return {
6335
+ code,
6336
+ codeVerifier: tx.codeVerifier,
6337
+ redirectUri: tx.redirectUri,
6338
+ nonce: tx.nonce,
6339
+ state: tx.state,
6340
+ postLoginRedirect: tx.postLoginRedirect
6341
+ };
6342
+ }
6343
+ async function completeSignIn(currentUrl) {
6344
+ const tx = await handleRedirectCallback(currentUrl);
6345
+ if (!tx) return null;
6346
+ const clientId = resolveClientId();
6347
+ const idpOrigin = resolveIdpOrigin(config.baseUrl);
6348
+ const tokenUrl = `${idpOrigin}/api/v1/oauth/token`;
6349
+ const form = new URLSearchParams({
6350
+ grant_type: "authorization_code",
6351
+ code: tx.code,
6352
+ redirect_uri: tx.redirectUri,
6353
+ client_id: clientId,
6354
+ code_verifier: tx.codeVerifier
6355
+ });
6356
+ let res;
6357
+ try {
6358
+ res = await config.fetch(tokenUrl, {
6359
+ method: "POST",
6360
+ headers: { "content-type": "application/x-www-form-urlencoded" },
6361
+ body: form.toString()
6362
+ });
6363
+ } catch (err) {
6364
+ throw new NeetruError(
6365
+ "network_error",
6366
+ `POST ${tokenUrl} falhou (network): ${err?.message ?? String(err)}`
6367
+ );
6368
+ }
6369
+ let payload = null;
6370
+ try {
6371
+ payload = await res.json();
6372
+ } catch {
6373
+ payload = null;
6374
+ }
6375
+ if (!res.ok || typeof payload?.error === "string") {
6376
+ const desc = typeof payload?.error_description === "string" && payload.error_description || typeof payload?.error === "string" && payload.error || `HTTP ${res.status}`;
6377
+ throw new NeetruError(
6378
+ "token_exchange_failed",
6379
+ `Troca do authorization_code por tokens falhou no /token: ${desc}`,
6380
+ res.status
6381
+ );
6382
+ }
6383
+ const idToken = payload?.id_token;
6384
+ if (typeof idToken !== "string" || idToken.length === 0) {
6385
+ throw new NeetruError(
6386
+ "token_exchange_failed",
6387
+ "Resposta do /token sem `id_token` \u2014 o login n\xE3o pode ser completado.",
6388
+ res.status
6389
+ );
6390
+ }
6391
+ const claims = decodeJwtPayload(idToken);
6392
+ if (!claims) {
6393
+ throw new NeetruError(
6394
+ "token_exchange_failed",
6395
+ "id_token retornado pelo /token \xE9 malformado (payload indecodific\xE1vel)."
6396
+ );
6397
+ }
6398
+ if (claims.nonce !== tx.nonce) {
6399
+ throw new NeetruError(
6400
+ "oidc_nonce_mismatch",
6401
+ "nonce do id_token n\xE3o confere com o da transa\xE7\xE3o OIDC (poss\xEDvel replay). Token descartado."
6402
+ );
6403
+ }
6404
+ const user = tokenToUser(idToken);
6405
+ if (!user) {
6406
+ throw new NeetruError(
6407
+ "token_exchange_failed",
6408
+ "id_token retornado pelo /token n\xE3o tem `sub` ou j\xE1 est\xE1 expirado."
6409
+ );
6410
+ }
6411
+ getStorage()?.setItem(STORAGE_KEY, idToken);
6412
+ cachedUser = user;
6413
+ scheduleExpiryTimer(user);
6414
+ notify();
6415
+ return { user, postLoginRedirect: tx.postLoginRedirect };
6416
+ }
6266
6417
  return {
6267
6418
  async signIn(options) {
6268
6419
  if (typeof globalThis.location !== "undefined" && typeof globalThis.location.assign === "function") {
6269
6420
  const crypto2 = getWebCrypto();
6270
6421
  const redirectUri = options?.redirectUri ?? globalThis.location.origin;
6271
6422
  const scope = options?.scope ?? "openid profile email";
6272
- let clientId = config.oidcClientId;
6273
- if (!clientId && config.apiKey) {
6274
- clientId = parseApiKey(config.apiKey).keyId;
6275
- }
6276
- if (!clientId) {
6277
- throw new NeetruError(
6278
- "invalid_config",
6279
- "auth.signIn requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
6280
- );
6281
- }
6423
+ const clientId = resolveClientId();
6282
6424
  const state = randomUrlSafe(crypto2, 16);
6283
6425
  const nonce = randomUrlSafe(crypto2, 16);
6284
6426
  const codeVerifier = randomUrlSafe(crypto2, 32);
@@ -6316,61 +6458,8 @@ function createOidcAuthNamespace(config) {
6316
6458
  "auth.signIn requires a browser context or mocks. Use NEETRU_ENV=dev or pass mocks.auth."
6317
6459
  );
6318
6460
  },
6319
- async handleRedirectCallback(currentUrl) {
6320
- const href = currentUrl ?? (typeof globalThis.location !== "undefined" ? globalThis.location.href : void 0);
6321
- if (!href) return null;
6322
- let parsed;
6323
- try {
6324
- parsed = new URL(href);
6325
- } catch {
6326
- return null;
6327
- }
6328
- const params = parsed.searchParams;
6329
- const idpError = params.get("error");
6330
- if (idpError) {
6331
- const desc = params.get("error_description") ?? idpError;
6332
- getSessionStorage()?.removeItem(OIDC_TX_KEY);
6333
- cleanCallbackUrl(parsed);
6334
- throw new NeetruError(idpError, `OIDC authorize falhou: ${desc}`);
6335
- }
6336
- const code = params.get("code");
6337
- if (!code) return null;
6338
- const returnedState = params.get("state");
6339
- const session = getSessionStorage();
6340
- const txRaw = session?.getItem(OIDC_TX_KEY) ?? null;
6341
- let tx = null;
6342
- if (txRaw) {
6343
- try {
6344
- tx = JSON.parse(txRaw);
6345
- } catch {
6346
- tx = null;
6347
- }
6348
- }
6349
- if (!tx) {
6350
- throw new NeetruError(
6351
- "oidc_state_mismatch",
6352
- "Callback OIDC sem transa\xE7\xE3o pendente \u2014 `signIn` n\xE3o foi iniciado nesta sess\xE3o (ou j\xE1 consumido)."
6353
- );
6354
- }
6355
- if (!returnedState || returnedState !== tx.state) {
6356
- session?.removeItem(OIDC_TX_KEY);
6357
- cleanCallbackUrl(parsed);
6358
- throw new NeetruError(
6359
- "oidc_state_mismatch",
6360
- "state do callback OIDC n\xE3o confere com o da transa\xE7\xE3o (poss\xEDvel CSRF)."
6361
- );
6362
- }
6363
- session?.removeItem(OIDC_TX_KEY);
6364
- cleanCallbackUrl(parsed);
6365
- return {
6366
- code,
6367
- codeVerifier: tx.codeVerifier,
6368
- redirectUri: tx.redirectUri,
6369
- nonce: tx.nonce,
6370
- state: tx.state,
6371
- postLoginRedirect: tx.postLoginRedirect
6372
- };
6373
- },
6461
+ handleRedirectCallback,
6462
+ completeSignIn,
6374
6463
  getIdToken() {
6375
6464
  const storage = getStorage();
6376
6465
  const token = storage?.getItem(STORAGE_KEY) ?? null;