@nocios/crudify-ui 3.0.42 → 3.0.46

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/index.d.mts CHANGED
@@ -290,6 +290,10 @@ declare class SessionManager {
290
290
  * Configurar interceptor de respuesta para manejo automático de errores
291
291
  */
292
292
  setupResponseInterceptor(): void;
293
+ /**
294
+ * Detectar errores de autorización en todos los formatos posibles
295
+ */
296
+ private detectAuthorizationError;
293
297
  /**
294
298
  * Limpiar sesión completamente
295
299
  */
package/dist/index.d.ts CHANGED
@@ -290,6 +290,10 @@ declare class SessionManager {
290
290
  * Configurar interceptor de respuesta para manejo automático de errores
291
291
  */
292
292
  setupResponseInterceptor(): void;
293
+ /**
294
+ * Detectar errores de autorización en todos los formatos posibles
295
+ */
296
+ private detectAuthorizationError;
293
297
  /**
294
298
  * Limpiar sesión completamente
295
299
  */
package/dist/index.js CHANGED
@@ -487,7 +487,7 @@ var useLoginState = () => {
487
487
  };
488
488
 
489
489
  // src/providers/SessionProvider.tsx
490
- var import_react7 = require("react");
490
+ var import_react7 = __toESM(require("react"));
491
491
 
492
492
  // src/hooks/useSession.ts
493
493
  var import_react5 = require("react");
@@ -842,53 +842,103 @@ var SessionManager = class _SessionManager {
842
842
  */
843
843
  setupResponseInterceptor() {
844
844
  import_crudify_browser2.default.setResponseInterceptor(async (response) => {
845
- if (response.errors) {
846
- this.log("Response interceptor - received response with errors:", response);
847
- }
848
- if (response.errors) {
849
- let hasAuthError = false;
850
- if (Array.isArray(response.errors)) {
851
- hasAuthError = response.errors.some(
852
- (error) => error.message?.includes("Unauthorized") || error.message?.includes("Token") || error.extensions?.code === "UNAUTHENTICATED" || error.message?.includes("NOT_AUTHORIZED")
853
- );
854
- } else if (typeof response.errors === "object") {
855
- const errorMessages = Object.values(response.errors).flat();
856
- hasAuthError = errorMessages.some(
857
- (message) => typeof message === "string" && (message.includes("NOT_AUTHORIZED") || message.includes("TOKEN_REFRESH_FAILED") || message.includes("PLEASE_LOGIN") || message.includes("Unauthorized") || message.includes("UNAUTHENTICATED") || message.includes("Token"))
858
- );
859
- }
860
- if (!hasAuthError && response.errorCode) {
861
- const errorCode = response.errorCode;
862
- hasAuthError = errorCode === "UNAUTHORIZED" || errorCode === "UNAUTHENTICATED" || errorCode === "TOKEN_EXPIRED";
845
+ const authError = this.detectAuthorizationError(response);
846
+ if (authError.isAuthError) {
847
+ console.warn("\u{1F6A8} SessionManager - Authorization error detected:", {
848
+ errorType: authError.errorType,
849
+ errorDetails: authError.errorDetails,
850
+ fullResponse: response
851
+ });
852
+ if (authError.isRefreshTokenInvalid || authError.isTokenRefreshFailed) {
853
+ this.log("Refresh token invalid or refresh already failed, clearing session");
854
+ TokenStorage.clearTokens();
855
+ this.config.onSessionExpired?.();
856
+ return response;
863
857
  }
864
- if (hasAuthError) {
865
- this.log("Auth error detected in response interceptor");
866
- const isRefreshTokenFailed = response.errors && typeof response.errors === "object" && Object.values(response.errors).flat().some(
867
- (message) => typeof message === "string" && message.includes("TOKEN_REFRESH_FAILED")
868
- );
869
- if (isRefreshTokenFailed) {
870
- this.log("Refresh token failed, clearing tokens and triggering session expired");
871
- TokenStorage.clearTokens();
872
- this.config.onSessionExpired?.();
873
- } else if (TokenStorage.hasValidTokens()) {
874
- this.log("Auth error detected, attempting token refresh...");
875
- const refreshSuccess = await this.refreshTokens();
876
- if (!refreshSuccess) {
877
- this.log("Session expired, triggering callback");
878
- this.config.onSessionExpired?.();
879
- }
880
- } else {
881
- this.log("Auth error but no valid tokens, triggering session expired");
858
+ if (TokenStorage.hasValidTokens() && !authError.isIrrecoverable) {
859
+ this.log("Auth error detected, attempting token refresh...");
860
+ const refreshSuccess = await this.refreshTokens();
861
+ if (!refreshSuccess) {
862
+ this.log("Token refresh failed, triggering session expired");
882
863
  this.config.onSessionExpired?.();
883
864
  }
884
865
  } else {
885
- this.log("No auth error detected in response");
866
+ this.log("Auth error with no valid tokens or irrecoverable error, triggering session expired");
867
+ TokenStorage.clearTokens();
868
+ this.config.onSessionExpired?.();
886
869
  }
887
870
  }
888
871
  return response;
889
872
  });
890
873
  this.log("Response interceptor configured");
891
874
  }
875
+ /**
876
+ * Detectar errores de autorización en todos los formatos posibles
877
+ */
878
+ detectAuthorizationError(response) {
879
+ const result = {
880
+ isAuthError: false,
881
+ isRefreshTokenInvalid: false,
882
+ isTokenRefreshFailed: false,
883
+ isIrrecoverable: false,
884
+ errorType: "",
885
+ errorDetails: null
886
+ };
887
+ if (response.errors) {
888
+ if (Array.isArray(response.errors)) {
889
+ const hasAuthError = response.errors.some(
890
+ (error) => error.message?.includes("Unauthorized") || error.message?.includes("Token") || error.extensions?.code === "UNAUTHENTICATED" || error.message?.includes("NOT_AUTHORIZED")
891
+ );
892
+ if (hasAuthError) {
893
+ result.isAuthError = true;
894
+ result.errorType = "GraphQL Array Format";
895
+ result.errorDetails = response.errors;
896
+ }
897
+ } else if (typeof response.errors === "object") {
898
+ const errorMessages = Object.values(response.errors).flat();
899
+ const hasAuthError = errorMessages.some(
900
+ (message) => typeof message === "string" && (message.includes("NOT_AUTHORIZED") || message.includes("TOKEN_REFRESH_FAILED") || message.includes("PLEASE_LOGIN") || message.includes("Unauthorized") || message.includes("UNAUTHENTICATED") || message.includes("Token"))
901
+ );
902
+ if (hasAuthError) {
903
+ result.isAuthError = true;
904
+ result.errorType = "GraphQL Object Format";
905
+ result.errorDetails = response.errors;
906
+ result.isTokenRefreshFailed = errorMessages.some(
907
+ (message) => typeof message === "string" && message.includes("TOKEN_REFRESH_FAILED")
908
+ );
909
+ }
910
+ }
911
+ }
912
+ if (!result.isAuthError && response.data?.response?.status === "UNAUTHORIZED") {
913
+ result.isAuthError = true;
914
+ result.errorType = "Status UNAUTHORIZED";
915
+ result.errorDetails = response.data.response;
916
+ result.isIrrecoverable = true;
917
+ }
918
+ if (!result.isAuthError && response.data?.response?.data) {
919
+ try {
920
+ const parsedData = JSON.parse(response.data.response.data);
921
+ if (parsedData.error === "REFRESH_TOKEN_INVALID" || parsedData.error === "TOKEN_EXPIRED") {
922
+ result.isAuthError = true;
923
+ result.errorType = "Parsed Data Format";
924
+ result.errorDetails = parsedData;
925
+ result.isRefreshTokenInvalid = true;
926
+ result.isIrrecoverable = true;
927
+ }
928
+ } catch {
929
+ }
930
+ }
931
+ if (!result.isAuthError && response.errorCode) {
932
+ const errorCode = response.errorCode;
933
+ const isAuthErrorCode = errorCode === "UNAUTHORIZED" || errorCode === "UNAUTHENTICATED" || errorCode === "TOKEN_EXPIRED";
934
+ if (isAuthErrorCode) {
935
+ result.isAuthError = true;
936
+ result.errorType = "Error Code Format";
937
+ result.errorDetails = { errorCode };
938
+ }
939
+ }
940
+ return result;
941
+ }
892
942
  /**
893
943
  * Limpiar sesión completamente
894
944
  */
@@ -1314,7 +1364,14 @@ function SessionProvider({
1314
1364
  // ✅ Por defecto DESACTIVADO
1315
1365
  notificationOptions = {}
1316
1366
  }) {
1317
- const sessionHook = useSession(options);
1367
+ const enhancedOptions = import_react7.default.useMemo(() => ({
1368
+ ...options,
1369
+ onSessionExpired: () => {
1370
+ console.log("\u{1F6A8} SessionProvider - Session expired callback triggered");
1371
+ options.onSessionExpired?.();
1372
+ }
1373
+ }), [options]);
1374
+ const sessionHook = useSession(enhancedOptions);
1318
1375
  const resolvedConfig = (0, import_react7.useMemo)(() => {
1319
1376
  let publicApiKey;
1320
1377
  let env;
@@ -1852,6 +1909,9 @@ function translateErrorCode(errorCode, config) {
1852
1909
  }
1853
1910
  for (const key of translationKeys) {
1854
1911
  const translated = translateFn(key);
1912
+ if (enableDebug) {
1913
+ console.log(`\u{1F50D} [ErrorTranslation] Checking key: "${key}" -> result: "${translated}" (same as key: ${translated === key})`);
1914
+ }
1855
1915
  if (translated && translated !== key) {
1856
1916
  if (enableDebug) {
1857
1917
  console.log(`\u2705 [ErrorTranslation] Found translation at key: ${key} = "${translated}"`);
@@ -1880,13 +1940,25 @@ function translateError(error, config) {
1880
1940
  if (enableDebug) {
1881
1941
  console.log(`\u{1F50D} [ErrorTranslation] Translating error:`, error);
1882
1942
  }
1883
- if (error.message && !error.message.includes("Error:") && error.message.length > 0) {
1943
+ const translatedCode = translateErrorCode(error.code, config);
1944
+ if (translatedCode !== error.code.toUpperCase() && translatedCode !== error.code) {
1884
1945
  if (enableDebug) {
1885
- console.log(`\u2705 [ErrorTranslation] Using API message: "${error.message}"`);
1946
+ console.log(`\u2705 [ErrorTranslation] Using hierarchical translation: "${translatedCode}"`);
1947
+ }
1948
+ if (error.field) {
1949
+ return `${error.field}: ${translatedCode}`;
1950
+ }
1951
+ return translatedCode;
1952
+ }
1953
+ if (error.message && !error.message.includes("Error:") && error.message.length > 0 && error.message !== error.code) {
1954
+ if (enableDebug) {
1955
+ console.log(`\u{1F504} [ErrorTranslation] No hierarchical translation found, using API message: "${error.message}"`);
1886
1956
  }
1887
1957
  return error.message;
1888
1958
  }
1889
- const translatedCode = translateErrorCode(error.code, config);
1959
+ if (enableDebug) {
1960
+ console.log(`\u26A0\uFE0F [ErrorTranslation] Using final fallback: "${translatedCode}"`);
1961
+ }
1890
1962
  if (error.field) {
1891
1963
  return `${error.field}: ${translatedCode}`;
1892
1964
  }
@@ -1949,11 +2021,14 @@ var LoginForm = ({ onScreenChange, onExternalNavigate, onLoginSuccess, onError,
1949
2021
  return () => clearTimeout(timer);
1950
2022
  }, []);
1951
2023
  const translateError2 = (parsedError) => {
1952
- return errorTranslator.translateError({
2024
+ console.log("\u{1F50D} [LoginForm] Translating parsed error:", parsedError);
2025
+ const result = errorTranslator.translateError({
1953
2026
  code: parsedError.code,
1954
2027
  message: parsedError.message,
1955
2028
  field: parsedError.field
1956
2029
  });
2030
+ console.log("\u{1F50D} [LoginForm] Translation result:", result);
2031
+ return result;
1957
2032
  };
1958
2033
  const handleLogin = async () => {
1959
2034
  if (state.loading) return;
package/dist/index.mjs CHANGED
@@ -414,7 +414,7 @@ var useLoginState = () => {
414
414
  };
415
415
 
416
416
  // src/providers/SessionProvider.tsx
417
- import { createContext as createContext5, useContext as useContext5, useMemo as useMemo2 } from "react";
417
+ import React5, { createContext as createContext5, useContext as useContext5, useMemo as useMemo2 } from "react";
418
418
 
419
419
  // src/hooks/useSession.ts
420
420
  import { useState as useState3, useEffect as useEffect4, useCallback } from "react";
@@ -769,53 +769,103 @@ var SessionManager = class _SessionManager {
769
769
  */
770
770
  setupResponseInterceptor() {
771
771
  crudify2.setResponseInterceptor(async (response) => {
772
- if (response.errors) {
773
- this.log("Response interceptor - received response with errors:", response);
774
- }
775
- if (response.errors) {
776
- let hasAuthError = false;
777
- if (Array.isArray(response.errors)) {
778
- hasAuthError = response.errors.some(
779
- (error) => error.message?.includes("Unauthorized") || error.message?.includes("Token") || error.extensions?.code === "UNAUTHENTICATED" || error.message?.includes("NOT_AUTHORIZED")
780
- );
781
- } else if (typeof response.errors === "object") {
782
- const errorMessages = Object.values(response.errors).flat();
783
- hasAuthError = errorMessages.some(
784
- (message) => typeof message === "string" && (message.includes("NOT_AUTHORIZED") || message.includes("TOKEN_REFRESH_FAILED") || message.includes("PLEASE_LOGIN") || message.includes("Unauthorized") || message.includes("UNAUTHENTICATED") || message.includes("Token"))
785
- );
786
- }
787
- if (!hasAuthError && response.errorCode) {
788
- const errorCode = response.errorCode;
789
- hasAuthError = errorCode === "UNAUTHORIZED" || errorCode === "UNAUTHENTICATED" || errorCode === "TOKEN_EXPIRED";
772
+ const authError = this.detectAuthorizationError(response);
773
+ if (authError.isAuthError) {
774
+ console.warn("\u{1F6A8} SessionManager - Authorization error detected:", {
775
+ errorType: authError.errorType,
776
+ errorDetails: authError.errorDetails,
777
+ fullResponse: response
778
+ });
779
+ if (authError.isRefreshTokenInvalid || authError.isTokenRefreshFailed) {
780
+ this.log("Refresh token invalid or refresh already failed, clearing session");
781
+ TokenStorage.clearTokens();
782
+ this.config.onSessionExpired?.();
783
+ return response;
790
784
  }
791
- if (hasAuthError) {
792
- this.log("Auth error detected in response interceptor");
793
- const isRefreshTokenFailed = response.errors && typeof response.errors === "object" && Object.values(response.errors).flat().some(
794
- (message) => typeof message === "string" && message.includes("TOKEN_REFRESH_FAILED")
795
- );
796
- if (isRefreshTokenFailed) {
797
- this.log("Refresh token failed, clearing tokens and triggering session expired");
798
- TokenStorage.clearTokens();
799
- this.config.onSessionExpired?.();
800
- } else if (TokenStorage.hasValidTokens()) {
801
- this.log("Auth error detected, attempting token refresh...");
802
- const refreshSuccess = await this.refreshTokens();
803
- if (!refreshSuccess) {
804
- this.log("Session expired, triggering callback");
805
- this.config.onSessionExpired?.();
806
- }
807
- } else {
808
- this.log("Auth error but no valid tokens, triggering session expired");
785
+ if (TokenStorage.hasValidTokens() && !authError.isIrrecoverable) {
786
+ this.log("Auth error detected, attempting token refresh...");
787
+ const refreshSuccess = await this.refreshTokens();
788
+ if (!refreshSuccess) {
789
+ this.log("Token refresh failed, triggering session expired");
809
790
  this.config.onSessionExpired?.();
810
791
  }
811
792
  } else {
812
- this.log("No auth error detected in response");
793
+ this.log("Auth error with no valid tokens or irrecoverable error, triggering session expired");
794
+ TokenStorage.clearTokens();
795
+ this.config.onSessionExpired?.();
813
796
  }
814
797
  }
815
798
  return response;
816
799
  });
817
800
  this.log("Response interceptor configured");
818
801
  }
802
+ /**
803
+ * Detectar errores de autorización en todos los formatos posibles
804
+ */
805
+ detectAuthorizationError(response) {
806
+ const result = {
807
+ isAuthError: false,
808
+ isRefreshTokenInvalid: false,
809
+ isTokenRefreshFailed: false,
810
+ isIrrecoverable: false,
811
+ errorType: "",
812
+ errorDetails: null
813
+ };
814
+ if (response.errors) {
815
+ if (Array.isArray(response.errors)) {
816
+ const hasAuthError = response.errors.some(
817
+ (error) => error.message?.includes("Unauthorized") || error.message?.includes("Token") || error.extensions?.code === "UNAUTHENTICATED" || error.message?.includes("NOT_AUTHORIZED")
818
+ );
819
+ if (hasAuthError) {
820
+ result.isAuthError = true;
821
+ result.errorType = "GraphQL Array Format";
822
+ result.errorDetails = response.errors;
823
+ }
824
+ } else if (typeof response.errors === "object") {
825
+ const errorMessages = Object.values(response.errors).flat();
826
+ const hasAuthError = errorMessages.some(
827
+ (message) => typeof message === "string" && (message.includes("NOT_AUTHORIZED") || message.includes("TOKEN_REFRESH_FAILED") || message.includes("PLEASE_LOGIN") || message.includes("Unauthorized") || message.includes("UNAUTHENTICATED") || message.includes("Token"))
828
+ );
829
+ if (hasAuthError) {
830
+ result.isAuthError = true;
831
+ result.errorType = "GraphQL Object Format";
832
+ result.errorDetails = response.errors;
833
+ result.isTokenRefreshFailed = errorMessages.some(
834
+ (message) => typeof message === "string" && message.includes("TOKEN_REFRESH_FAILED")
835
+ );
836
+ }
837
+ }
838
+ }
839
+ if (!result.isAuthError && response.data?.response?.status === "UNAUTHORIZED") {
840
+ result.isAuthError = true;
841
+ result.errorType = "Status UNAUTHORIZED";
842
+ result.errorDetails = response.data.response;
843
+ result.isIrrecoverable = true;
844
+ }
845
+ if (!result.isAuthError && response.data?.response?.data) {
846
+ try {
847
+ const parsedData = JSON.parse(response.data.response.data);
848
+ if (parsedData.error === "REFRESH_TOKEN_INVALID" || parsedData.error === "TOKEN_EXPIRED") {
849
+ result.isAuthError = true;
850
+ result.errorType = "Parsed Data Format";
851
+ result.errorDetails = parsedData;
852
+ result.isRefreshTokenInvalid = true;
853
+ result.isIrrecoverable = true;
854
+ }
855
+ } catch {
856
+ }
857
+ }
858
+ if (!result.isAuthError && response.errorCode) {
859
+ const errorCode = response.errorCode;
860
+ const isAuthErrorCode = errorCode === "UNAUTHORIZED" || errorCode === "UNAUTHENTICATED" || errorCode === "TOKEN_EXPIRED";
861
+ if (isAuthErrorCode) {
862
+ result.isAuthError = true;
863
+ result.errorType = "Error Code Format";
864
+ result.errorDetails = { errorCode };
865
+ }
866
+ }
867
+ return result;
868
+ }
819
869
  /**
820
870
  * Limpiar sesión completamente
821
871
  */
@@ -1241,7 +1291,14 @@ function SessionProvider({
1241
1291
  // ✅ Por defecto DESACTIVADO
1242
1292
  notificationOptions = {}
1243
1293
  }) {
1244
- const sessionHook = useSession(options);
1294
+ const enhancedOptions = React5.useMemo(() => ({
1295
+ ...options,
1296
+ onSessionExpired: () => {
1297
+ console.log("\u{1F6A8} SessionProvider - Session expired callback triggered");
1298
+ options.onSessionExpired?.();
1299
+ }
1300
+ }), [options]);
1301
+ const sessionHook = useSession(enhancedOptions);
1245
1302
  const resolvedConfig = useMemo2(() => {
1246
1303
  let publicApiKey;
1247
1304
  let env;
@@ -1779,6 +1836,9 @@ function translateErrorCode(errorCode, config) {
1779
1836
  }
1780
1837
  for (const key of translationKeys) {
1781
1838
  const translated = translateFn(key);
1839
+ if (enableDebug) {
1840
+ console.log(`\u{1F50D} [ErrorTranslation] Checking key: "${key}" -> result: "${translated}" (same as key: ${translated === key})`);
1841
+ }
1782
1842
  if (translated && translated !== key) {
1783
1843
  if (enableDebug) {
1784
1844
  console.log(`\u2705 [ErrorTranslation] Found translation at key: ${key} = "${translated}"`);
@@ -1807,13 +1867,25 @@ function translateError(error, config) {
1807
1867
  if (enableDebug) {
1808
1868
  console.log(`\u{1F50D} [ErrorTranslation] Translating error:`, error);
1809
1869
  }
1810
- if (error.message && !error.message.includes("Error:") && error.message.length > 0) {
1870
+ const translatedCode = translateErrorCode(error.code, config);
1871
+ if (translatedCode !== error.code.toUpperCase() && translatedCode !== error.code) {
1811
1872
  if (enableDebug) {
1812
- console.log(`\u2705 [ErrorTranslation] Using API message: "${error.message}"`);
1873
+ console.log(`\u2705 [ErrorTranslation] Using hierarchical translation: "${translatedCode}"`);
1874
+ }
1875
+ if (error.field) {
1876
+ return `${error.field}: ${translatedCode}`;
1877
+ }
1878
+ return translatedCode;
1879
+ }
1880
+ if (error.message && !error.message.includes("Error:") && error.message.length > 0 && error.message !== error.code) {
1881
+ if (enableDebug) {
1882
+ console.log(`\u{1F504} [ErrorTranslation] No hierarchical translation found, using API message: "${error.message}"`);
1813
1883
  }
1814
1884
  return error.message;
1815
1885
  }
1816
- const translatedCode = translateErrorCode(error.code, config);
1886
+ if (enableDebug) {
1887
+ console.log(`\u26A0\uFE0F [ErrorTranslation] Using final fallback: "${translatedCode}"`);
1888
+ }
1817
1889
  if (error.field) {
1818
1890
  return `${error.field}: ${translatedCode}`;
1819
1891
  }
@@ -1876,11 +1948,14 @@ var LoginForm = ({ onScreenChange, onExternalNavigate, onLoginSuccess, onError,
1876
1948
  return () => clearTimeout(timer);
1877
1949
  }, []);
1878
1950
  const translateError2 = (parsedError) => {
1879
- return errorTranslator.translateError({
1951
+ console.log("\u{1F50D} [LoginForm] Translating parsed error:", parsedError);
1952
+ const result = errorTranslator.translateError({
1880
1953
  code: parsedError.code,
1881
1954
  message: parsedError.message,
1882
1955
  field: parsedError.field
1883
1956
  });
1957
+ console.log("\u{1F50D} [LoginForm] Translation result:", result);
1958
+ return result;
1884
1959
  };
1885
1960
  const handleLogin = async () => {
1886
1961
  if (state.loading) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocios/crudify-ui",
3
- "version": "3.0.42",
3
+ "version": "3.0.46",
4
4
  "description": "Biblioteca de componentes UI para Crudify",
5
5
  "author": "Nocios",
6
6
  "license": "MIT",
@@ -25,7 +25,7 @@
25
25
  "@mui/icons-material": "^7.1.0",
26
26
  "@mui/material": "^7.1.0",
27
27
  "@mui/x-data-grid": "^8.5.1",
28
- "@nocios/crudify-browser": "^2.0.2",
28
+ "@nocios/crudify-browser": "^2.0.4",
29
29
  "@types/uuid": "^10.0.0",
30
30
  "crypto-js": "^4.2.0",
31
31
  "i18next-browser-languagedetector": "^8.1.0",