analytica-frontend-lib 1.1.23 → 1.1.24
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/useUrlAuthentication/index.d.mts +6 -0
- package/dist/Auth/useUrlAuthentication/index.d.ts +6 -0
- package/dist/Auth/useUrlAuthentication/index.js +41 -8
- package/dist/Auth/useUrlAuthentication/index.js.map +1 -1
- package/dist/Auth/useUrlAuthentication/index.mjs +42 -9
- package/dist/Auth/useUrlAuthentication/index.mjs.map +1 -1
- package/dist/index.js +41 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +46 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
* @property {string} endpoint - API endpoint to fetch session data
|
|
17
17
|
* @property {(searchParams: URLSearchParams) => object} [extractParams] - Custom parameter extraction function
|
|
18
18
|
* @property {() => void} [clearParamsFromURL] - Function to clear URL parameters after processing
|
|
19
|
+
* @property {number} [maxRetries] - Maximum number of retry attempts (default: 3)
|
|
20
|
+
* @property {number} [retryDelay] - Base delay between retries in milliseconds (default: 1000)
|
|
21
|
+
* @property {(error: unknown) => void} [onError] - Error handler callback
|
|
19
22
|
*/
|
|
20
23
|
interface UseUrlAuthOptions<Tokens = unknown, Session = unknown, Profile = unknown, User = unknown> {
|
|
21
24
|
setTokens: (tokens: Tokens) => void;
|
|
@@ -32,6 +35,9 @@ interface UseUrlAuthOptions<Tokens = unknown, Session = unknown, Profile = unkno
|
|
|
32
35
|
refreshToken: string;
|
|
33
36
|
};
|
|
34
37
|
clearParamsFromURL?: () => void;
|
|
38
|
+
maxRetries?: number;
|
|
39
|
+
retryDelay?: number;
|
|
40
|
+
onError?: (error: unknown) => void;
|
|
35
41
|
}
|
|
36
42
|
/**
|
|
37
43
|
* Hook for handling URL-based authentication
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
* @property {string} endpoint - API endpoint to fetch session data
|
|
17
17
|
* @property {(searchParams: URLSearchParams) => object} [extractParams] - Custom parameter extraction function
|
|
18
18
|
* @property {() => void} [clearParamsFromURL] - Function to clear URL parameters after processing
|
|
19
|
+
* @property {number} [maxRetries] - Maximum number of retry attempts (default: 3)
|
|
20
|
+
* @property {number} [retryDelay] - Base delay between retries in milliseconds (default: 1000)
|
|
21
|
+
* @property {(error: unknown) => void} [onError] - Error handler callback
|
|
19
22
|
*/
|
|
20
23
|
interface UseUrlAuthOptions<Tokens = unknown, Session = unknown, Profile = unknown, User = unknown> {
|
|
21
24
|
setTokens: (tokens: Tokens) => void;
|
|
@@ -32,6 +35,9 @@ interface UseUrlAuthOptions<Tokens = unknown, Session = unknown, Profile = unkno
|
|
|
32
35
|
refreshToken: string;
|
|
33
36
|
};
|
|
34
37
|
clearParamsFromURL?: () => void;
|
|
38
|
+
maxRetries?: number;
|
|
39
|
+
retryDelay?: number;
|
|
40
|
+
onError?: (error: unknown) => void;
|
|
35
41
|
}
|
|
36
42
|
/**
|
|
37
43
|
* Hook for handling URL-based authentication
|
|
@@ -71,28 +71,58 @@ var handleUserData = (responseData, setUser) => {
|
|
|
71
71
|
};
|
|
72
72
|
function useUrlAuthentication(options) {
|
|
73
73
|
const location = (0, import_react_router_dom.useLocation)();
|
|
74
|
+
const processedRef = (0, import_react.useRef)(false);
|
|
74
75
|
(0, import_react.useEffect)(() => {
|
|
75
76
|
const handleAuthentication = async () => {
|
|
77
|
+
if (processedRef.current) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
76
80
|
const authParams = getAuthParams(location, options.extractParams);
|
|
77
81
|
if (!hasValidAuthParams(authParams)) {
|
|
78
82
|
return;
|
|
79
83
|
}
|
|
84
|
+
processedRef.current = true;
|
|
80
85
|
try {
|
|
81
86
|
options.setTokens({
|
|
82
87
|
token: authParams.token,
|
|
83
88
|
refreshToken: authParams.refreshToken
|
|
84
89
|
});
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
90
|
+
const maxRetries = options.maxRetries || 3;
|
|
91
|
+
const retryDelay = options.retryDelay || 1e3;
|
|
92
|
+
let retries = 0;
|
|
93
|
+
let sessionData = null;
|
|
94
|
+
while (retries < maxRetries && !sessionData) {
|
|
95
|
+
try {
|
|
96
|
+
const response = await options.api.get(options.endpoint, {
|
|
97
|
+
headers: {
|
|
98
|
+
Authorization: `Bearer ${authParams.token}`
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
sessionData = response.data.data;
|
|
102
|
+
break;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
retries++;
|
|
105
|
+
console.warn(
|
|
106
|
+
`Tentativa ${retries}/${maxRetries} falhou para ${options.endpoint}:`,
|
|
107
|
+
error
|
|
108
|
+
);
|
|
109
|
+
if (retries < maxRetries) {
|
|
110
|
+
await new Promise(
|
|
111
|
+
(resolve) => setTimeout(resolve, retryDelay * retries)
|
|
112
|
+
);
|
|
113
|
+
} else {
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
88
116
|
}
|
|
89
|
-
}
|
|
90
|
-
options.setSessionInfo(
|
|
91
|
-
handleProfileSelection(
|
|
92
|
-
handleUserData(
|
|
117
|
+
}
|
|
118
|
+
options.setSessionInfo(sessionData);
|
|
119
|
+
handleProfileSelection(sessionData, options.setSelectedProfile);
|
|
120
|
+
handleUserData(sessionData, options.setUser);
|
|
93
121
|
options.clearParamsFromURL?.();
|
|
94
122
|
} catch (error) {
|
|
95
123
|
console.error("Erro ao obter informa\xE7\xF5es da sess\xE3o:", error);
|
|
124
|
+
processedRef.current = false;
|
|
125
|
+
options.onError?.(error);
|
|
96
126
|
}
|
|
97
127
|
};
|
|
98
128
|
handleAuthentication();
|
|
@@ -105,7 +135,10 @@ function useUrlAuthentication(options) {
|
|
|
105
135
|
options.api,
|
|
106
136
|
options.endpoint,
|
|
107
137
|
options.extractParams,
|
|
108
|
-
options.clearParamsFromURL
|
|
138
|
+
options.clearParamsFromURL,
|
|
139
|
+
options.maxRetries,
|
|
140
|
+
options.retryDelay,
|
|
141
|
+
options.onError
|
|
109
142
|
]);
|
|
110
143
|
}
|
|
111
144
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Auth/useUrlAuthentication.ts"],"sourcesContent":["import { useEffect } 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 */\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}\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\n useEffect(() => {\n /**\n * Main authentication handler that processes URL parameters\n *\n * @returns {Promise<void>}\n * @private\n */\n const handleAuthentication = async () => {\n const authParams = getAuthParams(location, options.extractParams);\n\n if (!hasValidAuthParams(authParams)) {\n return;\n }\n\n try {\n options.setTokens({\n token: authParams.token,\n refreshToken: authParams.refreshToken,\n } as Tokens);\n\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 options.setSessionInfo(response.data.data as Session);\n handleProfileSelection(response.data.data, options.setSelectedProfile);\n handleUserData(response.data.data, options.setUser);\n options.clearParamsFromURL?.();\n } catch (error) {\n console.error('Erro ao obter informações da sessão:', 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 ]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA0B;AAC1B,8BAA4B;AAmD5B,IAAM,gBAAgB,CACpB,UACA,kBAKG;AACH,QAAM,eAAe,IAAI,gBAAgB,SAAS,MAAM;AACxD,SAAO,gBACH,cAAc,YAAY,IAC1B;AAAA,IACE,WAAW,aAAa,IAAI,WAAW;AAAA,IACvC,OAAO,aAAa,IAAI,OAAO;AAAA,IAC/B,cAAc,aAAa,IAAI,cAAc;AAAA,EAC/C;AACN;AAaA,IAAM,qBAAqB,CAAC,eAItB;AACJ,SAAO,CAAC,EACN,YAAY,aACZ,YAAY,SACZ,YAAY;AAEhB;AAUA,IAAM,sBAAsB,CAC1B,SACoC;AACpC,SAAO,SAAS,QAAQ,OAAO,SAAS,YAAY,SAAS;AAC/D;AAYA,IAAM,yBAAyB,CAC7B,cACA,uBACG;AACH,MAAI,CAAC,mBAAoB;AACzB,MAAI,CAAC,oBAAoB,YAAY,EAAG;AAExC,QAAM,YAAY,aAAa;AAC/B,QAAM,mBAAmB,cAAc,QAAQ,cAAc;AAE7D,MAAI,kBAAkB;AACpB,uBAAmB;AAAA,MACjB,IAAI;AAAA,IACN,CAAY;AAAA,EACd;AACF;AAYA,IAAM,iBAAiB,CACrB,cACA,YACG;AACH,MAAI,CAAC,QAAS;AACd,MAAI,CAAC,oBAAoB,YAAY,EAAG;AAGxC,QAAM,SAAS,aAAa;AAC5B,QAAM,WAAW,aAAa;AAC9B,QAAM,YAAY,aAAa;AAE/B,MAAI,QAAQ;AACV,UAAM,WAAoC;AAAA,MACxC,IAAI;AAAA,IACN;AAEA,QAAI,UAAU;AACZ,eAAS,OAAO;AAAA,IAClB;AAEA,QAAI,WAAW;AACb,eAAS,QAAQ;AAAA,IACnB;AAGA,YAAQ,QAAgB;AAAA,EAC1B;AACF;AA2BO,SAAS,qBAKd,SAA4D;AAC5D,QAAM,eAAW,qCAAY;AAE7B,8BAAU,MAAM;AAOd,UAAM,uBAAuB,YAAY;AACvC,YAAM,aAAa,cAAc,UAAU,QAAQ,aAAa;AAEhE,UAAI,CAAC,mBAAmB,UAAU,GAAG;AACnC;AAAA,MACF;AAEA,UAAI;AACF,gBAAQ,UAAU;AAAA,UAChB,OAAO,WAAW;AAAA,UAClB,cAAc,WAAW;AAAA,QAC3B,CAAW;AAEX,cAAM,WAAY,MAAM,QAAQ,IAAI,IAAI,QAAQ,UAAU;AAAA,UACxD,SAAS;AAAA,YACP,eAAe,UAAU,WAAW,KAAK;AAAA,UAC3C;AAAA,QACF,CAAC;AAED,gBAAQ,eAAe,SAAS,KAAK,IAAe;AACpD,+BAAuB,SAAS,KAAK,MAAM,QAAQ,kBAAkB;AACrE,uBAAe,SAAS,KAAK,MAAM,QAAQ,OAAO;AAClD,gBAAQ,qBAAqB;AAAA,MAC/B,SAAS,OAAO;AACd,gBAAQ,MAAM,iDAAwC,KAAK;AAAA,MAC7D;AAAA,IACF;AAEA,yBAAqB;AAAA,EACvB,GAAG;AAAA,IACD,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AACH;","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 */\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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkC;AAClC,8BAA4B;AAyD5B,IAAM,gBAAgB,CACpB,UACA,kBAKG;AACH,QAAM,eAAe,IAAI,gBAAgB,SAAS,MAAM;AACxD,SAAO,gBACH,cAAc,YAAY,IAC1B;AAAA,IACE,WAAW,aAAa,IAAI,WAAW;AAAA,IACvC,OAAO,aAAa,IAAI,OAAO;AAAA,IAC/B,cAAc,aAAa,IAAI,cAAc;AAAA,EAC/C;AACN;AAaA,IAAM,qBAAqB,CAAC,eAItB;AACJ,SAAO,CAAC,EACN,YAAY,aACZ,YAAY,SACZ,YAAY;AAEhB;AAUA,IAAM,sBAAsB,CAC1B,SACoC;AACpC,SAAO,SAAS,QAAQ,OAAO,SAAS,YAAY,SAAS;AAC/D;AAYA,IAAM,yBAAyB,CAC7B,cACA,uBACG;AACH,MAAI,CAAC,mBAAoB;AACzB,MAAI,CAAC,oBAAoB,YAAY,EAAG;AAExC,QAAM,YAAY,aAAa;AAC/B,QAAM,mBAAmB,cAAc,QAAQ,cAAc;AAE7D,MAAI,kBAAkB;AACpB,uBAAmB;AAAA,MACjB,IAAI;AAAA,IACN,CAAY;AAAA,EACd;AACF;AAYA,IAAM,iBAAiB,CACrB,cACA,YACG;AACH,MAAI,CAAC,QAAS;AACd,MAAI,CAAC,oBAAoB,YAAY,EAAG;AAGxC,QAAM,SAAS,aAAa;AAC5B,QAAM,WAAW,aAAa;AAC9B,QAAM,YAAY,aAAa;AAE/B,MAAI,QAAQ;AACV,UAAM,WAAoC;AAAA,MACxC,IAAI;AAAA,IACN;AAEA,QAAI,UAAU;AACZ,eAAS,OAAO;AAAA,IAClB;AAEA,QAAI,WAAW;AACb,eAAS,QAAQ;AAAA,IACnB;AAGA,YAAQ,QAAgB;AAAA,EAC1B;AACF;AA2BO,SAAS,qBAKd,SAA4D;AAC5D,QAAM,eAAW,qCAAY;AAC7B,QAAM,mBAAe,qBAAO,KAAK;AAEjC,8BAAU,MAAM;AAMd,UAAM,uBAAuB,YAA2B;AAEtD,UAAI,aAAa,SAAS;AACxB;AAAA,MACF;AAEA,YAAM,aAAa,cAAc,UAAU,QAAQ,aAAa;AAGhE,UAAI,CAAC,mBAAmB,UAAU,GAAG;AACnC;AAAA,MACF;AAGA,mBAAa,UAAU;AAEvB,UAAI;AAEF,gBAAQ,UAAU;AAAA,UAChB,OAAO,WAAW;AAAA,UAClB,cAAc,WAAW;AAAA,QAC3B,CAAW;AAGX,cAAM,aAAa,QAAQ,cAAc;AACzC,cAAM,aAAa,QAAQ,cAAc;AACzC,YAAI,UAAU;AACd,YAAI,cAAc;AAElB,eAAO,UAAU,cAAc,CAAC,aAAa;AAC3C,cAAI;AACF,kBAAM,WAAY,MAAM,QAAQ,IAAI,IAAI,QAAQ,UAAU;AAAA,cACxD,SAAS;AAAA,gBACP,eAAe,UAAU,WAAW,KAAK;AAAA,cAC3C;AAAA,YACF,CAAC;AAED,0BAAc,SAAS,KAAK;AAC5B;AAAA,UACF,SAAS,OAAO;AACd;AACA,oBAAQ;AAAA,cACN,aAAa,OAAO,IAAI,UAAU,gBAAgB,QAAQ,QAAQ;AAAA,cAClE;AAAA,YACF;AAEA,gBAAI,UAAU,YAAY;AAExB,oBAAM,IAAI;AAAA,gBAAQ,CAAC,YACjB,WAAW,SAAS,aAAa,OAAO;AAAA,cAC1C;AAAA,YACF,OAAO;AACL,oBAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAGA,gBAAQ,eAAe,WAAsB;AAC7C,+BAAuB,aAAa,QAAQ,kBAAkB;AAC9D,uBAAe,aAAa,QAAQ,OAAO;AAC3C,gBAAQ,qBAAqB;AAAA,MAC/B,SAAS,OAAO;AACd,gBAAQ,MAAM,iDAAwC,KAAK;AAE3D,qBAAa,UAAU;AAEvB,gBAAQ,UAAU,KAAK;AAAA,MACzB;AAAA,IACF;AAEA,yBAAqB;AAAA,EACvB,GAAG;AAAA,IACD,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AACH;","names":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/components/Auth/useUrlAuthentication.ts
|
|
2
|
-
import { useEffect } from "react";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
3
|
import { useLocation } from "react-router-dom";
|
|
4
4
|
var getAuthParams = (location, extractParams) => {
|
|
5
5
|
const searchParams = new URLSearchParams(location.search);
|
|
@@ -47,28 +47,58 @@ var handleUserData = (responseData, setUser) => {
|
|
|
47
47
|
};
|
|
48
48
|
function useUrlAuthentication(options) {
|
|
49
49
|
const location = useLocation();
|
|
50
|
+
const processedRef = useRef(false);
|
|
50
51
|
useEffect(() => {
|
|
51
52
|
const handleAuthentication = async () => {
|
|
53
|
+
if (processedRef.current) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
52
56
|
const authParams = getAuthParams(location, options.extractParams);
|
|
53
57
|
if (!hasValidAuthParams(authParams)) {
|
|
54
58
|
return;
|
|
55
59
|
}
|
|
60
|
+
processedRef.current = true;
|
|
56
61
|
try {
|
|
57
62
|
options.setTokens({
|
|
58
63
|
token: authParams.token,
|
|
59
64
|
refreshToken: authParams.refreshToken
|
|
60
65
|
});
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
const maxRetries = options.maxRetries || 3;
|
|
67
|
+
const retryDelay = options.retryDelay || 1e3;
|
|
68
|
+
let retries = 0;
|
|
69
|
+
let sessionData = null;
|
|
70
|
+
while (retries < maxRetries && !sessionData) {
|
|
71
|
+
try {
|
|
72
|
+
const response = await options.api.get(options.endpoint, {
|
|
73
|
+
headers: {
|
|
74
|
+
Authorization: `Bearer ${authParams.token}`
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
sessionData = response.data.data;
|
|
78
|
+
break;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
retries++;
|
|
81
|
+
console.warn(
|
|
82
|
+
`Tentativa ${retries}/${maxRetries} falhou para ${options.endpoint}:`,
|
|
83
|
+
error
|
|
84
|
+
);
|
|
85
|
+
if (retries < maxRetries) {
|
|
86
|
+
await new Promise(
|
|
87
|
+
(resolve) => setTimeout(resolve, retryDelay * retries)
|
|
88
|
+
);
|
|
89
|
+
} else {
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
64
92
|
}
|
|
65
|
-
}
|
|
66
|
-
options.setSessionInfo(
|
|
67
|
-
handleProfileSelection(
|
|
68
|
-
handleUserData(
|
|
93
|
+
}
|
|
94
|
+
options.setSessionInfo(sessionData);
|
|
95
|
+
handleProfileSelection(sessionData, options.setSelectedProfile);
|
|
96
|
+
handleUserData(sessionData, options.setUser);
|
|
69
97
|
options.clearParamsFromURL?.();
|
|
70
98
|
} catch (error) {
|
|
71
99
|
console.error("Erro ao obter informa\xE7\xF5es da sess\xE3o:", error);
|
|
100
|
+
processedRef.current = false;
|
|
101
|
+
options.onError?.(error);
|
|
72
102
|
}
|
|
73
103
|
};
|
|
74
104
|
handleAuthentication();
|
|
@@ -81,7 +111,10 @@ function useUrlAuthentication(options) {
|
|
|
81
111
|
options.api,
|
|
82
112
|
options.endpoint,
|
|
83
113
|
options.extractParams,
|
|
84
|
-
options.clearParamsFromURL
|
|
114
|
+
options.clearParamsFromURL,
|
|
115
|
+
options.maxRetries,
|
|
116
|
+
options.retryDelay,
|
|
117
|
+
options.onError
|
|
85
118
|
]);
|
|
86
119
|
}
|
|
87
120
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Auth/useUrlAuthentication.ts"],"sourcesContent":["import { useEffect } 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 */\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}\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\n useEffect(() => {\n /**\n * Main authentication handler that processes URL parameters\n *\n * @returns {Promise<void>}\n * @private\n */\n const handleAuthentication = async () => {\n const authParams = getAuthParams(location, options.extractParams);\n\n if (!hasValidAuthParams(authParams)) {\n return;\n }\n\n try {\n options.setTokens({\n token: authParams.token,\n refreshToken: authParams.refreshToken,\n } as Tokens);\n\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 options.setSessionInfo(response.data.data as Session);\n handleProfileSelection(response.data.data, options.setSelectedProfile);\n handleUserData(response.data.data, options.setUser);\n options.clearParamsFromURL?.();\n } catch (error) {\n console.error('Erro ao obter informações da sessão:', 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 ]);\n}\n"],"mappings":";AAAA,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAmD5B,IAAM,gBAAgB,CACpB,UACA,kBAKG;AACH,QAAM,eAAe,IAAI,gBAAgB,SAAS,MAAM;AACxD,SAAO,gBACH,cAAc,YAAY,IAC1B;AAAA,IACE,WAAW,aAAa,IAAI,WAAW;AAAA,IACvC,OAAO,aAAa,IAAI,OAAO;AAAA,IAC/B,cAAc,aAAa,IAAI,cAAc;AAAA,EAC/C;AACN;AAaA,IAAM,qBAAqB,CAAC,eAItB;AACJ,SAAO,CAAC,EACN,YAAY,aACZ,YAAY,SACZ,YAAY;AAEhB;AAUA,IAAM,sBAAsB,CAC1B,SACoC;AACpC,SAAO,SAAS,QAAQ,OAAO,SAAS,YAAY,SAAS;AAC/D;AAYA,IAAM,yBAAyB,CAC7B,cACA,uBACG;AACH,MAAI,CAAC,mBAAoB;AACzB,MAAI,CAAC,oBAAoB,YAAY,EAAG;AAExC,QAAM,YAAY,aAAa;AAC/B,QAAM,mBAAmB,cAAc,QAAQ,cAAc;AAE7D,MAAI,kBAAkB;AACpB,uBAAmB;AAAA,MACjB,IAAI;AAAA,IACN,CAAY;AAAA,EACd;AACF;AAYA,IAAM,iBAAiB,CACrB,cACA,YACG;AACH,MAAI,CAAC,QAAS;AACd,MAAI,CAAC,oBAAoB,YAAY,EAAG;AAGxC,QAAM,SAAS,aAAa;AAC5B,QAAM,WAAW,aAAa;AAC9B,QAAM,YAAY,aAAa;AAE/B,MAAI,QAAQ;AACV,UAAM,WAAoC;AAAA,MACxC,IAAI;AAAA,IACN;AAEA,QAAI,UAAU;AACZ,eAAS,OAAO;AAAA,IAClB;AAEA,QAAI,WAAW;AACb,eAAS,QAAQ;AAAA,IACnB;AAGA,YAAQ,QAAgB;AAAA,EAC1B;AACF;AA2BO,SAAS,qBAKd,SAA4D;AAC5D,QAAM,WAAW,YAAY;AAE7B,YAAU,MAAM;AAOd,UAAM,uBAAuB,YAAY;AACvC,YAAM,aAAa,cAAc,UAAU,QAAQ,aAAa;AAEhE,UAAI,CAAC,mBAAmB,UAAU,GAAG;AACnC;AAAA,MACF;AAEA,UAAI;AACF,gBAAQ,UAAU;AAAA,UAChB,OAAO,WAAW;AAAA,UAClB,cAAc,WAAW;AAAA,QAC3B,CAAW;AAEX,cAAM,WAAY,MAAM,QAAQ,IAAI,IAAI,QAAQ,UAAU;AAAA,UACxD,SAAS;AAAA,YACP,eAAe,UAAU,WAAW,KAAK;AAAA,UAC3C;AAAA,QACF,CAAC;AAED,gBAAQ,eAAe,SAAS,KAAK,IAAe;AACpD,+BAAuB,SAAS,KAAK,MAAM,QAAQ,kBAAkB;AACrE,uBAAe,SAAS,KAAK,MAAM,QAAQ,OAAO;AAClD,gBAAQ,qBAAqB;AAAA,MAC/B,SAAS,OAAO;AACd,gBAAQ,MAAM,iDAAwC,KAAK;AAAA,MAC7D;AAAA,IACF;AAEA,yBAAqB;AAAA,EACvB,GAAG;AAAA,IACD,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AACH;","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 */\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":[]}
|
package/dist/index.js
CHANGED
|
@@ -7948,28 +7948,58 @@ var handleUserData = (responseData, setUser) => {
|
|
|
7948
7948
|
};
|
|
7949
7949
|
function useUrlAuthentication(options) {
|
|
7950
7950
|
const location = (0, import_react_router_dom2.useLocation)();
|
|
7951
|
+
const processedRef = (0, import_react26.useRef)(false);
|
|
7951
7952
|
(0, import_react26.useEffect)(() => {
|
|
7952
7953
|
const handleAuthentication = async () => {
|
|
7954
|
+
if (processedRef.current) {
|
|
7955
|
+
return;
|
|
7956
|
+
}
|
|
7953
7957
|
const authParams = getAuthParams(location, options.extractParams);
|
|
7954
7958
|
if (!hasValidAuthParams(authParams)) {
|
|
7955
7959
|
return;
|
|
7956
7960
|
}
|
|
7961
|
+
processedRef.current = true;
|
|
7957
7962
|
try {
|
|
7958
7963
|
options.setTokens({
|
|
7959
7964
|
token: authParams.token,
|
|
7960
7965
|
refreshToken: authParams.refreshToken
|
|
7961
7966
|
});
|
|
7962
|
-
const
|
|
7963
|
-
|
|
7964
|
-
|
|
7967
|
+
const maxRetries = options.maxRetries || 3;
|
|
7968
|
+
const retryDelay = options.retryDelay || 1e3;
|
|
7969
|
+
let retries = 0;
|
|
7970
|
+
let sessionData = null;
|
|
7971
|
+
while (retries < maxRetries && !sessionData) {
|
|
7972
|
+
try {
|
|
7973
|
+
const response = await options.api.get(options.endpoint, {
|
|
7974
|
+
headers: {
|
|
7975
|
+
Authorization: `Bearer ${authParams.token}`
|
|
7976
|
+
}
|
|
7977
|
+
});
|
|
7978
|
+
sessionData = response.data.data;
|
|
7979
|
+
break;
|
|
7980
|
+
} catch (error) {
|
|
7981
|
+
retries++;
|
|
7982
|
+
console.warn(
|
|
7983
|
+
`Tentativa ${retries}/${maxRetries} falhou para ${options.endpoint}:`,
|
|
7984
|
+
error
|
|
7985
|
+
);
|
|
7986
|
+
if (retries < maxRetries) {
|
|
7987
|
+
await new Promise(
|
|
7988
|
+
(resolve) => setTimeout(resolve, retryDelay * retries)
|
|
7989
|
+
);
|
|
7990
|
+
} else {
|
|
7991
|
+
throw error;
|
|
7992
|
+
}
|
|
7965
7993
|
}
|
|
7966
|
-
}
|
|
7967
|
-
options.setSessionInfo(
|
|
7968
|
-
handleProfileSelection(
|
|
7969
|
-
handleUserData(
|
|
7994
|
+
}
|
|
7995
|
+
options.setSessionInfo(sessionData);
|
|
7996
|
+
handleProfileSelection(sessionData, options.setSelectedProfile);
|
|
7997
|
+
handleUserData(sessionData, options.setUser);
|
|
7970
7998
|
options.clearParamsFromURL?.();
|
|
7971
7999
|
} catch (error) {
|
|
7972
8000
|
console.error("Erro ao obter informa\xE7\xF5es da sess\xE3o:", error);
|
|
8001
|
+
processedRef.current = false;
|
|
8002
|
+
options.onError?.(error);
|
|
7973
8003
|
}
|
|
7974
8004
|
};
|
|
7975
8005
|
handleAuthentication();
|
|
@@ -7982,7 +8012,10 @@ function useUrlAuthentication(options) {
|
|
|
7982
8012
|
options.api,
|
|
7983
8013
|
options.endpoint,
|
|
7984
8014
|
options.extractParams,
|
|
7985
|
-
options.clearParamsFromURL
|
|
8015
|
+
options.clearParamsFromURL,
|
|
8016
|
+
options.maxRetries,
|
|
8017
|
+
options.retryDelay,
|
|
8018
|
+
options.onError
|
|
7986
8019
|
]);
|
|
7987
8020
|
}
|
|
7988
8021
|
|