academe-kit 0.6.1 → 0.6.2

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/index.cjs CHANGED
@@ -5854,6 +5854,37 @@ exports.GLOBAL_ROLES = void 0;
5854
5854
  GLOBAL_ROLES["GUARDIAN"] = "guardian";
5855
5855
  })(exports.GLOBAL_ROLES || (exports.GLOBAL_ROLES = {}));
5856
5856
 
5857
+ function detectMobileTokenSync() {
5858
+ if (typeof window === "undefined") {
5859
+ return { token: undefined, isMobile: false, decoded: null };
5860
+ }
5861
+ const keycloakConfig = window.keycloakConfig;
5862
+ if (!keycloakConfig?.fromMobile || !keycloakConfig?.token) {
5863
+ return { token: undefined, isMobile: false, decoded: null };
5864
+ }
5865
+ // Validar e decodificar o token mobile
5866
+ try {
5867
+ const decoded = jwtDecode(keycloakConfig.token);
5868
+ if (!decoded) {
5869
+ console.error("[SecurityProvider] Token mobile inválido - ignorando");
5870
+ return { token: undefined, isMobile: false, decoded: null };
5871
+ }
5872
+ // Verificar se o token não está expirado
5873
+ const now = Math.floor(Date.now() / 1000);
5874
+ if (decoded.exp && decoded.exp < now) {
5875
+ console.error("[SecurityProvider] Token mobile expirado - ignorando");
5876
+ return { token: undefined, isMobile: false, decoded: null };
5877
+ }
5878
+ console.log("[SecurityProvider] ✅ Token mobile detectado síncronamente");
5879
+ return { token: keycloakConfig.token, isMobile: true, decoded };
5880
+ }
5881
+ catch (error) {
5882
+ console.error("[SecurityProvider] Erro ao decodificar token mobile:", error);
5883
+ return { token: undefined, isMobile: false, decoded: null };
5884
+ }
5885
+ }
5886
+ // Detecta o token mobile UMA VEZ no carregamento do módulo
5887
+ const initialMobileState = detectMobileTokenSync();
5857
5888
  const AcademeAuthProvider = ({ realm, hubUrl, children, clientId, keycloakUrl, apiBaseUrl, skipApiUserFetch, }) => {
5858
5889
  const oidcConfig = {
5859
5890
  authority: `${keycloakUrl}/realms/${realm}`,
@@ -5900,13 +5931,14 @@ const decodeAccessToken = (token) => {
5900
5931
  const SecurityProvider = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipApiUserFetch = false, children, }) => {
5901
5932
  const auth = useAuth();
5902
5933
  const [currentUser, setCurrentUser] = React2.useState(null);
5903
- const hasTriedSignInSilent = React2.useRef(false);
5904
- const [isTokenReady, setIsTokenReady] = React2.useState(false);
5905
5934
  const [isRefreshing, setIsRefreshing] = React2.useState(false);
5906
- // --- Estado para autenticação mobile ---
5907
- const [isMobileAuth, setIsMobileAuth] = React2.useState(false);
5908
- const [mobileToken, setMobileToken] = React2.useState(undefined);
5909
- const mobileInitializedRef = React2.useRef(false);
5935
+ // CRÍTICO: Inicializar estados com valores do token mobile detectado síncronamente
5936
+ // Isso garante que no primeiro render já temos os valores corretos
5937
+ const hasTriedSignInSilent = React2.useRef(initialMobileState.isMobile);
5938
+ const [isTokenReady, setIsTokenReady] = React2.useState(initialMobileState.isMobile);
5939
+ // --- Estado para autenticação mobile (inicializado com detecção síncrona) ---
5940
+ const [isMobileAuth, setIsMobileAuth] = React2.useState(initialMobileState.isMobile);
5941
+ const [mobileToken, setMobileToken] = React2.useState(initialMobileState.token);
5910
5942
  // Ref para armazenar o resolver da Promise de token
5911
5943
  const tokenReadyResolverRef = React2.useRef(null);
5912
5944
  const tokenReadyPromiseRef = React2.useRef(null);
@@ -5917,48 +5949,13 @@ const SecurityProvider = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipA
5917
5949
  const accessToken = auth.user?.access_token;
5918
5950
  const userProfile = auth.user?.profile;
5919
5951
  const userProfileSub = auth.user?.profile?.sub;
5920
- // Ref para armazenar o token atual (acessível no middleware)
5921
- const currentTokenRef = React2.useRef(undefined);
5922
- // --- 0. Detecção de Token Mobile (ANTES do SSO check) ---
5923
- React2.useEffect(() => {
5924
- // executa uma vez na inicialização
5925
- if (mobileInitializedRef.current)
5926
- return;
5927
- mobileInitializedRef.current = true;
5928
- if (typeof window === "undefined")
5929
- return;
5930
- const keycloakConfig = window.keycloakConfig;
5931
- if (!keycloakConfig?.fromMobile || !keycloakConfig?.token) {
5932
- console.debug("[SecurityProvider] Modo web normal - sem token mobile");
5933
- return;
5934
- }
5935
- // Validar e decodificar o token mobile
5936
- const decoded = decodeAccessToken(keycloakConfig.token);
5937
- if (!decoded) {
5938
- console.error("[SecurityProvider] Token mobile inválido - ignorando");
5939
- return;
5940
- }
5941
- // Verificar se o token não está expirado
5942
- const now = Math.floor(Date.now() / 1000);
5943
- if (decoded.exp && decoded.exp < now) {
5944
- console.error("[SecurityProvider] Token mobile expirado - ignorando");
5945
- return;
5946
- }
5947
- console.log("[SecurityProvider] ✅ Token mobile detectado e válido");
5948
- // Ativar modo mobile
5949
- setMobileToken(keycloakConfig.token);
5950
- setIsMobileAuth(true);
5951
- // Sincronizar com window.accessToken e currentTokenRef
5952
- window.accessToken = keycloakConfig.token;
5953
- currentTokenRef.current = keycloakConfig.token;
5954
- // Marcar que já tentamos SSO (para pular o check)
5955
- hasTriedSignInSilent.current = true;
5956
- // Resolver promise de token imediatamente
5957
- if (tokenReadyResolverRef.current) {
5958
- tokenReadyResolverRef.current();
5959
- }
5960
- setIsTokenReady(true);
5961
- }, []);
5952
+ // CRÍTICO: Inicializar currentTokenRef com o token mobile detectado síncronamente
5953
+ // Isso garante que o middleware do apiClient já tenha o token no primeiro request
5954
+ const currentTokenRef = React2.useRef(initialMobileState.token);
5955
+ // Sincronizar window.accessToken se tivermos token mobile (executa síncronamente)
5956
+ if (initialMobileState.token && typeof window !== "undefined" && !window.accessToken) {
5957
+ window.accessToken = initialMobileState.token;
5958
+ }
5962
5959
  // --- 1. Silent Check Inicial (Check SSO) - Pulado se mobile ---
5963
5960
  React2.useEffect(() => {
5964
5961
  // Pular SSO check se já estamos em modo mobile
@@ -5980,10 +5977,18 @@ const SecurityProvider = ({ apiBaseUrl = "https://stg-api.academe.com.br", skipA
5980
5977
  // --- 2. Configuração de API e Services ---
5981
5978
  const apiClient = React2.useMemo(() => {
5982
5979
  const client = createAcademeApiClient(apiBaseUrl);
5983
- // Inicializa a Promise de token ready
5984
- tokenReadyPromiseRef.current = new Promise((resolve) => {
5985
- tokenReadyResolverRef.current = resolve;
5986
- });
5980
+ // CRÍTICO: Se temos token mobile, criar Promise já resolvida
5981
+ // Isso evita que o middleware aguarde uma Promise que nunca será resolvida
5982
+ if (initialMobileState.token) {
5983
+ tokenReadyPromiseRef.current = Promise.resolve();
5984
+ tokenReadyResolverRef.current = () => { };
5985
+ }
5986
+ else {
5987
+ // Inicializa a Promise de token ready para modo OIDC
5988
+ tokenReadyPromiseRef.current = new Promise((resolve) => {
5989
+ tokenReadyResolverRef.current = resolve;
5990
+ });
5991
+ }
5987
5992
  // Middleware que aguarda o token estar disponível antes de fazer requests
5988
5993
  client.use({
5989
5994
  async onRequest({ request }) {