analytica-frontend-lib 1.4.63 → 1.4.65

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 (33) hide show
  1. package/dist/Auth/useUrlAuthentication/index.d.ts +4 -0
  2. package/dist/Auth/useUrlAuthentication/index.d.ts.map +1 -1
  3. package/dist/Auth/useUrlAuthentication/index.js +3 -1
  4. package/dist/Auth/useUrlAuthentication/index.js.map +1 -1
  5. package/dist/Auth/useUrlAuthentication/index.mjs +3 -1
  6. package/dist/Auth/useUrlAuthentication/index.mjs.map +1 -1
  7. package/dist/RecommendedLessonsHistory/index.js +2745 -624
  8. package/dist/RecommendedLessonsHistory/index.js.map +1 -1
  9. package/dist/RecommendedLessonsHistory/index.mjs +2765 -634
  10. package/dist/RecommendedLessonsHistory/index.mjs.map +1 -1
  11. package/dist/hooks/useAppContent.d.ts +1 -0
  12. package/dist/hooks/useAppContent.d.ts.map +1 -1
  13. package/dist/hooks/useRecommendedClassDrafts/index.js.map +1 -1
  14. package/dist/hooks/useRecommendedClassDrafts/index.mjs.map +1 -1
  15. package/dist/hooks/useRecommendedLessonsPage/index.d.ts +7 -2
  16. package/dist/hooks/useRecommendedLessonsPage/index.d.ts.map +1 -1
  17. package/dist/hooks/useRecommendedLessonsPage/index.js +25 -8
  18. package/dist/hooks/useRecommendedLessonsPage/index.js.map +1 -1
  19. package/dist/hooks/useRecommendedLessonsPage/index.mjs +25 -8
  20. package/dist/hooks/useRecommendedLessonsPage/index.mjs.map +1 -1
  21. package/dist/hooks/useRecommendedLessonsPage.d.ts +7 -2
  22. package/dist/hooks/useRecommendedLessonsPage.d.ts.map +1 -1
  23. package/dist/index.js +2424 -2094
  24. package/dist/index.js.map +1 -1
  25. package/dist/index.mjs +2287 -1957
  26. package/dist/index.mjs.map +1 -1
  27. package/dist/types/recommendedLessons/index.d.ts +8 -0
  28. package/dist/types/recommendedLessons/index.d.ts.map +1 -1
  29. package/dist/types/recommendedLessons/index.js.map +1 -1
  30. package/dist/types/recommendedLessons/index.mjs.map +1 -1
  31. package/dist/types/recommendedLessons.d.ts +8 -0
  32. package/dist/types/recommendedLessons.d.ts.map +1 -1
  33. package/package.json +1 -1
@@ -19,6 +19,9 @@
19
19
  * @property {number} [maxRetries] - Maximum number of retry attempts (default: 3)
20
20
  * @property {number} [retryDelay] - Base delay between retries in milliseconds (default: 1000)
21
21
  * @property {(error: unknown) => void} [onError] - Error handler callback
22
+ * @property {() => void} [onAuthHydrated] - Called after session is stored, before URL params are cleared.
23
+ * Use this to re-run the auth context check so guards re-evaluate immediately,
24
+ * preventing the "Área Restrita" flash on the first login redirect.
22
25
  */
23
26
  export interface UseUrlAuthOptions<Tokens = unknown, Session = unknown, Profile = unknown, User = unknown> {
24
27
  setTokens: (tokens: Tokens) => void;
@@ -38,6 +41,7 @@ export interface UseUrlAuthOptions<Tokens = unknown, Session = unknown, Profile
38
41
  maxRetries?: number;
39
42
  retryDelay?: number;
40
43
  onError?: (error: unknown) => void;
44
+ onAuthHydrated?: () => void | Promise<void>;
41
45
  }
42
46
  /**
43
47
  * Hook for handling URL-based authentication
@@ -1 +1 @@
1
- {"version":3,"file":"useUrlAuthentication.d.ts","sourceRoot":"","sources":["../../../src/components/Auth/useUrlAuthentication.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,iBAAiB,CAChC,MAAM,GAAG,OAAO,EAChB,OAAO,GAAG,OAAO,EACjB,OAAO,GAAG,OAAO,EACjB,IAAI,GAAG,OAAO;IAEd,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,cAAc,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC/B,GAAG,EAAE;QAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,CAAC;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,CAAC,YAAY,EAAE,eAAe,KAAK;QACjD,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;AAsID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,GAAG,OAAO,EAChB,OAAO,GAAG,OAAO,EACjB,OAAO,GAAG,OAAO,EACjB,IAAI,GAAG,OAAO,EACd,OAAO,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,QAgG3D"}
1
+ {"version":3,"file":"useUrlAuthentication.d.ts","sourceRoot":"","sources":["../../../src/components/Auth/useUrlAuthentication.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,iBAAiB,CAChC,MAAM,GAAG,OAAO,EAChB,OAAO,GAAG,OAAO,EACjB,OAAO,GAAG,OAAO,EACjB,IAAI,GAAG,OAAO;IAEd,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,cAAc,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC/B,GAAG,EAAE;QAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,CAAC;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,CAAC,YAAY,EAAE,eAAe,KAAK;QACjD,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAsID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,GAAG,OAAO,EAChB,OAAO,GAAG,OAAO,EACjB,OAAO,GAAG,OAAO,EACjB,IAAI,GAAG,OAAO,EACd,OAAO,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,QAoG3D"}
@@ -118,6 +118,7 @@ function useUrlAuthentication(options) {
118
118
  options.setSessionInfo(sessionData);
119
119
  handleProfileSelection(sessionData, options.setSelectedProfile);
120
120
  handleUserData(sessionData, options.setUser);
121
+ if (options.onAuthHydrated) await options.onAuthHydrated();
121
122
  options.clearParamsFromURL?.();
122
123
  } catch (error) {
123
124
  console.error("Erro ao obter informa\xE7\xF5es da sess\xE3o:", error);
@@ -138,7 +139,8 @@ function useUrlAuthentication(options) {
138
139
  options.clearParamsFromURL,
139
140
  options.maxRetries,
140
141
  options.retryDelay,
141
- options.onError
142
+ options.onError,
143
+ options.onAuthHydrated
142
144
  ]);
143
145
  }
144
146
  // Annotate the CommonJS export names for ESM import in node:
@@ -1 +1 @@
1
- {"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 */\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}\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 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 ]);\n}\n"],"mappings":"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","names":[]}
1
+ {"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":[]}
@@ -94,6 +94,7 @@ function useUrlAuthentication(options) {
94
94
  options.setSessionInfo(sessionData);
95
95
  handleProfileSelection(sessionData, options.setSelectedProfile);
96
96
  handleUserData(sessionData, options.setUser);
97
+ if (options.onAuthHydrated) await options.onAuthHydrated();
97
98
  options.clearParamsFromURL?.();
98
99
  } catch (error) {
99
100
  console.error("Erro ao obter informa\xE7\xF5es da sess\xE3o:", error);
@@ -114,7 +115,8 @@ function useUrlAuthentication(options) {
114
115
  options.clearParamsFromURL,
115
116
  options.maxRetries,
116
117
  options.retryDelay,
117
- options.onError
118
+ options.onError,
119
+ options.onAuthHydrated
118
120
  ]);
119
121
  }
120
122
  export {
@@ -1 +1 @@
1
- {"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 */\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}\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 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 ]);\n}\n"],"mappings":"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","names":[]}
1
+ {"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":[]}