@neetru/sdk 3.5.0 → 3.6.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.
package/dist/auth.mjs CHANGED
@@ -81,7 +81,7 @@ function compareCalVer(a, b) {
81
81
  }
82
82
  function readInjectedSdkVersion() {
83
83
  try {
84
- return "3.5.0";
84
+ return "3.6.0";
85
85
  } catch {
86
86
  return void 0;
87
87
  }
@@ -6988,6 +6988,94 @@ var MockAi = class {
6988
6988
  }
6989
6989
  };
6990
6990
 
6991
+ // src/auth-pkce-shared.ts
6992
+ init_errors();
6993
+ function getWebCrypto() {
6994
+ const c = globalThis.crypto;
6995
+ if (!c || typeof c.getRandomValues !== "function" || !c.subtle) {
6996
+ throw new NeetruError(
6997
+ "runtime_unsupported",
6998
+ "auth.signIn requer WebCrypto (crypto.subtle) \u2014 indispon\xEDvel neste runtime. Use HTTPS (ou http://localhost) num browser moderno, ou instale um polyfill WebCrypto (ex: react-native-quick-crypto) em React Native."
6999
+ );
7000
+ }
7001
+ return c;
7002
+ }
7003
+ function base64UrlFromBytes(bytes) {
7004
+ let str = "";
7005
+ for (const b of bytes) str += String.fromCharCode(b);
7006
+ const b64 = typeof btoa === "function" ? btoa(str) : Buffer.from(str, "binary").toString("base64");
7007
+ return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
7008
+ }
7009
+ function randomUrlSafe(crypto2, byteLen) {
7010
+ const bytes = new Uint8Array(byteLen);
7011
+ crypto2.getRandomValues(bytes);
7012
+ return base64UrlFromBytes(bytes);
7013
+ }
7014
+ async function pkceChallengeS256(crypto2, verifier) {
7015
+ const data = new TextEncoder().encode(verifier);
7016
+ const digest = await crypto2.subtle.digest("SHA-256", data);
7017
+ return base64UrlFromBytes(new Uint8Array(digest));
7018
+ }
7019
+ function resolveIdpOrigin(baseUrl) {
7020
+ const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
7021
+ return overrideAuthUrl ?? baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
7022
+ }
7023
+ function resolveOidcClientId(config) {
7024
+ let clientId = config.oidcClientId;
7025
+ if (!clientId && config.apiKey) {
7026
+ clientId = parseApiKey(config.apiKey).keyId;
7027
+ }
7028
+ if (!clientId) {
7029
+ throw new NeetruError(
7030
+ "invalid_config",
7031
+ "auth OIDC requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
7032
+ );
7033
+ }
7034
+ return clientId;
7035
+ }
7036
+ function buildAuthorizeUrl(params) {
7037
+ const url = new URL("/api/v1/oauth/authorize", params.idpOrigin);
7038
+ url.searchParams.set("response_type", "code");
7039
+ url.searchParams.set("client_id", params.clientId);
7040
+ url.searchParams.set("redirect_uri", params.redirectUri);
7041
+ url.searchParams.set("scope", params.scope);
7042
+ url.searchParams.set("state", params.state);
7043
+ url.searchParams.set("nonce", params.nonce);
7044
+ url.searchParams.set("code_challenge", params.codeChallenge);
7045
+ url.searchParams.set("code_challenge_method", "S256");
7046
+ return url;
7047
+ }
7048
+ function decodeJwtPayload(token) {
7049
+ const parts = token.split(".");
7050
+ if (parts.length !== 3) return null;
7051
+ try {
7052
+ const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
7053
+ const pad = "=".repeat((4 - b64.length % 4) % 4);
7054
+ const decoded = typeof atob === "function" ? atob(b64 + pad) : Buffer.from(b64 + pad, "base64").toString("utf-8");
7055
+ return JSON.parse(decoded);
7056
+ } catch {
7057
+ return null;
7058
+ }
7059
+ }
7060
+ function jwtToNeetruUser(token) {
7061
+ const payload = decodeJwtPayload(token);
7062
+ if (!payload || typeof payload.sub !== "string") return null;
7063
+ if (typeof payload.exp === "number" && payload.exp * 1e3 < Date.now()) {
7064
+ return null;
7065
+ }
7066
+ return {
7067
+ uid: payload.sub,
7068
+ email: typeof payload.email === "string" ? payload.email : "",
7069
+ emailVerified: typeof payload.email_verified === "boolean" ? payload.email_verified : void 0,
7070
+ displayName: typeof payload.name === "string" ? payload.name : void 0,
7071
+ photoURL: typeof payload.picture === "string" ? payload.picture : void 0,
7072
+ isStaff: payload.is_staff === true,
7073
+ isCustomer: payload.is_customer === true,
7074
+ tenantId: typeof payload.tenant_id === "string" ? payload.tenant_id : void 0,
7075
+ ...payload
7076
+ };
7077
+ }
7078
+
6991
7079
  // src/auth.ts
6992
7080
  function readEnvApiKey() {
6993
7081
  try {
@@ -7045,36 +7133,6 @@ function _jwtPayloadToUser(payload) {
7045
7133
  };
7046
7134
  }
7047
7135
  var OIDC_TX_KEY = "neetru_oauth_tx";
7048
- function resolveIdpOrigin(baseUrl) {
7049
- const overrideAuthUrl = typeof globalThis.NEETRU_AUTH_URL === "string" ? globalThis.NEETRU_AUTH_URL : null;
7050
- return overrideAuthUrl ?? baseUrl.replace(/^https?:\/\/api\./, "https://auth.");
7051
- }
7052
- function getWebCrypto() {
7053
- const c = globalThis.crypto;
7054
- if (!c || typeof c.getRandomValues !== "function" || !c.subtle) {
7055
- throw new NeetruError(
7056
- "runtime_unsupported",
7057
- "auth.signIn requer WebCrypto (crypto.subtle) \u2014 indispon\xEDvel neste runtime. Use HTTPS (ou http://localhost) num browser moderno."
7058
- );
7059
- }
7060
- return c;
7061
- }
7062
- function base64UrlFromBytes(bytes) {
7063
- let str = "";
7064
- for (const b of bytes) str += String.fromCharCode(b);
7065
- const b64 = typeof btoa === "function" ? btoa(str) : Buffer.from(str, "binary").toString("base64");
7066
- return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
7067
- }
7068
- function randomUrlSafe(crypto2, byteLen) {
7069
- const bytes = new Uint8Array(byteLen);
7070
- crypto2.getRandomValues(bytes);
7071
- return base64UrlFromBytes(bytes);
7072
- }
7073
- async function pkceChallengeS256(crypto2, verifier) {
7074
- const data = new TextEncoder().encode(verifier);
7075
- const digest = await crypto2.subtle.digest("SHA-256", data);
7076
- return base64UrlFromBytes(new Uint8Array(digest));
7077
- }
7078
7136
  function cleanCallbackUrl(parsed) {
7079
7137
  try {
7080
7138
  const history = globalThis.history;
@@ -7108,36 +7166,6 @@ function createOidcAuthNamespace(config) {
7108
7166
  return null;
7109
7167
  }
7110
7168
  }
7111
- function decodeJwtPayload(token) {
7112
- const parts = token.split(".");
7113
- if (parts.length !== 3) return null;
7114
- try {
7115
- const b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
7116
- const pad = "=".repeat((4 - b64.length % 4) % 4);
7117
- const decoded = typeof atob === "function" ? atob(b64 + pad) : Buffer.from(b64 + pad, "base64").toString("utf-8");
7118
- return JSON.parse(decoded);
7119
- } catch {
7120
- return null;
7121
- }
7122
- }
7123
- function tokenToUser(token) {
7124
- const payload = decodeJwtPayload(token);
7125
- if (!payload || typeof payload.sub !== "string") return null;
7126
- if (typeof payload.exp === "number" && payload.exp * 1e3 < Date.now()) {
7127
- return null;
7128
- }
7129
- return {
7130
- uid: payload.sub,
7131
- email: typeof payload.email === "string" ? payload.email : "",
7132
- emailVerified: typeof payload.email_verified === "boolean" ? payload.email_verified : void 0,
7133
- displayName: typeof payload.name === "string" ? payload.name : void 0,
7134
- photoURL: typeof payload.picture === "string" ? payload.picture : void 0,
7135
- isStaff: payload.is_staff === true,
7136
- isCustomer: payload.is_customer === true,
7137
- tenantId: typeof payload.tenant_id === "string" ? payload.tenant_id : void 0,
7138
- ...payload
7139
- };
7140
- }
7141
7169
  function loadCachedUser() {
7142
7170
  if (cachedUser) {
7143
7171
  const exp = cachedUser.exp;
@@ -7158,7 +7186,7 @@ function createOidcAuthNamespace(config) {
7158
7186
  attemptSilentRefresh();
7159
7187
  return null;
7160
7188
  }
7161
- const user = tokenToUser(token);
7189
+ const user = jwtToNeetruUser(token);
7162
7190
  if (!user) {
7163
7191
  storage.removeItem(STORAGE_KEY);
7164
7192
  attemptSilentRefresh();
@@ -7229,7 +7257,7 @@ function createOidcAuthNamespace(config) {
7229
7257
  if (!res.ok || typeof payload?.error === "string") return false;
7230
7258
  const idToken = payload?.id_token;
7231
7259
  if (typeof idToken !== "string" || idToken.length === 0) return false;
7232
- const user = tokenToUser(idToken);
7260
+ const user = jwtToNeetruUser(idToken);
7233
7261
  if (!user) return false;
7234
7262
  const storage = getStorage();
7235
7263
  storage?.setItem(STORAGE_KEY, idToken);
@@ -7275,17 +7303,7 @@ function createOidcAuthNamespace(config) {
7275
7303
  }, msUntilExpiry + 1);
7276
7304
  }
7277
7305
  function resolveClientId() {
7278
- let clientId = config.oidcClientId;
7279
- if (!clientId && config.apiKey) {
7280
- clientId = parseApiKey(config.apiKey).keyId;
7281
- }
7282
- if (!clientId) {
7283
- throw new NeetruError(
7284
- "invalid_config",
7285
- "auth OIDC requer `oidcClientId` (ou `apiKey`) configurado para montar o client_id."
7286
- );
7287
- }
7288
- return clientId;
7306
+ return resolveOidcClientId(config);
7289
7307
  }
7290
7308
  async function handleRedirectCallback(currentUrl) {
7291
7309
  const href = currentUrl ?? (typeof globalThis.location !== "undefined" ? globalThis.location.href : void 0);
@@ -7403,7 +7421,7 @@ function createOidcAuthNamespace(config) {
7403
7421
  "nonce do id_token n\xE3o confere com o da transa\xE7\xE3o OIDC (poss\xEDvel replay). Token descartado."
7404
7422
  );
7405
7423
  }
7406
- const user = tokenToUser(idToken);
7424
+ const user = jwtToNeetruUser(idToken);
7407
7425
  if (!user) {
7408
7426
  throw new NeetruError(
7409
7427
  "token_exchange_failed",
@@ -7448,15 +7466,15 @@ function createOidcAuthNamespace(config) {
7448
7466
  };
7449
7467
  session.setItem(OIDC_TX_KEY, JSON.stringify(tx));
7450
7468
  const idpOrigin = resolveIdpOrigin(config.baseUrl);
7451
- const url = new URL("/api/v1/oauth/authorize", idpOrigin);
7452
- url.searchParams.set("response_type", "code");
7453
- url.searchParams.set("client_id", clientId);
7454
- url.searchParams.set("redirect_uri", redirectUri);
7455
- url.searchParams.set("scope", scope);
7456
- url.searchParams.set("state", state);
7457
- url.searchParams.set("nonce", nonce);
7458
- url.searchParams.set("code_challenge", codeChallenge);
7459
- url.searchParams.set("code_challenge_method", "S256");
7469
+ const url = buildAuthorizeUrl({
7470
+ idpOrigin,
7471
+ clientId,
7472
+ redirectUri,
7473
+ scope,
7474
+ state,
7475
+ nonce,
7476
+ codeChallenge
7477
+ });
7460
7478
  globalThis.location.assign(url.toString());
7461
7479
  return;
7462
7480
  }
@@ -7471,7 +7489,7 @@ function createOidcAuthNamespace(config) {
7471
7489
  const storage = getStorage();
7472
7490
  const token = storage?.getItem(STORAGE_KEY) ?? null;
7473
7491
  if (!token) return null;
7474
- return tokenToUser(token) ? token : null;
7492
+ return jwtToNeetruUser(token) ? token : null;
7475
7493
  },
7476
7494
  async signOut() {
7477
7495
  const storage = getStorage();