@neetru/sdk 3.1.1 → 3.1.4

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 (82) hide show
  1. package/README.md +56 -5
  2. package/dist/auth.cjs +255 -18
  3. package/dist/auth.cjs.map +1 -1
  4. package/dist/auth.d.cts +1 -1
  5. package/dist/auth.d.ts +1 -1
  6. package/dist/auth.mjs +255 -18
  7. package/dist/auth.mjs.map +1 -1
  8. package/dist/catalog.cjs.map +1 -1
  9. package/dist/catalog.d.cts +1 -1
  10. package/dist/catalog.d.ts +1 -1
  11. package/dist/catalog.mjs.map +1 -1
  12. package/dist/checkout.cjs +22 -7
  13. package/dist/checkout.cjs.map +1 -1
  14. package/dist/checkout.d.cts +1 -1
  15. package/dist/checkout.d.ts +1 -1
  16. package/dist/checkout.mjs +22 -7
  17. package/dist/checkout.mjs.map +1 -1
  18. package/dist/db-react.d.cts +1 -1
  19. package/dist/db-react.d.ts +1 -1
  20. package/dist/db.cjs +59 -3
  21. package/dist/db.cjs.map +1 -1
  22. package/dist/db.d.cts +1 -1
  23. package/dist/db.d.ts +1 -1
  24. package/dist/db.mjs +59 -3
  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 +11 -6
  32. package/dist/errors.d.ts +11 -6
  33. package/dist/errors.mjs.map +1 -1
  34. package/dist/firestore-compat.cjs +15 -2
  35. package/dist/firestore-compat.cjs.map +1 -1
  36. package/dist/firestore-compat.d.cts +1 -1
  37. package/dist/firestore-compat.d.ts +1 -1
  38. package/dist/firestore-compat.mjs +15 -2
  39. package/dist/firestore-compat.mjs.map +1 -1
  40. package/dist/index.cjs +267 -22
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.cts +2 -2
  43. package/dist/index.d.ts +2 -2
  44. package/dist/index.mjs +267 -22
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/mocks.cjs +25 -0
  47. package/dist/mocks.cjs.map +1 -1
  48. package/dist/mocks.d.cts +18 -1
  49. package/dist/mocks.d.ts +18 -1
  50. package/dist/mocks.mjs +25 -0
  51. package/dist/mocks.mjs.map +1 -1
  52. package/dist/notifications.cjs.map +1 -1
  53. package/dist/notifications.d.cts +1 -1
  54. package/dist/notifications.d.ts +1 -1
  55. package/dist/notifications.mjs.map +1 -1
  56. package/dist/react.cjs.map +1 -1
  57. package/dist/react.d.cts +1 -1
  58. package/dist/react.d.ts +1 -1
  59. package/dist/react.mjs.map +1 -1
  60. package/dist/support.cjs.map +1 -1
  61. package/dist/support.d.cts +1 -1
  62. package/dist/support.d.ts +1 -1
  63. package/dist/support.mjs.map +1 -1
  64. package/dist/telemetry.cjs +2 -1
  65. package/dist/telemetry.cjs.map +1 -1
  66. package/dist/telemetry.d.cts +1 -1
  67. package/dist/telemetry.d.ts +1 -1
  68. package/dist/telemetry.mjs +2 -1
  69. package/dist/telemetry.mjs.map +1 -1
  70. package/dist/{types-B3XFHD4A.d.ts → types-CRIIjqzC.d.ts} +105 -12
  71. package/dist/{types-DePdSU3P.d.cts → types-DvMdYbfV.d.cts} +105 -12
  72. package/dist/usage.cjs.map +1 -1
  73. package/dist/usage.d.cts +1 -1
  74. package/dist/usage.d.ts +1 -1
  75. package/dist/usage.mjs.map +1 -1
  76. package/dist/webhooks.cjs +11 -3
  77. package/dist/webhooks.cjs.map +1 -1
  78. package/dist/webhooks.d.cts +1 -1
  79. package/dist/webhooks.d.ts +1 -1
  80. package/dist/webhooks.mjs +11 -3
  81. package/dist/webhooks.mjs.map +1 -1
  82. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -1095,7 +1095,8 @@ function createTelemetryNamespace(config) {
1095
1095
  message: input.message
1096
1096
  };
1097
1097
  if (input.metadata) body.metadata = input.metadata;
1098
- if (input.productSlug) body.productSlug = input.productSlug;
1098
+ const productSlug = input.productSlug ?? config.productId;
1099
+ if (productSlug) body.productSlug = productSlug;
1099
1100
  let cid = input.correlationId;
1100
1101
  if (!cid) {
1101
1102
  try {
@@ -4614,13 +4615,69 @@ function createRestSyncTransport(config) {
4614
4615
  if (!config) {
4615
4616
  return { docs: [], newWatermark: Date.now(), resyncRequired: false };
4616
4617
  }
4617
- return { docs: [], newWatermark: Date.now(), resyncRequired: false };
4618
+ return { docs: [], newWatermark: Date.now(), resyncRequired: true };
4618
4619
  },
4619
- async fullResync(_collections) {
4620
+ async fullResync(collections) {
4620
4621
  if (!config) {
4621
4622
  return { docs: [], newWatermark: Date.now() };
4622
4623
  }
4623
- return { docs: [], newWatermark: Date.now() };
4624
+ const { httpRequest: httpRequest2 } = await Promise.resolve().then(() => (init_http(), http_exports));
4625
+ const tenantScopeId = config.tenantId ?? config.productId;
4626
+ const tenantHeaders = tenantScopeId ? { "x-neetru-tenant": tenantScopeId } : void 0;
4627
+ const now = Date.now();
4628
+ const docs = [];
4629
+ for (const collection of collections) {
4630
+ let raw;
4631
+ try {
4632
+ raw = await httpRequest2(config, {
4633
+ method: "GET",
4634
+ path: DATASTORE_COLLECTION_ENDPOINT(collection),
4635
+ requireAuth: true,
4636
+ retries: 2,
4637
+ headers: tenantHeaders,
4638
+ // Teto do Core é 200. Coleções > 200 docs truncam silenciosamente
4639
+ // aqui (paginação cursor é tarefa Core separada) — a detecção de
4640
+ // deleção-por-ausência do SyncEngine NÃO deve rodar sobre truncamento,
4641
+ // então mantemos o limite no máximo do servidor por ora.
4642
+ query: { limit: 200 }
4643
+ });
4644
+ } catch (err) {
4645
+ const msg = err instanceof Error ? err.message : String(err);
4646
+ throw new exports.NeetruDbError(
4647
+ "db_unavailable",
4648
+ `[RestSyncTransport] fullResync falhou na cole\xE7\xE3o "${collection}": ${msg}`
4649
+ );
4650
+ }
4651
+ const resp = raw;
4652
+ const items = Array.isArray(resp?.items) ? resp.items : [];
4653
+ for (const item of items) {
4654
+ if (!item || typeof item !== "object") continue;
4655
+ const record = item;
4656
+ const id = typeof record["id"] === "string" ? record["id"] : null;
4657
+ if (!id) continue;
4658
+ const { id: _inlinedId, ...data } = record;
4659
+ let serverTimestamp2 = now;
4660
+ const updatedAt = data["_updatedAt"];
4661
+ if (typeof updatedAt === "number") {
4662
+ serverTimestamp2 = updatedAt;
4663
+ } else if (updatedAt !== null && typeof updatedAt === "object" && typeof updatedAt["_seconds"] === "number") {
4664
+ serverTimestamp2 = updatedAt["_seconds"] * 1e3;
4665
+ } else if (typeof updatedAt === "string") {
4666
+ const parsed = Date.parse(updatedAt);
4667
+ if (!Number.isNaN(parsed)) serverTimestamp2 = parsed;
4668
+ }
4669
+ const serverVersion = `rest_${id}_${serverTimestamp2}`;
4670
+ docs.push({
4671
+ collection,
4672
+ id,
4673
+ data,
4674
+ serverVersion,
4675
+ serverTimestamp: serverTimestamp2,
4676
+ deleted: false
4677
+ });
4678
+ }
4679
+ }
4680
+ return { docs, newWatermark: now };
4624
4681
  }
4625
4682
  };
4626
4683
  }
@@ -4860,6 +4917,15 @@ function createLazyCollectionRef(name, getDocsPromise) {
4860
4917
  // src/checkout.ts
4861
4918
  init_errors();
4862
4919
  init_http();
4920
+ function checkoutAuth(accessToken, method) {
4921
+ if (!accessToken || typeof accessToken !== "string") {
4922
+ throw new exports.NeetruError(
4923
+ "validation_failed",
4924
+ `checkout.${method} requer o access_token OIDC do usu\xE1rio final (passe \`accessToken\`). A chave de API do SDK (nrt_*) N\xC3O \xE9 aceita pelo endpoint de checkout \u2014 ele autentica a identidade do cliente que est\xE1 assinando (Bearer access_token OIDC ou cookie de sess\xE3o).`
4925
+ );
4926
+ }
4927
+ return { requireAuth: false, headers: { authorization: `Bearer ${accessToken}` } };
4928
+ }
4863
4929
  function parseStartResponse(raw) {
4864
4930
  if (!raw || typeof raw !== "object") {
4865
4931
  throw new exports.NeetruError("invalid_response", "checkout.start response is not an object");
@@ -4937,11 +5003,13 @@ function createHttpCheckoutNamespace(config) {
4937
5003
  };
4938
5004
  if (input.tenantType) body.targetTenantType = input.tenantType;
4939
5005
  if (input.tenantId) body.targetTenantId = input.tenantId;
5006
+ const { requireAuth, headers } = checkoutAuth(input.accessToken, "start");
4940
5007
  const raw = await httpRequest(config, {
4941
5008
  method: "POST",
4942
5009
  path: "/api/v1/checkout/intents",
4943
5010
  body,
4944
- requireAuth: true,
5011
+ requireAuth,
5012
+ headers,
4945
5013
  idempotencyKey: true
4946
5014
  });
4947
5015
  const result = parseStartResponse(raw);
@@ -4951,25 +5019,29 @@ function createHttpCheckoutNamespace(config) {
4951
5019
  }
4952
5020
  return result;
4953
5021
  },
4954
- async get(intentId) {
5022
+ async get(intentId, opts) {
4955
5023
  if (!intentId || typeof intentId !== "string") {
4956
5024
  throw new exports.NeetruError("validation_failed", "checkout.get: intentId is required");
4957
5025
  }
5026
+ const { requireAuth, headers } = checkoutAuth(opts?.accessToken, "get");
4958
5027
  const raw = await httpRequest(config, {
4959
5028
  method: "GET",
4960
5029
  path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,
4961
- requireAuth: true
5030
+ requireAuth,
5031
+ headers
4962
5032
  });
4963
5033
  return parseGetResponse(raw);
4964
5034
  },
4965
- async cancel(intentId) {
5035
+ async cancel(intentId, opts) {
4966
5036
  if (!intentId || typeof intentId !== "string") {
4967
5037
  throw new exports.NeetruError("validation_failed", "checkout.cancel: intentId is required");
4968
5038
  }
5039
+ const { requireAuth, headers } = checkoutAuth(opts?.accessToken, "cancel");
4969
5040
  const raw = await httpRequest(config, {
4970
5041
  method: "DELETE",
4971
5042
  path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,
4972
- requireAuth: true
5043
+ requireAuth,
5044
+ headers
4973
5045
  });
4974
5046
  return {
4975
5047
  ok: true,
@@ -5013,14 +5085,14 @@ var MockCheckout = class {
5013
5085
  requiresKyc: false
5014
5086
  };
5015
5087
  }
5016
- async get(intentId) {
5088
+ async get(intentId, _opts) {
5017
5089
  const found = this.intents.get(intentId);
5018
5090
  if (!found) {
5019
5091
  throw new exports.NeetruError("not_found", `Mock intent ${intentId} not found`);
5020
5092
  }
5021
5093
  return { ...found };
5022
5094
  }
5023
- async cancel(intentId) {
5095
+ async cancel(intentId, _opts) {
5024
5096
  const found = this.intents.get(intentId);
5025
5097
  if (!found) {
5026
5098
  throw new exports.NeetruError("not_found", `Mock intent ${intentId} not found`);
@@ -5038,7 +5110,7 @@ function createCheckoutNamespace(config) {
5038
5110
  // src/webhooks.ts
5039
5111
  init_errors();
5040
5112
  init_http();
5041
- async function verifyWebhookSignature(payload, signature, secret) {
5113
+ async function verifyWebhookSignature(payload, signature, secret, timestamp) {
5042
5114
  if (!signature || !secret) return false;
5043
5115
  const sigHex = signature.startsWith("sha256=") ? signature.slice(7) : signature;
5044
5116
  if (!/^[0-9a-f]+$/i.test(sigHex)) return false;
@@ -5051,7 +5123,15 @@ async function verifyWebhookSignature(payload, signature, secret) {
5051
5123
  }
5052
5124
  const encoder = new TextEncoder();
5053
5125
  const keyBytes = encoder.encode(secret);
5054
- const payloadBytes = typeof payload === "string" ? encoder.encode(payload) : payload;
5126
+ const rawBytes = typeof payload === "string" ? encoder.encode(payload) : payload;
5127
+ let payloadBytes = rawBytes;
5128
+ if (timestamp !== void 0) {
5129
+ const prefix = encoder.encode(`${timestamp}.`);
5130
+ const merged = new Uint8Array(prefix.length + rawBytes.length);
5131
+ merged.set(prefix, 0);
5132
+ merged.set(rawBytes, prefix.length);
5133
+ payloadBytes = merged;
5134
+ }
5055
5135
  const key = await subtle.importKey(
5056
5136
  "raw",
5057
5137
  keyBytes,
@@ -5099,7 +5179,7 @@ async function verifyWebhookRequest(payload, headers, secret, options = {}) {
5099
5179
  return { ok: false, reason: "timestamp_expired" };
5100
5180
  }
5101
5181
  const sig = getHeader("x-neetru-signature");
5102
- const valid = await verifyWebhookSignature(payload, sig, secret);
5182
+ const valid = await verifyWebhookSignature(payload, sig, secret, tsHeader);
5103
5183
  if (!valid) {
5104
5184
  return { ok: false, reason: "invalid_signature" };
5105
5185
  }
@@ -5554,6 +5634,31 @@ var MockAuth = class {
5554
5634
  if (this._user) return this._user;
5555
5635
  throw Object.assign(new Error("Nenhum user mock dispon\xEDvel"), { code: "token_invalid_signature" });
5556
5636
  }
5637
+ /**
5638
+ * Mock de `handleRedirectCallback` (Bug 2 / 3.1.3) — não há redirect real no
5639
+ * mock, então retorna `null` por default. Use `__setPendingCallback(result)`
5640
+ * em testes pra simular um retorno do IdP.
5641
+ */
5642
+ async handleRedirectCallback(_currentUrl) {
5643
+ return this._pendingCallback;
5644
+ }
5645
+ /**
5646
+ * Mock de `getIdToken` (Bug 2 / 3.1.3). Retorna `null` por default; use
5647
+ * `__setIdToken(token)` pra injetar um token cru em testes.
5648
+ */
5649
+ getIdToken() {
5650
+ return this._idToken;
5651
+ }
5652
+ _pendingCallback = null;
5653
+ _idToken = null;
5654
+ /** Test helper — simula o material devolvido por um callback OIDC. */
5655
+ __setPendingCallback(result) {
5656
+ this._pendingCallback = result;
5657
+ }
5658
+ /** Test helper — injeta o id_token cru retornado por `getIdToken`. */
5659
+ __setIdToken(token) {
5660
+ this._idToken = token;
5661
+ }
5557
5662
  _verifyTokenOverride = null;
5558
5663
  /**
5559
5664
  * Injeta override pra `verifyToken` em testes — permite simular expiração,
@@ -6083,6 +6188,49 @@ function _jwtPayloadToUser(payload) {
6083
6188
  ...payload
6084
6189
  };
6085
6190
  }
6191
+ var OIDC_TX_KEY = "neetru_oauth_tx";
6192
+ function resolveIdpOrigin(baseUrl) {
6193
+ const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
6194
+ return overrideAuthUrl ?? baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
6195
+ }
6196
+ function getWebCrypto() {
6197
+ const c = globalThis.crypto;
6198
+ if (!c || typeof c.getRandomValues !== "function" || !c.subtle) {
6199
+ throw new exports.NeetruError(
6200
+ "runtime_unsupported",
6201
+ "auth.signIn requer WebCrypto (crypto.subtle) \u2014 indispon\xEDvel neste runtime. Use HTTPS (ou http://localhost) num browser moderno."
6202
+ );
6203
+ }
6204
+ return c;
6205
+ }
6206
+ function base64UrlFromBytes(bytes) {
6207
+ let str = "";
6208
+ for (const b of bytes) str += String.fromCharCode(b);
6209
+ const b64 = typeof btoa === "function" ? btoa(str) : Buffer.from(str, "binary").toString("base64");
6210
+ return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
6211
+ }
6212
+ function randomUrlSafe(crypto2, byteLen) {
6213
+ const bytes = new Uint8Array(byteLen);
6214
+ crypto2.getRandomValues(bytes);
6215
+ return base64UrlFromBytes(bytes);
6216
+ }
6217
+ async function pkceChallengeS256(crypto2, verifier) {
6218
+ const data = new TextEncoder().encode(verifier);
6219
+ const digest = await crypto2.subtle.digest("SHA-256", data);
6220
+ return base64UrlFromBytes(new Uint8Array(digest));
6221
+ }
6222
+ function cleanCallbackUrl(parsed) {
6223
+ try {
6224
+ const history = globalThis.history;
6225
+ if (!history || typeof history.replaceState !== "function") return;
6226
+ const clean = new URL(parsed.toString());
6227
+ for (const p of ["code", "state", "error", "error_description", "iss", "session_state"]) {
6228
+ clean.searchParams.delete(p);
6229
+ }
6230
+ history.replaceState(history.state ?? null, "", clean.pathname + clean.search + clean.hash);
6231
+ } catch {
6232
+ }
6233
+ }
6086
6234
  function createOidcAuthNamespace(config) {
6087
6235
  const STORAGE_KEY = "neetru_id_token";
6088
6236
  const listeners = /* @__PURE__ */ new Set();
@@ -6095,6 +6243,13 @@ function createOidcAuthNamespace(config) {
6095
6243
  return null;
6096
6244
  }
6097
6245
  }
6246
+ function getSessionStorage() {
6247
+ try {
6248
+ return typeof globalThis.sessionStorage !== "undefined" ? globalThis.sessionStorage : null;
6249
+ } catch {
6250
+ return null;
6251
+ }
6252
+ }
6098
6253
  function decodeJwtPayload(token) {
6099
6254
  const parts = token.split(".");
6100
6255
  if (parts.length !== 3) return null;
@@ -6178,20 +6333,48 @@ function createOidcAuthNamespace(config) {
6178
6333
  return {
6179
6334
  async signIn(options) {
6180
6335
  if (typeof globalThis.location !== "undefined" && typeof globalThis.location.assign === "function") {
6336
+ const crypto2 = getWebCrypto();
6181
6337
  const redirectUri = options?.redirectUri ?? globalThis.location.origin;
6182
6338
  const scope = options?.scope ?? "openid profile email";
6183
- const state = options?.postLoginRedirect ?? globalThis.location.href;
6184
- const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
6185
- const idpOrigin = overrideAuthUrl ?? config.baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
6339
+ let clientId = config.oidcClientId;
6340
+ if (!clientId && config.apiKey) {
6341
+ clientId = parseApiKey(config.apiKey).keyId;
6342
+ }
6343
+ if (!clientId) {
6344
+ throw new exports.NeetruError(
6345
+ "invalid_config",
6346
+ "auth.signIn requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
6347
+ );
6348
+ }
6349
+ const state = randomUrlSafe(crypto2, 16);
6350
+ const nonce = randomUrlSafe(crypto2, 16);
6351
+ const codeVerifier = randomUrlSafe(crypto2, 32);
6352
+ const codeChallenge = await pkceChallengeS256(crypto2, codeVerifier);
6353
+ const session = getSessionStorage();
6354
+ if (!session) {
6355
+ throw new exports.NeetruError(
6356
+ "runtime_unsupported",
6357
+ "auth.signIn requer sessionStorage para guardar a transa\xE7\xE3o PKCE entre o redirect e o callback."
6358
+ );
6359
+ }
6360
+ const tx = {
6361
+ state,
6362
+ nonce,
6363
+ codeVerifier,
6364
+ redirectUri,
6365
+ postLoginRedirect: options?.postLoginRedirect
6366
+ };
6367
+ session.setItem(OIDC_TX_KEY, JSON.stringify(tx));
6368
+ const idpOrigin = resolveIdpOrigin(config.baseUrl);
6186
6369
  const url = new URL("/api/v1/oauth/authorize", idpOrigin);
6187
6370
  url.searchParams.set("response_type", "code");
6371
+ url.searchParams.set("client_id", clientId);
6188
6372
  url.searchParams.set("redirect_uri", redirectUri);
6189
6373
  url.searchParams.set("scope", scope);
6190
6374
  url.searchParams.set("state", state);
6191
- if (config.apiKey) {
6192
- const { keyId } = parseApiKey(config.apiKey);
6193
- url.searchParams.set("client_id", keyId);
6194
- }
6375
+ url.searchParams.set("nonce", nonce);
6376
+ url.searchParams.set("code_challenge", codeChallenge);
6377
+ url.searchParams.set("code_challenge_method", "S256");
6195
6378
  globalThis.location.assign(url.toString());
6196
6379
  return;
6197
6380
  }
@@ -6200,6 +6383,67 @@ function createOidcAuthNamespace(config) {
6200
6383
  "auth.signIn requires a browser context or mocks. Use NEETRU_ENV=dev or pass mocks.auth."
6201
6384
  );
6202
6385
  },
6386
+ async handleRedirectCallback(currentUrl) {
6387
+ const href = currentUrl ?? (typeof globalThis.location !== "undefined" ? globalThis.location.href : void 0);
6388
+ if (!href) return null;
6389
+ let parsed;
6390
+ try {
6391
+ parsed = new URL(href);
6392
+ } catch {
6393
+ return null;
6394
+ }
6395
+ const params = parsed.searchParams;
6396
+ const idpError = params.get("error");
6397
+ if (idpError) {
6398
+ const desc = params.get("error_description") ?? idpError;
6399
+ getSessionStorage()?.removeItem(OIDC_TX_KEY);
6400
+ cleanCallbackUrl(parsed);
6401
+ throw new exports.NeetruError(idpError, `OIDC authorize falhou: ${desc}`);
6402
+ }
6403
+ const code = params.get("code");
6404
+ if (!code) return null;
6405
+ const returnedState = params.get("state");
6406
+ const session = getSessionStorage();
6407
+ const txRaw = session?.getItem(OIDC_TX_KEY) ?? null;
6408
+ let tx = null;
6409
+ if (txRaw) {
6410
+ try {
6411
+ tx = JSON.parse(txRaw);
6412
+ } catch {
6413
+ tx = null;
6414
+ }
6415
+ }
6416
+ if (!tx) {
6417
+ throw new exports.NeetruError(
6418
+ "oidc_state_mismatch",
6419
+ "Callback OIDC sem transa\xE7\xE3o pendente \u2014 `signIn` n\xE3o foi iniciado nesta sess\xE3o (ou j\xE1 consumido)."
6420
+ );
6421
+ }
6422
+ if (!returnedState || returnedState !== tx.state) {
6423
+ session?.removeItem(OIDC_TX_KEY);
6424
+ cleanCallbackUrl(parsed);
6425
+ throw new exports.NeetruError(
6426
+ "oidc_state_mismatch",
6427
+ "state do callback OIDC n\xE3o confere com o da transa\xE7\xE3o (poss\xEDvel CSRF)."
6428
+ );
6429
+ }
6430
+ session?.removeItem(OIDC_TX_KEY);
6431
+ cleanCallbackUrl(parsed);
6432
+ return {
6433
+ code,
6434
+ codeVerifier: tx.codeVerifier,
6435
+ redirectUri: tx.redirectUri,
6436
+ nonce: tx.nonce,
6437
+ state: tx.state,
6438
+ postLoginRedirect: tx.postLoginRedirect
6439
+ };
6440
+ },
6441
+ getIdToken() {
6442
+ const storage = getStorage();
6443
+ const token = storage?.getItem(STORAGE_KEY) ?? null;
6444
+ if (!token) return null;
6445
+ return tokenToUser(token) ? token : null;
6446
+ },
6203
6447
  async signOut() {
6204
6448
  const storage = getStorage();
6205
6449
  const storedToken = storage?.getItem(STORAGE_KEY) ?? null;
@@ -6306,6 +6550,7 @@ function createNeetruClient(config = {}) {
6306
6550
  const env = resolveEnv(config.env);
6307
6551
  const resolved = Object.freeze({
6308
6552
  apiKey,
6553
+ oidcClientId: config.oidcClientId,
6309
6554
  baseUrl,
6310
6555
  fetch: fetchImpl.bind(globalThis),
6311
6556
  env,
@@ -6340,7 +6585,7 @@ function createNeetruClient(config = {}) {
6340
6585
  init_errors();
6341
6586
  init_db_errors();
6342
6587
  init_http();
6343
- var VERSION = "3.1.1";
6588
+ var VERSION = "3.1.3";
6344
6589
 
6345
6590
  exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
6346
6591
  exports.DEV_FIXTURE_USER = DEV_FIXTURE_USER;