@arex95/vue-core 1.1.11 → 1.1.13

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.
@@ -16,8 +16,8 @@ export declare function configureAuth(options: AuthConfig): void;
16
16
  */
17
17
  export declare function useAuth(secretKey?: string): {
18
18
  isAuthenticated: import("vue").ComputedRef<boolean>;
19
- jwt: import("vue").ComputedRef<string | null>;
20
- refresh_token: import("vue").ComputedRef<string | null>;
19
+ jwt: import("vue").Ref<string | null, string | null>;
20
+ refresh_token: import("vue").Ref<string | null, string | null>;
21
21
  tokenExpiry: import("vue").ComputedRef<number | null>;
22
22
  login: (params: {} | undefined, isRememberMe: boolean) => Promise<import("axios").AxiosResponse<any, any>>;
23
23
  refresh: () => Promise<import("axios").AxiosResponse<any, any> | undefined>;
@@ -1,5 +1,5 @@
1
1
  export declare function useApiActivity(sessionTimeoutMin: number, checkIntervalSec: number): {
2
- pause: import("@vueuse/shared").Fn;
3
- resume: import("@vueuse/shared").Fn;
2
+ pause: import("@vueuse/core").Fn;
3
+ resume: import("@vueuse/core").Fn;
4
4
  updateTimestamp: () => void;
5
5
  };
package/dist/index.mjs CHANGED
@@ -1,9 +1,8 @@
1
- import { useTimeoutFn, useBreakpoints, breakpointsTailwind, useWindowSize } from '@vueuse/core';
1
+ import { useTimeoutFn, useBreakpoints, breakpointsTailwind, useWindowSize, computedAsync } from '@vueuse/core';
2
2
  import axios from 'axios';
3
3
  import { useRouter } from 'vue-router';
4
4
  import { useQuery } from '@tanstack/vue-query';
5
5
  import { ref, watch, onServerPrefetch, onMounted, computed } from 'vue';
6
- import * as CryptoJS from 'crypto-js';
7
6
  import { jwtDecode } from 'jwt-decode';
8
7
  import { v4 } from 'uuid';
9
8
 
@@ -2594,13 +2593,13 @@ class AxiosService {
2594
2593
  }
2595
2594
  }
2596
2595
 
2597
- let axiosInstance$1;
2596
+ let axiosInstance;
2598
2597
  /**
2599
2598
  * Configures the global Axios instance with a base URL.
2600
2599
  * @param {string} baseURL - The base URL for the Axios instance.
2601
2600
  */
2602
2601
  const configAxios = (baseURL) => {
2603
- axiosInstance$1 = new AxiosService(baseURL);
2602
+ axiosInstance = new AxiosService(baseURL);
2604
2603
  };
2605
2604
  /**
2606
2605
  * Retrieves the configured Axios instance.
@@ -2608,10 +2607,10 @@ const configAxios = (baseURL) => {
2608
2607
  * @throws Will throw an error if the Axios instance is not configured.
2609
2608
  */
2610
2609
  const getAxiosInstance = () => {
2611
- if (!axiosInstance$1) {
2610
+ if (!axiosInstance) {
2612
2611
  throw new Error('Axios instance not configured. Call configureAxios first.');
2613
2612
  }
2614
- return axiosInstance$1.getAxiosInstance();
2613
+ return axiosInstance.getAxiosInstance();
2615
2614
  };
2616
2615
  /**
2617
2616
  * Creates a new AxiosService instance with custom headers.
@@ -2990,7 +2989,6 @@ function useSorter(items, criteriaList, selectedCriteria) {
2990
2989
  }).value;
2991
2990
  }
2992
2991
 
2993
- const axiosInstance = getAxiosInstance();
2994
2992
  const tokensConfig = getTokenConfig();
2995
2993
  const endpointsConfig = getEndpointsConfig();
2996
2994
  const config = {
@@ -3013,42 +3011,67 @@ function configureAuth(options) {
3013
3011
  config.storageKeys = { ...config.storageKeys, ...options.storageKeys };
3014
3012
  }
3015
3013
  }
3014
+ function ab2hex(buffer) {
3015
+ return Array.from(buffer)
3016
+ .map((b) => b.toString(16).padStart(2, "0"))
3017
+ .join("");
3018
+ }
3019
+ function hex2ab(hex) {
3020
+ return new Uint8Array(hex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
3021
+ }
3022
+ async function importKey(secretKey) {
3023
+ const encoder = new TextEncoder();
3024
+ const keyMaterial = await crypto.subtle.digest("SHA-256", encoder.encode(secretKey));
3025
+ return await crypto.subtle.importKey("raw", keyMaterial, { name: "AES-CBC", length: 256 }, false, ["encrypt", "decrypt"]);
3026
+ }
3016
3027
  /**
3017
- * Encrypts a value using AES encryption.
3028
+ * Encrypts a value using AES-256 CBC encryption with Web Cryptography API.
3029
+ * The IV is generated randomly for each encryption and prepended to the ciphertext.
3018
3030
  *
3019
3031
  * @param {string} value - The value to encrypt.
3020
- * @param {string} key - The encryption key.
3021
- * @returns {string} The encrypted string.
3022
- */
3023
- const encrypt = (value, key) => {
3024
- return CryptoJS.AES.encrypt(value, key).toString();
3032
+ * @param {string} secretKey - The encryption key string.
3033
+ * @returns {Promise<string>} A promise that resolves to the encrypted string (hex IV + hex ciphertext).
3034
+ */
3035
+ const encrypt = async (value, secretKey) => {
3036
+ const key = await importKey(secretKey);
3037
+ const textEncoder = new TextEncoder();
3038
+ const data = textEncoder.encode(value);
3039
+ const iv = crypto.getRandomValues(new Uint8Array(16));
3040
+ const encryptedContentBuffer = await crypto.subtle.encrypt({ name: "AES-CBC", iv: iv }, key, data);
3041
+ const encryptedContentUint8 = new Uint8Array(encryptedContentBuffer);
3042
+ return ab2hex(iv) + ab2hex(encryptedContentUint8);
3025
3043
  };
3026
3044
  /**
3027
- * Decrypts an AES encrypted value.
3045
+ * Decrypts an AES-256 CBC encrypted value using Web Cryptography API.
3046
+ * The IV is extracted from the beginning of the encrypted string.
3028
3047
  *
3029
- * @param {string} value - The encrypted value.
3030
- * @param {string} key - The encryption key.
3031
- * @returns {string} The decrypted string.
3032
- */
3033
- const decrypt = (value, key) => {
3034
- const bytes = CryptoJS.AES.decrypt(value, key);
3035
- return bytes.toString(CryptoJS.enc.Utf8);
3048
+ * @param {string} value - The encrypted string (hex IV + hex ciphertext).
3049
+ * @param {string} secretKey - The decryption key string.
3050
+ * @returns {Promise<string>} A promise that resolves to the decrypted string.
3051
+ */
3052
+ const decrypt = async (value, secretKey) => {
3053
+ const key = await importKey(secretKey);
3054
+ const iv = hex2ab(value.substring(0, 32));
3055
+ const encryptedData = hex2ab(value.substring(32));
3056
+ const decryptedContent = await crypto.subtle.decrypt({ name: "AES-CBC", iv: iv }, key, encryptedData);
3057
+ return new TextDecoder().decode(decryptedContent);
3036
3058
  };
3037
3059
  /**
3038
3060
  * Stores an encrypted value in sessionStorage or localStorage.
3039
3061
  *
3040
3062
  * @param {string} key - Storage key.
3041
- * @param {any} value - Value to store.
3063
+ * @param {string} value - Value to store.
3042
3064
  * @param {string} secretKey - Encryption key.
3043
3065
  * @param {boolean} isRememberMe - Whether to store in localStorage.
3044
3066
  * @param {number} [attempt=0] - Retry attempt count.
3045
3067
  * @returns {Promise<void>}
3046
3068
  */
3047
- const storeEncryptedItem = async (value, key, secretKey, isRememberMe, attempt = 0) => {
3069
+ const storeEncryptedItem = async (key, value, secretKey, isRememberMe, attempt = 0) => {
3048
3070
  const storage = isRememberMe ? localStorage : sessionStorage;
3049
3071
  if (typeof window !== "undefined" && storage) {
3050
3072
  try {
3051
- storage.setItem(key, encrypt(value, secretKey));
3073
+ const encryptedValue = await encrypt(value, secretKey);
3074
+ storage.setItem(key, encryptedValue);
3052
3075
  return;
3053
3076
  }
3054
3077
  catch (error) {
@@ -3074,13 +3097,15 @@ const storeEncryptedItem = async (value, key, secretKey, isRememberMe, attempt =
3074
3097
  * @param {string} key - Storage key.
3075
3098
  * @param {string} secretKey - Decryption key.
3076
3099
  * @param {boolean} isRememberMe - Whether to retrieve from localStorage.
3077
- * @returns {string|null} The decrypted value or null.
3100
+ * @returns {Promise<string|null>} The decrypted value or null.
3078
3101
  */
3079
- function getDecryptedValue(key, secretKey, isRememberMe) {
3102
+ async function getDecryptedValue(key, secretKey, isRememberMe) {
3080
3103
  const storage = sessionStorage;
3081
3104
  try {
3082
3105
  const value = storage.getItem(key);
3083
- return value ? decrypt(value, secretKey) : null;
3106
+ if (!value)
3107
+ return null;
3108
+ return await decrypt(value, secretKey);
3084
3109
  }
3085
3110
  catch (error) {
3086
3111
  handleError(error, false);
@@ -3094,8 +3119,9 @@ function getDecryptedValue(key, secretKey, isRememberMe) {
3094
3119
  * @returns {Object} Auth composable methods and properties.
3095
3120
  */
3096
3121
  function useAuth(secretKey = getSecretKey()) {
3097
- const jwt = computed(() => getDecryptedValue(config.storageKeys.ACCESS_TOKEN, secretKey));
3098
- const refresh_token = computed(() => getDecryptedValue(config.storageKeys.REFRESH_TOKEN, secretKey));
3122
+ const axiosInstance = getAxiosInstance();
3123
+ const jwt = computedAsync(async () => await getDecryptedValue(config.storageKeys.ACCESS_TOKEN, secretKey), null);
3124
+ const refresh_token = computedAsync(async () => await getDecryptedValue(config.storageKeys.REFRESH_TOKEN, secretKey), null);
3099
3125
  /**
3100
3126
  * Computes token expiration timestamp.
3101
3127
  */
@@ -3172,7 +3198,7 @@ function useAuth(secretKey = getSecretKey()) {
3172
3198
  * Clears stored authentication data.
3173
3199
  */
3174
3200
  const cleanStorage = async () => {
3175
- Object.keys(config.storageKeys).forEach(key => {
3201
+ Object.keys(config.storageKeys).forEach((key) => {
3176
3202
  sessionStorage.removeItem(config.storageKeys[key]);
3177
3203
  localStorage.removeItem(config.storageKeys[key]);
3178
3204
  });
@@ -3182,9 +3208,9 @@ function useAuth(secretKey = getSecretKey()) {
3182
3208
  */
3183
3209
  const verifyToken = async () => {
3184
3210
  if (!jwt.value) {
3185
- handleError('TOKEN_MISSING: No valid token found', true, '/auth-error', 'query');
3211
+ handleError("TOKEN_MISSING: No valid token found", true, "/auth-error", "query");
3186
3212
  await cleanStorage();
3187
- throw new Error('TOKEN_MISSING: No valid token found');
3213
+ throw new Error("TOKEN_MISSING: No valid token found");
3188
3214
  }
3189
3215
  try {
3190
3216
  const decoded = jwtDecode(jwt.value);
@@ -3212,7 +3238,7 @@ function useAuth(secretKey = getSecretKey()) {
3212
3238
  refresh,
3213
3239
  logout,
3214
3240
  cleanStorage,
3215
- verifyToken
3241
+ verifyToken,
3216
3242
  };
3217
3243
  }
3218
3244
 
package/package.json CHANGED
@@ -1,68 +1,68 @@
1
- {
2
- "name": "@arex95/vue-core",
3
- "version": "1.1.11",
4
- "description": "Opinionated Vue Core",
5
- "main": "dist/index.js",
6
- "module": "dist/index.mjs",
7
- "exports": {
8
- "import": "./dist/index.mjs"
9
- },
10
- "types": "dist/index.d.ts",
11
- "type": "module",
12
- "files": [
13
- "dist"
14
- ],
15
- "scripts": {
16
- "build": "rollup -c",
17
- "changelog": "conventional-changelog -p angular -o CHANGELOG.md -r 0",
18
- "release": "npm version patch && npm run changelog && git add CHANGELOG.md package.json package-lock.json && git commit -m \"chore(release): update changelog\" && git push && npm publish --access public"
19
- },
20
- "repository": {
21
- "type": "git",
22
- "url": "https://github.com/Arex95/npm-arex-core.git"
23
- },
24
- "keywords": [
25
- "vue",
26
- "composables",
27
- "core",
28
- "npm"
29
- ],
30
- "author": "Arturo Rafael Serrano Girón",
31
- "license": "MIT",
32
- "peerDependencies": {
33
- "@tanstack/vue-query": ">=5.0.0",
34
- "@vueuse/core": ">=12.8.2",
35
- "axios": ">=1.6.0",
36
- "uuid": ">=11.1.0",
37
- "vue": ">=3.0.0",
38
- "vue-router": ">=4.5.0"
39
- },
40
- "devDependencies": {
41
- "@eslint/js": "^9.23.0",
42
- "@rollup/plugin-commonjs": "^28.0.3",
43
- "@rollup/plugin-json": "^6.1.0",
44
- "@rollup/plugin-node-resolve": "^16.0.0",
45
- "@rollup/plugin-typescript": "^12.1.2",
46
- "@types/crypto-js": "^4.2.2",
47
- "@types/node": "^22.13.10",
48
- "conventional-changelog-cli": "^5.0.0",
49
- "eslint": "^9.23.0",
50
- "eslint-plugin-vue": "^10.0.0",
51
- "globals": "^16.0.0",
52
- "rollup": "^4.35.0",
53
- "ts-node": "^10.9.2",
54
- "tslib": "^2.8.1",
55
- "typescript": "^5.8.2",
56
- "typescript-eslint": "^8.28.0"
57
- },
58
- "dependencies": {
59
- "@tanstack/vue-query": ">=5.0.0",
60
- "@vueuse/core": ">=12.8.2",
61
- "axios": ">=1.6.0",
62
- "crypto-js": "^4.2.0",
63
- "jwt-decode": "^4.0.0",
64
- "uuid": ">=11.1.0",
65
- "vue": ">=3.0.0",
66
- "vue-router": ">=4.5.0"
67
- }
68
- }
1
+ {
2
+ "name": "@arex95/vue-core",
3
+ "version": "1.1.13",
4
+ "description": "Opinionated Vue Core",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "exports": {
8
+ "import": "./dist/index.mjs"
9
+ },
10
+ "types": "dist/index.d.ts",
11
+ "type": "module",
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "scripts": {
16
+ "build": "rollup -c",
17
+ "changelog": "conventional-changelog -p angular -o CHANGELOG.md -r 0",
18
+ "release": "npm version patch && npm run changelog && git add CHANGELOG.md package.json package-lock.json && git commit -m \"chore(release): update changelog\" && git push && npm publish --access public"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/Arex95/npm-arex-core.git"
23
+ },
24
+ "keywords": [
25
+ "vue",
26
+ "composables",
27
+ "core",
28
+ "npm"
29
+ ],
30
+ "author": "Arturo Rafael Serrano Girón",
31
+ "license": "MIT",
32
+ "peerDependencies": {
33
+ "@tanstack/vue-query": ">=5.0.0",
34
+ "@vueuse/core": ">=12.8.2",
35
+ "axios": ">=1.6.0",
36
+ "jwt-decode": "^4.0.0",
37
+ "uuid": ">=11.1.0",
38
+ "vue": ">=3.0.0",
39
+ "vue-router": ">=4.5.0"
40
+ },
41
+ "devDependencies": {
42
+ "@eslint/js": "^9.23.0",
43
+ "@rollup/plugin-commonjs": "^28.0.3",
44
+ "@rollup/plugin-json": "^6.1.0",
45
+ "@rollup/plugin-node-resolve": "^16.0.0",
46
+ "@rollup/plugin-typescript": "^12.1.2",
47
+ "@types/crypto-js": "^4.2.2",
48
+ "@types/node": "^22.13.10",
49
+ "conventional-changelog-cli": "^5.0.0",
50
+ "eslint": "^9.23.0",
51
+ "eslint-plugin-vue": "^10.0.0",
52
+ "globals": "^16.0.0",
53
+ "rollup": "^4.35.0",
54
+ "ts-node": "^10.9.2",
55
+ "tslib": "^2.8.1",
56
+ "typescript": "^5.8.2",
57
+ "typescript-eslint": "^8.28.0"
58
+ },
59
+ "dependencies": {
60
+ "@tanstack/vue-query": ">=5.0.0",
61
+ "@vueuse/core": ">=12.8.2",
62
+ "axios": ">=1.6.0",
63
+ "jwt-decode": "^4.0.0",
64
+ "uuid": ">=11.1.0",
65
+ "vue": ">=3.0.0",
66
+ "vue-router": ">=4.5.0"
67
+ }
68
+ }