{"version":3,"sources":["../src/components/Auth/useUrlAuthentication.ts"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { useLocation } from 'react-router-dom';\n\n/**\n * Options interface for the useUrlAuthentication hook\n *\n * @template Tokens - Type for authentication tokens\n * @template Session - Type for session information\n * @template Profile - Type for profile information\n * @template User - Type for user information\n *\n * @interface UseUrlAuthOptions\n * @property {(tokens: Tokens) => void} setTokens - Function to set authentication tokens\n * @property {(session: Session) => void} setSessionInfo - Function to set session information\n * @property {(profile: Profile) => void} [setSelectedProfile] - Optional function to set selected profile\n * @property {(user: User) => void} [setUser] - Optional function to set user data\n * @property {object} api - API instance with get method\n * @property {(endpoint: string, config: unknown) => Promise<unknown>} api.get - API get method\n * @property {string} endpoint - API endpoint to fetch session data\n * @property {(searchParams: URLSearchParams) => object} [extractParams] - Custom parameter extraction function\n * @property {() => void} [clearParamsFromURL] - Function to clear URL parameters after processing\n * @property {number} [maxRetries] - Maximum number of retry attempts (default: 3)\n * @property {number} [retryDelay] - Base delay between retries in milliseconds (default: 1000)\n * @property {(error: unknown) => void} [onError] - Error handler callback\n * @property {() => void} [onAuthHydrated] - Called after session is stored, before URL params are cleared.\n *   Use this to re-run the auth context check so guards re-evaluate immediately,\n *   preventing the \"Área Restrita\" flash on the first login redirect.\n */\nexport interface UseUrlAuthOptions<\n  Tokens = unknown,\n  Session = unknown,\n  Profile = unknown,\n  User = unknown,\n> {\n  setTokens: (tokens: Tokens) => void;\n  setSessionInfo: (session: Session) => void;\n  setSelectedProfile?: (profile: Profile) => void;\n  setUser?: (user: User) => void;\n  api: { get: (endpoint: string, config: unknown) => Promise<unknown> };\n  endpoint: string;\n  extractParams?: (searchParams: URLSearchParams) => {\n    sessionId: string;\n    token: string;\n    refreshToken: string;\n  };\n  clearParamsFromURL?: () => void;\n  maxRetries?: number;\n  retryDelay?: number;\n  onError?: (error: unknown) => void;\n  onAuthHydrated?: () => void | Promise<void>;\n}\n\n/**\n * Helper function to extract authentication parameters from URL\n *\n * @param {object} location - Location object with search property\n * @param {string} location.search - URL search string\n * @param {function} [extractParams] - Custom parameter extraction function\n * @returns {object} Object with sessionId, token, and refreshToken\n *\n * @private\n */\nconst getAuthParams = (\n  location: { search: string },\n  extractParams?: (searchParams: URLSearchParams) => {\n    sessionId: string;\n    token: string;\n    refreshToken: string;\n  }\n) => {\n  const searchParams = new URLSearchParams(location.search);\n  return extractParams\n    ? extractParams(searchParams)\n    : {\n        sessionId: searchParams.get('sessionId'),\n        token: searchParams.get('token'),\n        refreshToken: searchParams.get('refreshToken'),\n      };\n};\n\n/**\n * Helper function to validate authentication parameters\n *\n * @param {object} authParams - Authentication parameters object\n * @param {string | null} authParams.sessionId - Session ID from URL\n * @param {string | null} authParams.token - Authentication token from URL\n * @param {string | null} authParams.refreshToken - Refresh token from URL\n * @returns {boolean} True if all required parameters are present\n *\n * @private\n */\nconst hasValidAuthParams = (authParams: {\n  sessionId: string | null;\n  token: string | null;\n  refreshToken: string | null;\n}) => {\n  return !!(\n    authParams?.sessionId &&\n    authParams?.token &&\n    authParams?.refreshToken\n  );\n};\n\n/**\n * Helper function to check if response has valid profile data\n *\n * @param {unknown} data - Response data to validate\n * @returns {data is Record<string, unknown>} Type guard for valid profile data\n *\n * @private\n */\nconst hasValidProfileData = (\n  data: unknown\n): data is Record<string, unknown> => {\n  return data !== null && typeof data === 'object' && data !== undefined;\n};\n\n/**\n * Helper function to handle profile selection from response data\n *\n * @template Profile - Profile type\n * @param {unknown} responseData - Response data from API\n * @param {(profile: Profile) => void} [setSelectedProfile] - Optional function to set selected profile\n * @returns {void}\n *\n * @private\n */\nconst handleProfileSelection = <Profile>(\n  responseData: unknown,\n  setSelectedProfile?: (profile: Profile) => void\n) => {\n  if (!setSelectedProfile) return;\n  if (!hasValidProfileData(responseData)) return;\n\n  const profileId = responseData.profileId;\n  const isValidProfileId = profileId !== null && profileId !== undefined;\n\n  if (isValidProfileId) {\n    setSelectedProfile({\n      id: profileId,\n    } as Profile);\n  }\n};\n\n/**\n * Helper function to handle user data extraction from response data\n *\n * @template User - User type\n * @param {unknown} responseData - Response data from API\n * @param {(user: User) => void} [setUser] - Optional function to set user data\n * @returns {void}\n *\n * @private\n */\nconst handleUserData = <User>(\n  responseData: unknown,\n  setUser?: (user: User) => void\n) => {\n  if (!setUser) return;\n  if (!hasValidProfileData(responseData)) return;\n\n  // Extrair dados do usuário da resposta da API\n  const userId = responseData.userId;\n  const userName = responseData.userName;\n  const userEmail = responseData.userEmail;\n\n  if (userId) {\n    const userData: Record<string, unknown> = {\n      id: userId,\n    };\n\n    if (userName) {\n      userData.name = userName;\n    }\n\n    if (userEmail) {\n      userData.email = userEmail;\n    }\n\n    // Adicionar outros campos conforme necessário\n    setUser(userData as User);\n  }\n};\n\n/**\n * Hook for handling URL-based authentication\n * Extracts authentication parameters from URL and processes them\n *\n * @template Tokens - Type for authentication tokens\n * @template Session - Type for session information\n * @template Profile - Type for profile information\n * @template User - Type for user information\n *\n * @param {UseUrlAuthOptions<Tokens, Session, Profile, User>} options - Configuration options\n * @returns {void}\n *\n * @example\n * ```typescript\n * useUrlAuthentication({\n *   setTokens: (tokens) => authStore.setTokens(tokens),\n *   setSessionInfo: (session) => authStore.setSessionInfo(session),\n *   setSelectedProfile: (profile) => authStore.setProfile(profile),\n *   setUser: (user) => authStore.setUser(user),\n *   api: apiInstance,\n *   endpoint: '/auth/session',\n *   clearParamsFromURL: () => navigate('/', { replace: true })\n * });\n * ```\n */\nexport function useUrlAuthentication<\n  Tokens = unknown,\n  Session = unknown,\n  Profile = unknown,\n  User = unknown,\n>(options: UseUrlAuthOptions<Tokens, Session, Profile, User>) {\n  const location = useLocation();\n  const processedRef = useRef(false);\n\n  useEffect(() => {\n    /**\n     * Main authentication handler that processes URL parameters\n     *\n     * @private\n     */\n    const handleAuthentication = async (): Promise<void> => {\n      // Check if we already processed this request\n      if (processedRef.current) {\n        return;\n      }\n\n      const authParams = getAuthParams(location, options.extractParams);\n\n      // Only proceed if we have all required auth parameters\n      if (!hasValidAuthParams(authParams)) {\n        return;\n      }\n\n      // Mark as processed to prevent multiple calls\n      processedRef.current = true;\n\n      try {\n        // Set tokens first\n        options.setTokens({\n          token: authParams.token,\n          refreshToken: authParams.refreshToken,\n        } as Tokens);\n\n        // Call session-info with proper error handling and retry\n        const maxRetries = options.maxRetries || 3;\n        const retryDelay = options.retryDelay || 1000;\n        let retries = 0;\n        let sessionData = null;\n\n        while (retries < maxRetries && !sessionData) {\n          try {\n            const response = (await options.api.get(options.endpoint, {\n              headers: {\n                Authorization: `Bearer ${authParams.token}`,\n              },\n            })) as { data: { data: unknown; [key: string]: unknown } };\n\n            sessionData = response.data.data;\n            break;\n          } catch (error) {\n            retries++;\n            console.warn(\n              `Tentativa ${retries}/${maxRetries} falhou para ${options.endpoint}:`,\n              error\n            );\n\n            if (retries < maxRetries) {\n              // Wait before retry (exponential backoff)\n              await new Promise((resolve) =>\n                setTimeout(resolve, retryDelay * retries)\n              );\n            } else {\n              throw error;\n            }\n          }\n        }\n\n        // Always call setSessionInfo with the received data (even if null)\n        options.setSessionInfo(sessionData as Session);\n        handleProfileSelection(sessionData, options.setSelectedProfile);\n        handleUserData(sessionData, options.setUser);\n        // Notify caller that auth state is hydrated into the store so any\n        // auth context can re-check before URL params are removed.\n        if (options.onAuthHydrated) await options.onAuthHydrated();\n        options.clearParamsFromURL?.();\n      } catch (error) {\n        console.error('Erro ao obter informações da sessão:', error);\n        // Reset processed flag on error to allow retry\n        processedRef.current = false;\n        // Call error handler if provided\n        options.onError?.(error);\n      }\n    };\n\n    handleAuthentication();\n  }, [\n    location.search,\n    options.setSessionInfo,\n    options.setSelectedProfile,\n    options.setUser,\n    options.setTokens,\n    options.api,\n    options.endpoint,\n    options.extractParams,\n    options.clearParamsFromURL,\n    options.maxRetries,\n    options.retryDelay,\n    options.onError,\n    options.onAuthHydrated,\n  ]);\n}\n"],"mappings":"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","names":[]}