@arex95/vue-core 1.1.39 → 1.1.40

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.
@@ -1,23 +1,11 @@
1
- import { AuthParams, AuthResponse, AuthTokenPaths, LocationPreference } from "@/types";
2
- /**
3
- * @typedef {object} AuthHook
4
- * @property {function(): Promise<number | null>} getTokenExpiry - Retrieves the expiration time of the current token in milliseconds.
5
- * @property {function(): Promise<void>} cleanCredentials - Clears authentication credentials from storage.
6
- * @property {(params?: AuthParams) => Promise<void>} logout - Logs out the user, clears credentials, and reloads the page.
7
- * @property {(params: AuthParams, persistence: SessionPreference, tokenPaths?: AuthTokenPaths) => Promise<AuthResponse>} login - Logs in the user and stores tokens.
8
- * @property {(tokenPaths?: AuthTokenPaths) => Promise<AuthResponse>} refresh - Refreshes authentication tokens.
9
- * @property {function(): Promise<boolean>} verifyAuth - Verifies the validity and expiration of the current authentication token.
10
- * @property {(preference: SessionPreference) => void} setSessionPersistencePreference - Sets the user's preferred storage for authentication data.
11
- * @property {function(): SessionPreference} getSessionPersistence - Retrieves the user's current preferred storage for authentication data.
12
- */
1
+ import { AuthResponse, AuthTokenPaths, LocationPreference } from "@/types";
13
2
  /**
14
3
  * Custom hook for authentication logic, including login, logout, token management, and session preference.
15
4
  *
16
5
  * @param {string} secretKey - The secret key used for token encryption/decryption.
17
6
  * @returns {AuthHook} An object containing authentication functions.
18
7
  */
19
- export declare function useAuth(secretKey?: string): {
20
- logout: (params?: AuthParams) => Promise<void>;
21
- login: (params: AuthParams, persistence: LocationPreference, tokenPaths?: AuthTokenPaths) => Promise<AuthResponse>;
22
- refresh: (tokenPaths?: AuthTokenPaths) => Promise<AuthResponse>;
8
+ export declare function useAuth(): {
9
+ logout: (params?: any) => Promise<void>;
10
+ login: (params: any | undefined, persistence: LocationPreference, tokenPaths?: AuthTokenPaths) => Promise<AuthResponse>;
23
11
  };
@@ -10,13 +10,11 @@ export declare class AxiosService {
10
10
  private cancelTokenSource;
11
11
  private activeRequests;
12
12
  private readonly refreshTokenUrl;
13
- private readonly auth;
14
13
  private isRefreshing;
15
14
  private failedQueue;
16
15
  constructor(options: AxiosServiceOptions);
17
16
  private processQueue;
18
17
  private setAuthHeader;
19
- private getLatestAuthToken;
20
18
  private initializeInterceptors;
21
19
  getActiveRequests(): number;
22
20
  getAxiosInstance(): AxiosInstance;
@@ -1,41 +1,4 @@
1
+ import { AxiosServiceOptions } from "@/types/AxiosServiceOptions";
1
2
  import { AxiosInstance } from "axios";
2
- /**
3
- * Configuration object for the Axios instance.
4
- */
5
- interface AxiosConfig {
6
- baseURL: string;
7
- }
8
- /**
9
- * Configuration object for a custom Axios instance.
10
- */
11
- interface CustomAxiosConfig {
12
- baseURL: string;
13
- headers?: Record<string, string>;
14
- }
15
- /**
16
- * Configures the global Axios instance with a base URL.
17
- *
18
- * @param {AxiosConfig} config - An object containing the base URL for the Axios instance.
19
- * @param {string} config.baseURL - The base URL for the Axios instance.
20
- *
21
- * @returns {void}
22
- */
23
- export declare const configAxios: (config: AxiosConfig) => void;
24
- /**
25
- * Retrieves the configured Axios instance.
26
- *
27
- * @returns {AxiosService} The configured Axios instance.
28
- * @throws Will throw an error if the Axios instance is not configured.
29
- */
30
- export declare const getAxiosInstance: () => AxiosInstance;
31
- /**
32
- * Creates a new AxiosService instance with custom headers.
33
- *
34
- * @param {CustomAxiosConfig} config - An object containing the base URL and optional custom headers.
35
- * @param {string} config.baseURL - The base URL for the Axios instance.
36
- * @param {Record<string, string>} [config.headers] - Custom headers to set (optional).
37
- *
38
- * @returns {AxiosService} The new AxiosService instance.
39
- */
40
- export declare const createCustomAxiosInstance: (config: CustomAxiosConfig) => AxiosInstance;
41
- export {};
3
+ export declare const configAxios: (config: AxiosServiceOptions) => void;
4
+ export declare const getConfiguredAxiosInstance: () => AxiosInstance;
@@ -2,3 +2,4 @@ export * from './tokensConfig';
2
2
  export * from './endpointsConfig';
3
3
  export * from './sessionConfig';
4
4
  export * from './keyConfig';
5
+ export * from './tokenPathsConfig';
@@ -0,0 +1,36 @@
1
+ interface TokenPathsConfig {
2
+ accessTokenPath?: string;
3
+ refreshTokenPath?: string;
4
+ }
5
+ /**
6
+ * Configures the paths for access and refresh tokens in the authentication response.
7
+ * This function freezes the object to prevent further modifications.
8
+ *
9
+ * @param {TokenPathsConfig} config - An object containing the paths for access and refresh tokens.
10
+ * @param {string} [config.accessTokenPath="data.access_token"] - Path to the access token in the response.
11
+ * @param {string} [config.refreshTokenPath="data.refresh_token"] - Path to the refresh token in the response.
12
+ *
13
+ * @returns {void} Does not return anything but freezes the token paths configuration object.
14
+ */
15
+ export declare function configTokenPaths(config: TokenPathsConfig): void;
16
+ /**
17
+ * Configures the paths for access and refresh tokens in the refresh response.
18
+ * This function freezes the object to prevent further modifications.
19
+ *
20
+ * @param {TokenPathsConfig} config - An object containing the paths for access and refresh tokens.
21
+ * @param {string} [config.accessTokenPath="data.access_token"] - Path to the access token in the response.
22
+ * @param {string} [config.refreshTokenPath="data.refresh_token"] - Path to the refresh token in the response.
23
+ *
24
+ * @returns {void} Does not return anything but freezes the refresh token paths configuration object.
25
+ */
26
+ export declare function configRefreshTokenPaths(config: TokenPathsConfig): void;
27
+ /**
28
+ * Retrieves the configured authentication token paths.
29
+ *
30
+ * @returns {AuthTokenPaths} An object containing the configured authentication token paths.
31
+ * @property {string} accessTokenPath - Path to the access token in the response.
32
+ * @property {string} refreshTokenPath - Path to the refresh token in the response.
33
+ */
34
+ export declare function getTokenPathsConfig(): TokenPathsConfig;
35
+ export declare function getRefreshTokenPathsConfig(): TokenPathsConfig;
36
+ export {};
package/dist/index.d.ts CHANGED
@@ -20,3 +20,4 @@ export * from "./config";
20
20
  export * from "./enums";
21
21
  export * from "./types";
22
22
  export * from "./utils";
23
+ export * from "./services";
package/dist/index.mjs CHANGED
@@ -881,6 +881,60 @@ async function getSessionConfig() {
881
881
  return _sessionConfig;
882
882
  }
883
883
 
884
+ let tokenPathsConfig = {
885
+ accessTokenPath: "data.access_token",
886
+ refreshTokenPath: "data.refresh_token",
887
+ };
888
+ let refreshTokenPathsConfig = {
889
+ accessTokenPath: "data.access_token",
890
+ refreshTokenPath: "data.refresh_token",
891
+ };
892
+ /**
893
+ * Configures the paths for access and refresh tokens in the authentication response.
894
+ * This function freezes the object to prevent further modifications.
895
+ *
896
+ * @param {TokenPathsConfig} config - An object containing the paths for access and refresh tokens.
897
+ * @param {string} [config.accessTokenPath="data.access_token"] - Path to the access token in the response.
898
+ * @param {string} [config.refreshTokenPath="data.refresh_token"] - Path to the refresh token in the response.
899
+ *
900
+ * @returns {void} Does not return anything but freezes the token paths configuration object.
901
+ */
902
+ function configTokenPaths(config) {
903
+ tokenPathsConfig = Object.freeze({
904
+ accessTokenPath: config.accessTokenPath || "data.access_token",
905
+ refreshTokenPath: config.refreshTokenPath || "data.refresh_token",
906
+ });
907
+ }
908
+ /**
909
+ * Configures the paths for access and refresh tokens in the refresh response.
910
+ * This function freezes the object to prevent further modifications.
911
+ *
912
+ * @param {TokenPathsConfig} config - An object containing the paths for access and refresh tokens.
913
+ * @param {string} [config.accessTokenPath="data.access_token"] - Path to the access token in the response.
914
+ * @param {string} [config.refreshTokenPath="data.refresh_token"] - Path to the refresh token in the response.
915
+ *
916
+ * @returns {void} Does not return anything but freezes the refresh token paths configuration object.
917
+ */
918
+ function configRefreshTokenPaths(config) {
919
+ refreshTokenPathsConfig = Object.freeze({
920
+ accessTokenPath: config.accessTokenPath || "data.access_token",
921
+ refreshTokenPath: config.refreshTokenPath || "data.refresh_token",
922
+ });
923
+ }
924
+ /**
925
+ * Retrieves the configured authentication token paths.
926
+ *
927
+ * @returns {AuthTokenPaths} An object containing the configured authentication token paths.
928
+ * @property {string} accessTokenPath - Path to the access token in the response.
929
+ * @property {string} refreshTokenPath - Path to the refresh token in the response.
930
+ */
931
+ function getTokenPathsConfig() {
932
+ return tokenPathsConfig;
933
+ }
934
+ function getRefreshTokenPathsConfig() {
935
+ return refreshTokenPathsConfig;
936
+ }
937
+
884
938
  /**
885
939
  * Clears all stored authentication data (access and refresh tokens)
886
940
  * from either sessionStorage, localStorage, or both based on the provided location preference.
@@ -993,48 +1047,6 @@ const verifyAuth = async () => {
993
1047
  }
994
1048
  };
995
1049
 
996
- let axiosInstance;
997
- /**
998
- * Configures the global Axios instance with a base URL.
999
- *
1000
- * @param {AxiosConfig} config - An object containing the base URL for the Axios instance.
1001
- * @param {string} config.baseURL - The base URL for the Axios instance.
1002
- *
1003
- * @returns {void}
1004
- */
1005
- const configAxios = (config) => {
1006
- axiosInstance = new AxiosService({
1007
- baseURL: config.baseURL,
1008
- });
1009
- };
1010
- /**
1011
- * Retrieves the configured Axios instance.
1012
- *
1013
- * @returns {AxiosService} The configured Axios instance.
1014
- * @throws Will throw an error if the Axios instance is not configured.
1015
- */
1016
- const getAxiosInstance = () => {
1017
- if (!axiosInstance) {
1018
- throw new Error("Axios instance not configured. Call configAxios first.");
1019
- }
1020
- return axiosInstance.getAxiosInstance();
1021
- };
1022
- /**
1023
- * Creates a new AxiosService instance with custom headers.
1024
- *
1025
- * @param {CustomAxiosConfig} config - An object containing the base URL and optional custom headers.
1026
- * @param {string} config.baseURL - The base URL for the Axios instance.
1027
- * @param {Record<string, string>} [config.headers] - Custom headers to set (optional).
1028
- *
1029
- * @returns {AxiosService} The new AxiosService instance.
1030
- */
1031
- const createCustomAxiosInstance = (config) => {
1032
- return new AxiosService({
1033
- baseURL: config.baseURL,
1034
- headers: config.headers,
1035
- }).getAxiosInstance();
1036
- };
1037
-
1038
1050
  /**
1039
1051
  * Converts a Proxy object to a plain object.
1040
1052
  * @param {ProxyConstructor} proxy The Proxy object to convert.
@@ -1317,142 +1329,83 @@ function flattenObject(obj, parentKey = '', result = {}) {
1317
1329
  // flattenObject({ a: 1, b: { c: 2, d: { e: 3 } } }); // { 'a': 1, 'b.c': 2, 'b.d.e': 3 }
1318
1330
 
1319
1331
  /**
1320
- * @typedef {object} AuthHook
1321
- * @property {function(): Promise<number | null>} getTokenExpiry - Retrieves the expiration time of the current token in milliseconds.
1322
- * @property {function(): Promise<void>} cleanCredentials - Clears authentication credentials from storage.
1323
- * @property {(params?: AuthParams) => Promise<void>} logout - Logs out the user, clears credentials, and reloads the page.
1324
- * @property {(params: AuthParams, persistence: SessionPreference, tokenPaths?: AuthTokenPaths) => Promise<AuthResponse>} login - Logs in the user and stores tokens.
1325
- * @property {(tokenPaths?: AuthTokenPaths) => Promise<AuthResponse>} refresh - Refreshes authentication tokens.
1326
- * @property {function(): Promise<boolean>} verifyAuth - Verifies the validity and expiration of the current authentication token.
1327
- * @property {(preference: SessionPreference) => void} setSessionPersistencePreference - Sets the user's preferred storage for authentication data.
1328
- * @property {function(): SessionPreference} getSessionPersistence - Retrieves the user's current preferred storage for authentication data.
1329
- */
1330
- /**
1331
- * Custom hook for authentication logic, including login, logout, token management, and session preference.
1332
+ * Extracts and validates the access and refresh tokens from a response object.
1333
+ * Throws an error if the tokens are not found or are invalid.
1332
1334
  *
1333
- * @param {string} secretKey - The secret key used for token encryption/decryption.
1334
- * @returns {AuthHook} An object containing authentication functions.
1335
- */
1336
- function useAuth(secretKey = getAppKey()) {
1337
- const axiosInstance = getAxiosInstance();
1335
+ * @param {any} data - The API response object.
1336
+ * @param {AuthTokenPaths} tokenPaths - The paths for the tokens.
1337
+ * @param {string} errorSource - A prefix for the error message ("LOGIN" or "REFRESH").
1338
+ * @returns {TokenValidationResult} An object with the validated tokens.
1339
+ */
1340
+ const extractAndValidateTokens = (data, tokenPaths, errorSource) => {
1341
+ const accessTokenPath = tokenPaths?.accessTokenPath || "access_token";
1342
+ const refreshTokenPath = tokenPaths?.refreshTokenPath || "refresh_token";
1343
+ if (!data) {
1344
+ throw new Error(`${errorSource}_ERROR: No data received.`);
1345
+ }
1346
+ const accessToken = safeGet(data, accessTokenPath.split("."));
1347
+ const refreshToken = safeGet(data, refreshTokenPath.split("."));
1348
+ if (!accessToken || typeof accessToken !== "string") {
1349
+ throw new Error(`${errorSource}_ERROR: Access token not found or invalid at path '${accessTokenPath}' in response.`);
1350
+ }
1351
+ if (!refreshToken || typeof refreshToken !== "string") {
1352
+ throw new Error(`${errorSource}_ERROR: Refresh token not found or invalid at path '${refreshTokenPath}' in response.`);
1353
+ }
1354
+ return { accessToken, refreshToken };
1355
+ };
1356
+
1357
+ /**
1358
+ * Stores the access and refresh tokens in the appropriate storage based on the user's preference.
1359
+ *
1360
+ * @param {string} accessToken - El token de acceso.
1361
+ * @param {string} refreshToken - El token de refresco.
1362
+ * @param {LocationPreference} persistence - La preferencia de almacenamiento.
1363
+ */
1364
+ const storeTokens = async (accessToken, refreshToken, persistence) => {
1365
+ await storeAuthToken(accessToken, getAppKey(), persistence);
1366
+ await storeAuthRefreshToken(refreshToken, getAppKey(), persistence);
1367
+ };
1368
+
1369
+ /**
1370
+ * Refreshes the authentication tokens using the stored refresh token.
1371
+ * This function can also accept optional token paths if the refresh endpoint
1372
+ * returns tokens with a different structure than the default login.
1373
+ * If no refresh token is found, it throws an error and initiates a logout.
1374
+ *
1375
+ * @param {AuthTokenPaths} [tokenPaths] - Optional configuration for the paths (in dot notation) of the access and refresh tokens in the refresh endpoint response.
1376
+ * @returns {Promise<AuthResponse>} The new authentication response with refreshed tokens.
1377
+ * @throws {Error} If the refresh token is missing or the refresh request fails.
1378
+ */
1379
+ const refreshTokens = async (axiosInstance) => {
1380
+ const tokenPaths = getRefreshTokenPathsConfig();
1338
1381
  const endpoints = getEndpointsConfig();
1339
- /**
1340
- * Logs out the user by making a POST request to the logout endpoint,
1341
- * cleaning all stored credentials, and reloading the page.
1342
- * The session persistence preference is NOT reset here; it persists across logouts.
1343
- *
1344
- * @param {AuthParams} [params={}] - Optional parameters to send with the logout request.
1345
- * @returns {Promise<void>}
1346
- */
1347
- const logout = async (params = {}) => {
1348
- try {
1349
- await axiosInstance.post(endpoints.LOGOUT, params);
1350
- }
1351
- catch (error) {
1352
- handleError(error, false);
1382
+ const secretKey = getAppKey();
1383
+ const persistence = await getSessionPersistence();
1384
+ try {
1385
+ const refreshTokenFromStorage = await getAuthRefreshToken(secretKey, "any");
1386
+ if (!refreshTokenFromStorage) {
1387
+ throw new Error("TOKEN_MISSING: No refresh token found in storage.");
1353
1388
  }
1354
- finally {
1355
- await cleanCredentials(await getSessionPersistence());
1389
+ const { data } = await axiosInstance.post(endpoints.REFRESH);
1390
+ const { accessToken, refreshToken } = extractAndValidateTokens(data, tokenPaths, "REFRESH");
1391
+ await storeTokens(accessToken, refreshToken, persistence);
1392
+ return data;
1393
+ }
1394
+ catch (error) {
1395
+ handleError(error, false);
1396
+ await cleanCredentials(persistence);
1397
+ if (window) {
1356
1398
  window.location.reload();
1357
1399
  }
1358
- };
1359
- /**
1360
- * Authenticates the user by making a POST request to the login endpoint,
1361
- * stores the received access and refresh tokens, and sets the session persistence preference.
1362
- *
1363
- * @param {AuthParams} params - The authentication parameters (e.g., username, password).
1364
- * @param {SessionPreference} persistence - The storage preference: 'local' for localStorage, 'session' for sessionStorage.
1365
- * @param {AuthTokenPaths} [tokenPaths] - Configuración opcional para las rutas (en notación de punto) donde se encuentran los tokens en la respuesta de la API.
1366
- * @returns {Promise<AuthResponse>} La respuesta de autenticación que contiene los tokens e información del usuario.
1367
- * @throws {Error} Si la solicitud de login falla, o si los tokens de acceso/refresco no se encuentran o no son válidos en la respuesta.
1368
- */
1369
- const login = async (params, persistence, tokenPaths) => {
1370
- try {
1371
- const { data } = await axiosInstance.post(endpoints.LOGIN, params);
1372
- const accessTokenPath = tokenPaths?.accessTokenPath || "access_token";
1373
- const refreshTokenPath = tokenPaths?.refreshTokenPath || "refresh_token";
1374
- const accessTokenPathArray = accessTokenPath.split(".");
1375
- const refreshTokenPathArray = refreshTokenPath.split(".");
1376
- if (!data) {
1377
- throw new Error("LOGIN_ERROR: No data received from login endpoint.");
1378
- }
1379
- const accessToken = safeGet(data, accessTokenPathArray);
1380
- const refreshToken = safeGet(data, refreshTokenPathArray);
1381
- if (!accessToken || typeof accessToken !== "string") {
1382
- throw new Error(`LOGIN_ERROR: Access token not found or invalid at path '${accessTokenPath}' in response.`);
1383
- }
1384
- if (!refreshToken || typeof refreshToken !== "string") {
1385
- throw new Error(`LOGIN_ERROR: Refresh token not found or invalid at path '${refreshTokenPath}' in response.`);
1386
- }
1387
- configSession({
1388
- persistencePreference: persistence,
1389
- });
1390
- await storeAuthToken(accessToken, secretKey, persistence);
1391
- await storeAuthRefreshToken(refreshToken, secretKey, persistence);
1392
- return data;
1393
- }
1394
- catch (error) {
1395
- handleError(error, false);
1396
- throw error;
1397
- }
1398
- };
1399
- /**
1400
- * Refreshes the authentication tokens using the stored refresh token.
1401
- * This function can also accept optional token paths if the refresh endpoint
1402
- * returns tokens with a different structure than the default login.
1403
- * If no refresh token is found, it throws an error and initiates a logout.
1404
- *
1405
- * @param {AuthTokenPaths} [tokenPaths] - Configuración opcional para las rutas (en notación de punto) de los tokens de acceso y refresco en la respuesta del endpoint de refresco.
1406
- * @returns {Promise<AuthResponse>} The new authentication response with refreshed tokens.
1407
- * @throws {Error} If the refresh token is missing or the refresh request fails.
1408
- */
1409
- const refresh = async (tokenPaths) => {
1410
- try {
1411
- const refreshTokenFromStorage = await getAuthRefreshToken(secretKey, 'any');
1412
- if (!refreshTokenFromStorage) {
1413
- throw new Error("TOKEN_MISSING: No refresh token found in storage.");
1414
- }
1415
- const { data } = await axiosInstance.post(endpoints.REFRESH, { refresh_token: refreshTokenFromStorage });
1416
- const accessTokenPath = tokenPaths?.accessTokenPath || "access_token";
1417
- const refreshTokenPath = tokenPaths?.refreshTokenPath || "refresh_token";
1418
- const accessTokenPathArray = accessTokenPath.split(".");
1419
- const refreshTokenPathArray = refreshTokenPath.split(".");
1420
- if (!data) {
1421
- throw new Error("REFRESH_ERROR: No data received from refresh endpoint.");
1422
- }
1423
- const accessTokenAfterRefresh = safeGet(data, accessTokenPathArray);
1424
- const refreshTokenAfterRefresh = safeGet(data, refreshTokenPathArray);
1425
- if (!accessTokenAfterRefresh ||
1426
- typeof accessTokenAfterRefresh !== "string") {
1427
- throw new Error(`REFRESH_ERROR: Access token not found or invalid at path '${accessTokenPath}' in refresh response.`);
1428
- }
1429
- if (!refreshTokenAfterRefresh ||
1430
- typeof refreshTokenAfterRefresh !== "string") {
1431
- throw new Error(`REFRESH_ERROR: Refresh token not found or invalid at path '${refreshTokenPath}' in refresh response.`);
1432
- }
1433
- await storeAuthToken(accessTokenAfterRefresh, secretKey, await getSessionPersistence());
1434
- await storeAuthRefreshToken(refreshTokenAfterRefresh, secretKey, await getSessionPersistence());
1435
- return data;
1436
- }
1437
- catch (error) {
1438
- handleError(error, false);
1439
- await logout();
1440
- throw error;
1441
- }
1442
- };
1443
- return {
1444
- logout,
1445
- login,
1446
- refresh,
1447
- };
1448
- }
1400
+ throw error;
1401
+ }
1402
+ };
1449
1403
 
1450
1404
  class AxiosService {
1451
1405
  instance;
1452
1406
  cancelTokenSource;
1453
1407
  activeRequests = 0;
1454
1408
  refreshTokenUrl;
1455
- auth = useAuth();
1456
1409
  isRefreshing = false;
1457
1410
  failedQueue = [];
1458
1411
  constructor(options) {
@@ -1487,12 +1440,9 @@ class AxiosService {
1487
1440
  config.headers.Authorization = `Bearer ${token}`;
1488
1441
  }
1489
1442
  }
1490
- async getLatestAuthToken() {
1491
- return await getAuthToken(getAppKey(), "any");
1492
- }
1493
1443
  initializeInterceptors() {
1494
1444
  this.instance.interceptors.request.use(async (config) => {
1495
- const token = await this.getLatestAuthToken();
1445
+ const token = await getAuthToken(getAppKey(), "any");
1496
1446
  if (token) {
1497
1447
  this.setAuthHeader(config, token);
1498
1448
  }
@@ -1535,8 +1485,8 @@ class AxiosService {
1535
1485
  this.isRefreshing = true;
1536
1486
  originalRequest._retry = true;
1537
1487
  try {
1538
- await this.auth.refresh();
1539
- const newToken = await this.getLatestAuthToken();
1488
+ await refreshTokens(this.instance);
1489
+ const newToken = await getAuthToken(getAppKey(), "any");
1540
1490
  if (newToken) {
1541
1491
  this.processQueue(null, newToken);
1542
1492
  this.setAuthHeader(originalRequest, newToken);
@@ -1575,6 +1525,22 @@ class AxiosService {
1575
1525
  }
1576
1526
  }
1577
1527
 
1528
+ let axiosServiceInstance;
1529
+ const configAxios = (config) => {
1530
+ axiosServiceInstance = new AxiosService({
1531
+ baseURL: config.baseURL,
1532
+ headers: config.headers,
1533
+ timeout: config.timeout,
1534
+ withCredentials: config.withCredentials
1535
+ });
1536
+ };
1537
+ const getConfiguredAxiosInstance = () => {
1538
+ if (!axiosServiceInstance) {
1539
+ throw new Error("Axios instance not configured. Call configAxios first.");
1540
+ }
1541
+ return axiosServiceInstance.getAxiosInstance();
1542
+ };
1543
+
1578
1544
  /**
1579
1545
  * Creates and downloads a file from Blob data.
1580
1546
  * @param {Blob} blob The Blob containing the file data.
@@ -3147,7 +3113,7 @@ async function axiosFetch(axios, axiosRequest) {
3147
3113
  * @returns A function that handles the request using the provided composable.
3148
3114
  */
3149
3115
  function createFetch(fetchComposable, axiosCustomInstance) {
3150
- const instance = axiosCustomInstance || getAxiosInstance();
3116
+ const instance = axiosCustomInstance || getConfiguredAxiosInstance();
3151
3117
  return (axiosRequestConfig, options) => {
3152
3118
  return fetchComposable(instance, axiosRequestConfig, options);
3153
3119
  };
@@ -3507,6 +3473,66 @@ function useSorter(items, criteriaList, selectedCriteria) {
3507
3473
  }).value;
3508
3474
  }
3509
3475
 
3476
+ /**
3477
+ * Custom hook for authentication logic, including login, logout, token management, and session preference.
3478
+ *
3479
+ * @param {string} secretKey - The secret key used for token encryption/decryption.
3480
+ * @returns {AuthHook} An object containing authentication functions.
3481
+ */
3482
+ function useAuth() {
3483
+ const axiosInstance = getConfiguredAxiosInstance();
3484
+ const endpoints = getEndpointsConfig();
3485
+ /**
3486
+ * Logs out the user by making a POST request to the logout endpoint,
3487
+ * cleaning all stored credentials, and reloading the page.
3488
+ * The session persistence preference is NOT reset here; it persists across logouts.
3489
+ *
3490
+ * @param {AuthParams} [params={}] - Optional parameters to send with the logout request.
3491
+ * @returns {Promise<void>}
3492
+ */
3493
+ const logout = async (params = {}) => {
3494
+ try {
3495
+ await axiosInstance.post(endpoints.LOGOUT, params);
3496
+ }
3497
+ catch (error) {
3498
+ handleError(error, false);
3499
+ }
3500
+ finally {
3501
+ await cleanCredentials(await getSessionPersistence());
3502
+ window.location.reload();
3503
+ }
3504
+ };
3505
+ /**
3506
+ * Authenticates the user by making a POST request to the login endpoint,
3507
+ * stores the received access and refresh tokens, and sets the session persistence preference.
3508
+ *
3509
+ * @param {AuthParams} params - The authentication parameters (e.g., username, password).
3510
+ * @param {LocationPreference} persistence - The storage preference: 'local' for localStorage, 'session' for sessionStorage.
3511
+ * @param {AuthTokenPaths} [tokenPaths] - Optional configuration for the paths (in dot notation) where the tokens are located in the API response.
3512
+ * @returns {Promise<AuthResponse>} The authentication response containing the tokens and user information.
3513
+ * @throws {Error} If the login request fails, or if the access/refresh tokens are not found or are invalid in the response.
3514
+ */
3515
+ const login = async (params = {}, persistence, tokenPaths = getTokenPathsConfig()) => {
3516
+ try {
3517
+ const { data } = await axiosInstance.post(endpoints.LOGIN, params);
3518
+ const { accessToken, refreshToken } = extractAndValidateTokens(data, tokenPaths, "LOGIN");
3519
+ configSession({
3520
+ persistencePreference: persistence,
3521
+ });
3522
+ await storeTokens(accessToken, refreshToken, persistence);
3523
+ return data;
3524
+ }
3525
+ catch (error) {
3526
+ handleError(error, false);
3527
+ throw error;
3528
+ }
3529
+ };
3530
+ return {
3531
+ logout,
3532
+ login
3533
+ };
3534
+ }
3535
+
3510
3536
  /**
3511
3537
  * The Vue plugin for @arex95/vue-core.
3512
3538
  * Configures the core functionalities for authentication and API communication.
@@ -3529,17 +3555,28 @@ const ArexVueCore = {
3529
3555
  });
3530
3556
  configTokenKeys({
3531
3557
  accessTokenKey: options.tokenKeys.accessToken,
3532
- refreshTokenKey: options.tokenKeys.refreshToken
3558
+ refreshTokenKey: options.tokenKeys.refreshToken,
3533
3559
  });
3534
3560
  configEndpoints({
3535
3561
  loginEndpoint: options.endpoints.login,
3536
3562
  refreshEndpoint: options.endpoints.refresh,
3537
3563
  logoutEndpoint: options.endpoints.logout,
3538
3564
  });
3565
+ configTokenPaths({
3566
+ accessTokenPath: options.tokenPaths.accessToken,
3567
+ refreshTokenPath: options.tokenPaths.refreshToken,
3568
+ });
3569
+ configRefreshTokenPaths({
3570
+ accessTokenPath: options.refreshTokenPaths.accessToken,
3571
+ refreshTokenPath: options.refreshTokenPaths.refreshToken,
3572
+ });
3539
3573
  configAxios({
3540
- baseURL: options.apiUrl,
3574
+ baseURL: options.axios.baseURL,
3575
+ headers: options.axios.headers,
3576
+ timeout: options.axios.timeout,
3577
+ withCredentials: options.axios.withCredentials
3541
3578
  });
3542
3579
  },
3543
3580
  };
3544
3581
 
3545
- export { AppTypes, ArchiveTypes, ArexVueCore, AudioTypes, AxiosService, ContentTypeEnum, DocumentTypes, ERROR_MESSAGES, ERROR_STYLES, ErrorEnum, ErrorMessages, ErrorStyles, ExceptionEnum, FontTypes, ImageTypes, KeyCodeEnum, OtherTypes, RestStd, ScreenBreakpoint, ScreenSize, StorageKeyEnum, StorageTypeEnum, TextTypes, VideoTypes, ab2hex, addCustomKeyboardShortcut, addDays, addDoubleClickListener, addKeyListener, ageAtDate, axiosFetch, blobToFormData, bufferToBlob, calculateAge, cleanCredentials, clickOutside, compareObject, configAppKey, configAxios, configEndpoints, configSession, configTokenKeys, copyToClipboard, countWords, createCustomAxiosInstance, createFetch, createKeyMap, customShortcut, daysBetween, daysToNextBirthday, debounce, debounceAsync, debounceAsyncValidator, debounceAsyncWithImmediate, debounceLeading, debounceLeadingTrailing, debounceTrailing, decrypt, deepClone, deepEqual, deepMerge, detectKeyHold, disableCopy, disableF12Key, disableMouseButtons, disableRightClick, disableSpecificKeys, downloadBlob, enableMouseButtons, enableRightClick, enableSpecificKeys, encrypt, exportToCSV, exportToExcel, exportToJSON, exportToText, exportToXML, filterObjectByKeys, flattenObject, formDataToObject, formatDate, generateRandomString, getAppKey, getAuthRefreshToken, getAuthToken, getAxiosInstance, getDecryptedItem, getEndOfMonth, getEndpointsConfig, getObjectDifferences, getObjectKeys, getQueryParam, getSessionConfig, getSessionId, getSessionPersistence, getStartOfMonth, getTokenConfig, handleError, hasNestedProperties, hex2ab, importKey, isEmptyObject, isLeapYear, isStrongPassword, isValidAge, isValidCreditCard, isValidDate, isValidEmail, isValidExpiryDate, isValidHexColor, isValidHexColorAlpha, isValidHexNumber, isValidIP, isValidPhoneNumber, isValidSSN, isValidTime, isValidURL, isValidUsername, isValidZIP, lowerFirst, objectToFormData, objectToFormDataEnhanced, objectToQueryString, openWindow, parseDate, proxyToPlainObject, readFileAsDataURL, readFileAsText, registerKeyboardShortcuts, removeAccent, removeClickOutside, removeCustomKeyboardShortcut, removeCustomShortcuts, removeDoubleClickListener, removeEmptyProperties, removeKeyListeners, replaceAll, reverseString, safeGet, screenMap, scrollToTop, simulateKeyPress, stopDetectingKeyHold, storeAuthRefreshToken, storeAuthToken, storeEncryptedItem, stringToBlob, subtractDays, throttle, toCamelCase, toKebabCase, toggleTabNavigation, truncateString, unregisterKeyboardShortcuts, upperFirst, useAuth, useBreakpoint, useFilter, usePagination, useSorter, useVueQuery, validateAlphanumeric, validateLetters, validateNumbers, verifyAuth };
3582
+ export { AppTypes, ArchiveTypes, ArexVueCore, AudioTypes, AxiosService, ContentTypeEnum, DocumentTypes, ERROR_MESSAGES, ERROR_STYLES, ErrorEnum, ErrorMessages, ErrorStyles, ExceptionEnum, FontTypes, ImageTypes, KeyCodeEnum, OtherTypes, RestStd, ScreenBreakpoint, ScreenSize, StorageKeyEnum, StorageTypeEnum, TextTypes, VideoTypes, ab2hex, addCustomKeyboardShortcut, addDays, addDoubleClickListener, addKeyListener, ageAtDate, axiosFetch, blobToFormData, bufferToBlob, calculateAge, cleanCredentials, clickOutside, compareObject, configAppKey, configAxios, configEndpoints, configRefreshTokenPaths, configSession, configTokenKeys, configTokenPaths, copyToClipboard, countWords, createFetch, createKeyMap, customShortcut, daysBetween, daysToNextBirthday, debounce, debounceAsync, debounceAsyncValidator, debounceAsyncWithImmediate, debounceLeading, debounceLeadingTrailing, debounceTrailing, decrypt, deepClone, deepEqual, deepMerge, detectKeyHold, disableCopy, disableF12Key, disableMouseButtons, disableRightClick, disableSpecificKeys, downloadBlob, enableMouseButtons, enableRightClick, enableSpecificKeys, encrypt, exportToCSV, exportToExcel, exportToJSON, exportToText, exportToXML, extractAndValidateTokens, filterObjectByKeys, flattenObject, formDataToObject, formatDate, generateRandomString, getAppKey, getAuthRefreshToken, getAuthToken, getConfiguredAxiosInstance, getDecryptedItem, getEndOfMonth, getEndpointsConfig, getObjectDifferences, getObjectKeys, getQueryParam, getRefreshTokenPathsConfig, getSessionConfig, getSessionId, getSessionPersistence, getStartOfMonth, getTokenConfig, getTokenPathsConfig, handleError, hasNestedProperties, hex2ab, importKey, isEmptyObject, isLeapYear, isStrongPassword, isValidAge, isValidCreditCard, isValidDate, isValidEmail, isValidExpiryDate, isValidHexColor, isValidHexColorAlpha, isValidHexNumber, isValidIP, isValidPhoneNumber, isValidSSN, isValidTime, isValidURL, isValidUsername, isValidZIP, lowerFirst, objectToFormData, objectToFormDataEnhanced, objectToQueryString, openWindow, parseDate, proxyToPlainObject, readFileAsDataURL, readFileAsText, refreshTokens, registerKeyboardShortcuts, removeAccent, removeClickOutside, removeCustomKeyboardShortcut, removeCustomShortcuts, removeDoubleClickListener, removeEmptyProperties, removeKeyListeners, replaceAll, reverseString, safeGet, screenMap, scrollToTop, simulateKeyPress, stopDetectingKeyHold, storeAuthRefreshToken, storeAuthToken, storeEncryptedItem, storeTokens, stringToBlob, subtractDays, throttle, toCamelCase, toKebabCase, toggleTabNavigation, truncateString, unregisterKeyboardShortcuts, upperFirst, useAuth, useBreakpoint, useFilter, usePagination, useSorter, useVueQuery, validateAlphanumeric, validateLetters, validateNumbers, verifyAuth };
@@ -0,0 +1,56 @@
1
+ import { LocationPreference } from "@/types/SessionConfig";
2
+ /**
3
+ * Clears all stored authentication data (access and refresh tokens)
4
+ * from either sessionStorage, localStorage, or both based on the provided location preference.
5
+ *
6
+ * @param {LocationPreference} location - The storage preference ('local' for localStorage, 'session' for sessionStorage, 'any' for both).
7
+ * @returns {Promise<void>} A promise that resolves when all relevant storage items are removed.
8
+ */
9
+ export declare const cleanCredentials: (location: LocationPreference) => Promise<void>;
10
+ /**
11
+ * Retrieves the authentication token (access token) from storage, decrypting it
12
+ * using the provided secret key and based on the specified session preference.
13
+ *
14
+ * @param {string} secretKey - The secret key used for decryption.
15
+ * @param {SessionPreference} preference - The storage preference ('local' for localStorage, 'session' for sessionStorage).
16
+ * @returns {Promise<string | null>} A promise that resolves with the decrypted access token, or null if not found.
17
+ */
18
+ export declare const getAuthToken: (secretKey: string, location: LocationPreference) => Promise<string | null>;
19
+ /**
20
+ * Retrieves the authentication refresh token from storage, decrypting it
21
+ * using the provided secret key and based on the specified session preference.
22
+ *
23
+ * @param {string} secretKey - The secret key used for decryption.
24
+ * @param {SessionPreference} preference - The storage preference ('local' for localStorage, 'session' for sessionStorage).
25
+ * @returns {Promise<string | null>} A promise that resolves with the decrypted refresh token, or null if not found.
26
+ */
27
+ export declare const getAuthRefreshToken: (secretKey: string, location: LocationPreference) => Promise<string | null>;
28
+ /**
29
+ * Stores the authentication token (access token) in storage after encrypting it,
30
+ * based on the specified session preference.
31
+ *
32
+ * @param {string} token - The access token to store.
33
+ * @param {string} secretKey - The secret key used for encryption.
34
+ * @param {SessionPreference} preference - The storage preference ('local' for localStorage, 'session' for sessionStorage).
35
+ * @returns {Promise<void>} A promise that resolves when the token is successfully stored.
36
+ */
37
+ export declare const storeAuthToken: (token: string, secretKey: string, location: LocationPreference) => Promise<void>;
38
+ /**
39
+ * Stores the authentication refresh token in storage after encrypting it,
40
+ * based on the specified session preference.
41
+ *
42
+ * @param {string} token - The refresh token to store.
43
+ * @param {string} secretKey - The secret key used for encryption.
44
+ * @param {SessionPreference} preference - The storage preference ('local' for localStorage, 'session' for sessionStorage).
45
+ * @returns {Promise<void>} A promise that resolves when the token is successfully stored.
46
+ */
47
+ export declare const storeAuthRefreshToken: (token: string, secretKey: string, location: LocationPreference) => Promise<void>;
48
+ /**
49
+ * Verifies the validity and expiration of the current authentication token.
50
+ * If the token is missing, invalid, or expired, appropriate errors are thrown and credentials are cleaned.
51
+ *
52
+ * @returns {Promise<boolean>} True if the token is valid and unexpired.
53
+ * @throws {Error} "TOKEN_MISSING" if no token is found, "TOKEN_EXPIRED" if the token has expired,
54
+ * "TOKEN_INVALID" if the token format is invalid.
55
+ */
56
+ export declare const verifyAuth: () => Promise<boolean>;
@@ -0,0 +1,12 @@
1
+ import { AuthTokenPaths } from "@/types";
2
+ import { TokenValidationResult } from '@/types';
3
+ /**
4
+ * Extracts and validates the access and refresh tokens from a response object.
5
+ * Throws an error if the tokens are not found or are invalid.
6
+ *
7
+ * @param {any} data - The API response object.
8
+ * @param {AuthTokenPaths} tokenPaths - The paths for the tokens.
9
+ * @param {string} errorSource - A prefix for the error message ("LOGIN" or "REFRESH").
10
+ * @returns {TokenValidationResult} An object with the validated tokens.
11
+ */
12
+ export declare const extractAndValidateTokens: (data: any, tokenPaths: AuthTokenPaths, errorSource: string) => TokenValidationResult;
@@ -0,0 +1,4 @@
1
+ export * from './extractTokens';
2
+ export * from './refreshTokens';
3
+ export * from "./storeTokens";
4
+ export * from './credentials';
@@ -0,0 +1,13 @@
1
+ import { AuthResponse } from "@/types";
2
+ import { AxiosInstance } from 'axios';
3
+ /**
4
+ * Refreshes the authentication tokens using the stored refresh token.
5
+ * This function can also accept optional token paths if the refresh endpoint
6
+ * returns tokens with a different structure than the default login.
7
+ * If no refresh token is found, it throws an error and initiates a logout.
8
+ *
9
+ * @param {AuthTokenPaths} [tokenPaths] - Optional configuration for the paths (in dot notation) of the access and refresh tokens in the refresh endpoint response.
10
+ * @returns {Promise<AuthResponse>} The new authentication response with refreshed tokens.
11
+ * @throws {Error} If the refresh token is missing or the refresh request fails.
12
+ */
13
+ export declare const refreshTokens: (axiosInstance: AxiosInstance) => Promise<AuthResponse>;
@@ -0,0 +1,9 @@
1
+ import { LocationPreference } from "@/types";
2
+ /**
3
+ * Stores the access and refresh tokens in the appropriate storage based on the user's preference.
4
+ *
5
+ * @param {string} accessToken - El token de acceso.
6
+ * @param {string} refreshToken - El token de refresco.
7
+ * @param {LocationPreference} persistence - La preferencia de almacenamiento.
8
+ */
9
+ export declare const storeTokens: (accessToken: string, refreshToken: string, persistence: LocationPreference) => Promise<void>;
@@ -1,3 +1,4 @@
1
+ import { AxiosServiceOptions } from "./AxiosServiceOptions";
1
2
  export interface ArexVueCoreOptions {
2
3
  appKey: string;
3
4
  endpoints: {
@@ -9,5 +10,13 @@ export interface ArexVueCoreOptions {
9
10
  accessToken: string;
10
11
  refreshToken: string;
11
12
  };
12
- apiUrl: string;
13
+ tokenPaths: {
14
+ accessToken: string;
15
+ refreshToken: string;
16
+ };
17
+ refreshTokenPaths: {
18
+ accessToken: string;
19
+ refreshToken: string;
20
+ };
21
+ axios: AxiosServiceOptions;
13
22
  }
@@ -3,10 +3,6 @@ export type AuthConfig = {
3
3
  endpoints: EndpointsConfig;
4
4
  storageKeys: TokensConfig;
5
5
  };
6
- export interface AuthParams {
7
- username?: string;
8
- password?: string;
9
- }
10
6
  export interface AuthTokenPaths {
11
7
  accessTokenPath?: string;
12
8
  refreshTokenPath?: string;
@@ -0,0 +1,4 @@
1
+ export type TokenValidationResult = {
2
+ accessToken: string;
3
+ refreshToken: string;
4
+ };
@@ -9,3 +9,4 @@ export * from './DecodedJwtPayload';
9
9
  export * from './ArexVueCoreOptions';
10
10
  export * from './AppKeyConfig';
11
11
  export * from './AxiosServiceOptions';
12
+ export * from './TokenValidationResult';
@@ -7,7 +7,7 @@ export * from './files';
7
7
  export * from './objects';
8
8
  export * from './strings';
9
9
  export * from './validations';
10
- export * from './credentials';
10
+ export * from '../services/credentials';
11
11
  export * from './storage';
12
12
  export * from './encryption';
13
13
  export * from './errors';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arex95/vue-core",
3
- "version": "1.1.39",
3
+ "version": "1.1.40",
4
4
  "description": "Opinionated Vue Core",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",