@nocios/crudify-ui 4.0.96 → 4.1.0
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/{LoginComponent-saSn0o5x.d.mts → LoginComponent-CSTVsfeV.d.mts} +1 -1
- package/dist/{LoginComponent-saSn0o5x.d.ts → LoginComponent-CSTVsfeV.d.ts} +1 -1
- package/dist/chunk-5JKS55SE.mjs +1 -0
- package/dist/chunk-AT74WV5W.js +1 -0
- package/dist/chunk-CTDQEJAU.mjs +1 -0
- package/dist/{chunk-WG3ZXCPF.js → chunk-GFZGBKFG.js} +1 -1
- package/dist/{chunk-JYDCSNNQ.mjs → chunk-GLR5HDJC.mjs} +1 -1
- package/dist/{chunk-Y72XFXMI.mjs → chunk-KNEHDX2M.mjs} +1 -1
- package/dist/chunk-TLGRXZCS.js +1 -0
- package/dist/{chunk-LP5NJV2P.js → chunk-X3HSMDZ7.js} +1 -1
- package/dist/components.d.mts +1 -1
- package/dist/components.d.ts +1 -1
- package/dist/components.js +1 -1
- package/dist/components.mjs +1 -1
- package/dist/{errorTranslation-DqdgLEUy.d.mts → errorTranslation-DEn4aqs6.d.mts} +1 -1
- package/dist/{errorTranslation-CBbQYNWR.d.ts → errorTranslation-DdqZg8JD.d.ts} +1 -1
- package/dist/hooks.d.mts +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +1 -1
- package/dist/hooks.mjs +1 -1
- package/dist/{index-CUbUeMMS.d.mts → index-BwF68SOh.d.mts} +13 -2
- package/dist/{index-DZdMugLk.d.ts → index-Fkm9ErmY.d.ts} +13 -2
- package/dist/index.d.mts +128 -13
- package/dist/index.d.ts +128 -13
- package/dist/index.js +6 -1
- package/dist/index.mjs +6 -1
- package/dist/utils.d.mts +77 -3
- package/dist/utils.d.ts +77 -3
- package/dist/utils.js +1 -1
- package/dist/utils.mjs +1 -1
- package/package.json +24 -4
- package/vitest.config.ts +27 -0
- package/dist/chunk-ATAGEVFK.js +0 -1
- package/dist/chunk-HMJY3MMZ.mjs +0 -1
- package/dist/chunk-MMYGRMGB.mjs +0 -1
- package/dist/chunk-RHG74IMW.js +0 -1
|
@@ -105,6 +105,8 @@ declare class SessionManager {
|
|
|
105
105
|
private config;
|
|
106
106
|
private initialized;
|
|
107
107
|
private lastActivityTime;
|
|
108
|
+
private isRefreshingLocally;
|
|
109
|
+
private refreshPromise;
|
|
108
110
|
private constructor();
|
|
109
111
|
static getInstance(): SessionManager;
|
|
110
112
|
/**
|
|
@@ -152,11 +154,20 @@ declare class SessionManager {
|
|
|
152
154
|
hasValidTokens: boolean;
|
|
153
155
|
};
|
|
154
156
|
/**
|
|
155
|
-
* Refrescar tokens
|
|
157
|
+
* ✅ FASE 4: Refrescar tokens con protección contra concurrencia
|
|
156
158
|
*/
|
|
157
159
|
refreshTokens(): Promise<boolean>;
|
|
158
160
|
/**
|
|
159
|
-
* ✅ FASE
|
|
161
|
+
* ✅ FASE 4: Método privado que realiza el refresh real
|
|
162
|
+
*/
|
|
163
|
+
private _performRefresh;
|
|
164
|
+
/**
|
|
165
|
+
* ✅ FASE 4: Verificar si hay un refresh en progreso
|
|
166
|
+
*/
|
|
167
|
+
isRefreshing(): boolean;
|
|
168
|
+
/**
|
|
169
|
+
* ✅ MEJORADO FASE 3: Configurar interceptor de respuesta NON-BLOCKING
|
|
170
|
+
* El interceptor NO debe hacer await, solo detectar y emitir eventos
|
|
160
171
|
*/
|
|
161
172
|
setupResponseInterceptor(): void;
|
|
162
173
|
/**
|
|
@@ -105,6 +105,8 @@ declare class SessionManager {
|
|
|
105
105
|
private config;
|
|
106
106
|
private initialized;
|
|
107
107
|
private lastActivityTime;
|
|
108
|
+
private isRefreshingLocally;
|
|
109
|
+
private refreshPromise;
|
|
108
110
|
private constructor();
|
|
109
111
|
static getInstance(): SessionManager;
|
|
110
112
|
/**
|
|
@@ -152,11 +154,20 @@ declare class SessionManager {
|
|
|
152
154
|
hasValidTokens: boolean;
|
|
153
155
|
};
|
|
154
156
|
/**
|
|
155
|
-
* Refrescar tokens
|
|
157
|
+
* ✅ FASE 4: Refrescar tokens con protección contra concurrencia
|
|
156
158
|
*/
|
|
157
159
|
refreshTokens(): Promise<boolean>;
|
|
158
160
|
/**
|
|
159
|
-
* ✅ FASE
|
|
161
|
+
* ✅ FASE 4: Método privado que realiza el refresh real
|
|
162
|
+
*/
|
|
163
|
+
private _performRefresh;
|
|
164
|
+
/**
|
|
165
|
+
* ✅ FASE 4: Verificar si hay un refresh en progreso
|
|
166
|
+
*/
|
|
167
|
+
isRefreshing(): boolean;
|
|
168
|
+
/**
|
|
169
|
+
* ✅ MEJORADO FASE 3: Configurar interceptor de respuesta NON-BLOCKING
|
|
170
|
+
* El interceptor NO debe hacer await, solo detectar y emitir eventos
|
|
160
171
|
*/
|
|
161
172
|
setupResponseInterceptor(): void;
|
|
162
173
|
/**
|
package/dist/index.d.mts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export * from '@nocios/crudify-browser';
|
|
2
2
|
export { default as crudify } from '@nocios/crudify-browser';
|
|
3
|
-
export { B as BoxScreenType, C as CrudifyLogin,
|
|
3
|
+
export { B as BoxScreenType, C as CrudifyLogin, a as CrudifyLoginConfig, b as CrudifyLoginProps, c as CrudifyLoginTranslations, L as LoginComponent, f as POLICY_ACTIONS, g as PREFERRED_POLICY_ORDER, P as Policies, e as PolicyAction, S as SessionStatus, d as UserLoginData, U as UserProfileDisplay } from './LoginComponent-CSTVsfeV.mjs';
|
|
4
4
|
export { A as ApiError, C as CrudifyApiResponse, a as CrudifyTransactionResponse, F as ForgotPasswordRequest, J as JwtPayload, b as LoginRequest, L as LoginResponse, R as ResetPasswordRequest, T as TransactionResponseData, U as UserProfile, V as ValidateCodeRequest, c as ValidationError } from './api-Djqihi4n.mjs';
|
|
5
|
-
import { U as UseSessionOptions, T as TokenData, L as LoginResult } from './index-
|
|
6
|
-
export { a as SessionConfig, S as SessionManager, d as SessionState, c as StorageType, b as TokenStorage, j as UseAuthReturn, l as UseDataReturn, g as UseUserDataOptions, f as UseUserDataReturn, h as UserData, i as useAuth, n as useCrudifyWithNotifications, k as useData, u as useSession, e as useUserData, m as useUserProfile } from './index-
|
|
5
|
+
import { U as UseSessionOptions, T as TokenData, L as LoginResult } from './index-BwF68SOh.mjs';
|
|
6
|
+
export { a as SessionConfig, S as SessionManager, d as SessionState, c as StorageType, b as TokenStorage, j as UseAuthReturn, l as UseDataReturn, g as UseUserDataOptions, f as UseUserDataReturn, h as UserData, i as useAuth, n as useCrudifyWithNotifications, k as useData, u as useSession, e as useUserData, m as useUserProfile } from './index-BwF68SOh.mjs';
|
|
7
7
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
8
8
|
import { ReactNode } from 'react';
|
|
9
|
-
export { E as ERROR_CODES, j as ERROR_SEVERITY_MAP,
|
|
9
|
+
export { E as ERROR_CODES, j as ERROR_SEVERITY_MAP, n as ErrorCode, o as ErrorSeverity, q as ErrorTranslationConfig, P as ParsedError, m as createErrorTranslator, d as decodeJwtSafely, a as getCookie, g as getCurrentUserEmail, f as getErrorMessage, h as handleCrudifyError, i as isTokenExpired, p as parseApiError, e as parseJavaScriptError, c as parseTransactionError, b as secureLocalStorage, s as secureSessionStorage, l as translateError, t as translateErrorCode, k as translateErrorCodes } from './errorTranslation-DEn4aqs6.mjs';
|
|
10
10
|
export { G as GlobalNotificationProvider, a as GlobalNotificationProviderProps, N as Notification, b as NotificationSeverity, u as useGlobalNotification } from './GlobalNotificationProvider-C3iWgM1z.mjs';
|
|
11
11
|
|
|
12
12
|
type SessionData = {
|
|
@@ -65,17 +65,132 @@ declare function SessionProvider(props: SessionProviderProps): react_jsx_runtime
|
|
|
65
65
|
*/
|
|
66
66
|
declare function useSessionContext(): SessionContextType;
|
|
67
67
|
/**
|
|
68
|
-
*
|
|
68
|
+
* Componente para mostrar información de la sesión (debug)
|
|
69
69
|
*/
|
|
70
|
-
|
|
70
|
+
declare function SessionDebugInfo(): react_jsx_runtime.JSX.Element;
|
|
71
|
+
|
|
72
|
+
interface ProtectedRouteProps {
|
|
71
73
|
children: ReactNode;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Componente a mostrar mientras se valida la sesión
|
|
76
|
+
* @default <SessionLoadingScreen stage="validating-session" />
|
|
77
|
+
*/
|
|
78
|
+
loadingComponent?: ReactNode;
|
|
79
|
+
/**
|
|
80
|
+
* Ruta a la que redirigir si no está autenticado
|
|
81
|
+
* @default "/login"
|
|
82
|
+
*/
|
|
83
|
+
loginPath?: string;
|
|
84
|
+
}
|
|
76
85
|
/**
|
|
77
|
-
* Componente para
|
|
86
|
+
* Componente para proteger rutas que requieren autenticación
|
|
87
|
+
*
|
|
88
|
+
* Características:
|
|
89
|
+
* - Valida sesión de forma estricta (isAuthenticated + tokens válidos)
|
|
90
|
+
* - Guarda URL actual para redirect post-login
|
|
91
|
+
* - Previene open redirect attacks
|
|
92
|
+
* - Limpia storage corrupto automáticamente
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```tsx
|
|
96
|
+
* <Route
|
|
97
|
+
* path="/dashboard"
|
|
98
|
+
* element={
|
|
99
|
+
* <ProtectedRoute>
|
|
100
|
+
* <Dashboard />
|
|
101
|
+
* </ProtectedRoute>
|
|
102
|
+
* }
|
|
103
|
+
* />
|
|
104
|
+
* ```
|
|
78
105
|
*/
|
|
79
|
-
declare function
|
|
106
|
+
declare function ProtectedRoute({ children, loadingComponent, loginPath, }: ProtectedRouteProps): react_jsx_runtime.JSX.Element;
|
|
107
|
+
|
|
108
|
+
interface AuthRouteProps {
|
|
109
|
+
children: ReactNode;
|
|
110
|
+
/**
|
|
111
|
+
* Ruta a la que redirigir si ya está autenticado
|
|
112
|
+
* Si hay parámetro ?redirect= en la URL, se usará ese en su lugar
|
|
113
|
+
* @default "/"
|
|
114
|
+
*/
|
|
115
|
+
redirectTo?: string;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Componente para proteger rutas de autenticación (login, register, etc.)
|
|
119
|
+
* Redirige a home si el usuario ya está autenticado
|
|
120
|
+
*
|
|
121
|
+
* Características:
|
|
122
|
+
* - Si usuario autenticado → redirige a home (o ?redirect= si existe)
|
|
123
|
+
* - Si no autenticado → muestra el componente (login, etc.)
|
|
124
|
+
* - Valida parámetro redirect para prevenir open redirect
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```tsx
|
|
128
|
+
* <Route
|
|
129
|
+
* path="/login"
|
|
130
|
+
* element={
|
|
131
|
+
* <AuthRoute>
|
|
132
|
+
* <LoginPage />
|
|
133
|
+
* </AuthRoute>
|
|
134
|
+
* }
|
|
135
|
+
* />
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
declare function AuthRoute({ children, redirectTo }: AuthRouteProps): react_jsx_runtime.JSX.Element;
|
|
139
|
+
|
|
140
|
+
interface SessionLoadingScreenProps {
|
|
141
|
+
/**
|
|
142
|
+
* Stage of loading to display appropriate message
|
|
143
|
+
* @default "loading"
|
|
144
|
+
*/
|
|
145
|
+
stage?: "initializing" | "validating-session" | "loading";
|
|
146
|
+
/**
|
|
147
|
+
* Custom message to display (overrides default stage message)
|
|
148
|
+
*/
|
|
149
|
+
message?: string;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Loading screen component for session-related loading states
|
|
153
|
+
*
|
|
154
|
+
* Features:
|
|
155
|
+
* - Clean, minimal design
|
|
156
|
+
* - Customizable message
|
|
157
|
+
* - Stage-based default messages
|
|
158
|
+
* - No external dependencies (works without i18n)
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```tsx
|
|
162
|
+
* // Basic usage
|
|
163
|
+
* <SessionLoadingScreen stage="validating-session" />
|
|
164
|
+
*
|
|
165
|
+
* // With custom message
|
|
166
|
+
* <SessionLoadingScreen
|
|
167
|
+
* stage="validating-session"
|
|
168
|
+
* message={t("loading.validatingSession")}
|
|
169
|
+
* />
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
declare function SessionLoadingScreen({ stage, message, }: SessionLoadingScreenProps): react_jsx_runtime.JSX.Element;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Utilidades de seguridad para validar redirecciones
|
|
176
|
+
* Previene ataques de open redirect permitiendo rutas dinámicas
|
|
177
|
+
*/
|
|
178
|
+
/**
|
|
179
|
+
* Valida que una ruta de redirección sea segura (solo rutas internas)
|
|
180
|
+
* Permite rutas dinámicas pero bloquea ataques de open redirect
|
|
181
|
+
*
|
|
182
|
+
* @param path - La ruta a validar
|
|
183
|
+
* @param defaultPath - Ruta por defecto si la validación falla
|
|
184
|
+
* @returns Ruta validada y segura
|
|
185
|
+
*/
|
|
186
|
+
declare const validateInternalRedirect: (path: string, defaultPath?: string) => string;
|
|
187
|
+
/**
|
|
188
|
+
* Extrae y valida parámetro redirect de URL search params
|
|
189
|
+
*
|
|
190
|
+
* @param searchParams - URLSearchParams o string de query params
|
|
191
|
+
* @param defaultPath - Ruta por defecto
|
|
192
|
+
* @returns Ruta validada
|
|
193
|
+
*/
|
|
194
|
+
declare const extractSafeRedirectFromUrl: (searchParams: URLSearchParams | string, defaultPath?: string) => string;
|
|
80
195
|
|
|
81
|
-
export { LoginResult, type NotificationOptions, ProtectedRoute, type ProtectedRouteProps, SessionDebugInfo, SessionProvider, type SessionProviderProps, TokenData, UseSessionOptions, useSessionContext };
|
|
196
|
+
export { AuthRoute, type AuthRouteProps, LoginResult, type NotificationOptions, ProtectedRoute, type ProtectedRouteProps, SessionDebugInfo, SessionLoadingScreen, type SessionLoadingScreenProps, SessionProvider, type SessionProviderProps, TokenData, UseSessionOptions, extractSafeRedirectFromUrl, useSessionContext, validateInternalRedirect };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export * from '@nocios/crudify-browser';
|
|
2
2
|
export { default as crudify } from '@nocios/crudify-browser';
|
|
3
|
-
export { B as BoxScreenType, C as CrudifyLogin,
|
|
3
|
+
export { B as BoxScreenType, C as CrudifyLogin, a as CrudifyLoginConfig, b as CrudifyLoginProps, c as CrudifyLoginTranslations, L as LoginComponent, f as POLICY_ACTIONS, g as PREFERRED_POLICY_ORDER, P as Policies, e as PolicyAction, S as SessionStatus, d as UserLoginData, U as UserProfileDisplay } from './LoginComponent-CSTVsfeV.js';
|
|
4
4
|
export { A as ApiError, C as CrudifyApiResponse, a as CrudifyTransactionResponse, F as ForgotPasswordRequest, J as JwtPayload, b as LoginRequest, L as LoginResponse, R as ResetPasswordRequest, T as TransactionResponseData, U as UserProfile, V as ValidateCodeRequest, c as ValidationError } from './api-Djqihi4n.js';
|
|
5
|
-
import { U as UseSessionOptions, T as TokenData, L as LoginResult } from './index-
|
|
6
|
-
export { a as SessionConfig, S as SessionManager, d as SessionState, c as StorageType, b as TokenStorage, j as UseAuthReturn, l as UseDataReturn, g as UseUserDataOptions, f as UseUserDataReturn, h as UserData, i as useAuth, n as useCrudifyWithNotifications, k as useData, u as useSession, e as useUserData, m as useUserProfile } from './index-
|
|
5
|
+
import { U as UseSessionOptions, T as TokenData, L as LoginResult } from './index-Fkm9ErmY.js';
|
|
6
|
+
export { a as SessionConfig, S as SessionManager, d as SessionState, c as StorageType, b as TokenStorage, j as UseAuthReturn, l as UseDataReturn, g as UseUserDataOptions, f as UseUserDataReturn, h as UserData, i as useAuth, n as useCrudifyWithNotifications, k as useData, u as useSession, e as useUserData, m as useUserProfile } from './index-Fkm9ErmY.js';
|
|
7
7
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
8
8
|
import { ReactNode } from 'react';
|
|
9
|
-
export { E as ERROR_CODES, j as ERROR_SEVERITY_MAP,
|
|
9
|
+
export { E as ERROR_CODES, j as ERROR_SEVERITY_MAP, n as ErrorCode, o as ErrorSeverity, q as ErrorTranslationConfig, P as ParsedError, m as createErrorTranslator, d as decodeJwtSafely, a as getCookie, g as getCurrentUserEmail, f as getErrorMessage, h as handleCrudifyError, i as isTokenExpired, p as parseApiError, e as parseJavaScriptError, c as parseTransactionError, b as secureLocalStorage, s as secureSessionStorage, l as translateError, t as translateErrorCode, k as translateErrorCodes } from './errorTranslation-DdqZg8JD.js';
|
|
10
10
|
export { G as GlobalNotificationProvider, a as GlobalNotificationProviderProps, N as Notification, b as NotificationSeverity, u as useGlobalNotification } from './GlobalNotificationProvider-C3iWgM1z.js';
|
|
11
11
|
|
|
12
12
|
type SessionData = {
|
|
@@ -65,17 +65,132 @@ declare function SessionProvider(props: SessionProviderProps): react_jsx_runtime
|
|
|
65
65
|
*/
|
|
66
66
|
declare function useSessionContext(): SessionContextType;
|
|
67
67
|
/**
|
|
68
|
-
*
|
|
68
|
+
* Componente para mostrar información de la sesión (debug)
|
|
69
69
|
*/
|
|
70
|
-
|
|
70
|
+
declare function SessionDebugInfo(): react_jsx_runtime.JSX.Element;
|
|
71
|
+
|
|
72
|
+
interface ProtectedRouteProps {
|
|
71
73
|
children: ReactNode;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Componente a mostrar mientras se valida la sesión
|
|
76
|
+
* @default <SessionLoadingScreen stage="validating-session" />
|
|
77
|
+
*/
|
|
78
|
+
loadingComponent?: ReactNode;
|
|
79
|
+
/**
|
|
80
|
+
* Ruta a la que redirigir si no está autenticado
|
|
81
|
+
* @default "/login"
|
|
82
|
+
*/
|
|
83
|
+
loginPath?: string;
|
|
84
|
+
}
|
|
76
85
|
/**
|
|
77
|
-
* Componente para
|
|
86
|
+
* Componente para proteger rutas que requieren autenticación
|
|
87
|
+
*
|
|
88
|
+
* Características:
|
|
89
|
+
* - Valida sesión de forma estricta (isAuthenticated + tokens válidos)
|
|
90
|
+
* - Guarda URL actual para redirect post-login
|
|
91
|
+
* - Previene open redirect attacks
|
|
92
|
+
* - Limpia storage corrupto automáticamente
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```tsx
|
|
96
|
+
* <Route
|
|
97
|
+
* path="/dashboard"
|
|
98
|
+
* element={
|
|
99
|
+
* <ProtectedRoute>
|
|
100
|
+
* <Dashboard />
|
|
101
|
+
* </ProtectedRoute>
|
|
102
|
+
* }
|
|
103
|
+
* />
|
|
104
|
+
* ```
|
|
78
105
|
*/
|
|
79
|
-
declare function
|
|
106
|
+
declare function ProtectedRoute({ children, loadingComponent, loginPath, }: ProtectedRouteProps): react_jsx_runtime.JSX.Element;
|
|
107
|
+
|
|
108
|
+
interface AuthRouteProps {
|
|
109
|
+
children: ReactNode;
|
|
110
|
+
/**
|
|
111
|
+
* Ruta a la que redirigir si ya está autenticado
|
|
112
|
+
* Si hay parámetro ?redirect= en la URL, se usará ese en su lugar
|
|
113
|
+
* @default "/"
|
|
114
|
+
*/
|
|
115
|
+
redirectTo?: string;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Componente para proteger rutas de autenticación (login, register, etc.)
|
|
119
|
+
* Redirige a home si el usuario ya está autenticado
|
|
120
|
+
*
|
|
121
|
+
* Características:
|
|
122
|
+
* - Si usuario autenticado → redirige a home (o ?redirect= si existe)
|
|
123
|
+
* - Si no autenticado → muestra el componente (login, etc.)
|
|
124
|
+
* - Valida parámetro redirect para prevenir open redirect
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```tsx
|
|
128
|
+
* <Route
|
|
129
|
+
* path="/login"
|
|
130
|
+
* element={
|
|
131
|
+
* <AuthRoute>
|
|
132
|
+
* <LoginPage />
|
|
133
|
+
* </AuthRoute>
|
|
134
|
+
* }
|
|
135
|
+
* />
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
declare function AuthRoute({ children, redirectTo }: AuthRouteProps): react_jsx_runtime.JSX.Element;
|
|
139
|
+
|
|
140
|
+
interface SessionLoadingScreenProps {
|
|
141
|
+
/**
|
|
142
|
+
* Stage of loading to display appropriate message
|
|
143
|
+
* @default "loading"
|
|
144
|
+
*/
|
|
145
|
+
stage?: "initializing" | "validating-session" | "loading";
|
|
146
|
+
/**
|
|
147
|
+
* Custom message to display (overrides default stage message)
|
|
148
|
+
*/
|
|
149
|
+
message?: string;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Loading screen component for session-related loading states
|
|
153
|
+
*
|
|
154
|
+
* Features:
|
|
155
|
+
* - Clean, minimal design
|
|
156
|
+
* - Customizable message
|
|
157
|
+
* - Stage-based default messages
|
|
158
|
+
* - No external dependencies (works without i18n)
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```tsx
|
|
162
|
+
* // Basic usage
|
|
163
|
+
* <SessionLoadingScreen stage="validating-session" />
|
|
164
|
+
*
|
|
165
|
+
* // With custom message
|
|
166
|
+
* <SessionLoadingScreen
|
|
167
|
+
* stage="validating-session"
|
|
168
|
+
* message={t("loading.validatingSession")}
|
|
169
|
+
* />
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
declare function SessionLoadingScreen({ stage, message, }: SessionLoadingScreenProps): react_jsx_runtime.JSX.Element;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Utilidades de seguridad para validar redirecciones
|
|
176
|
+
* Previene ataques de open redirect permitiendo rutas dinámicas
|
|
177
|
+
*/
|
|
178
|
+
/**
|
|
179
|
+
* Valida que una ruta de redirección sea segura (solo rutas internas)
|
|
180
|
+
* Permite rutas dinámicas pero bloquea ataques de open redirect
|
|
181
|
+
*
|
|
182
|
+
* @param path - La ruta a validar
|
|
183
|
+
* @param defaultPath - Ruta por defecto si la validación falla
|
|
184
|
+
* @returns Ruta validada y segura
|
|
185
|
+
*/
|
|
186
|
+
declare const validateInternalRedirect: (path: string, defaultPath?: string) => string;
|
|
187
|
+
/**
|
|
188
|
+
* Extrae y valida parámetro redirect de URL search params
|
|
189
|
+
*
|
|
190
|
+
* @param searchParams - URLSearchParams o string de query params
|
|
191
|
+
* @param defaultPath - Ruta por defecto
|
|
192
|
+
* @returns Ruta validada
|
|
193
|
+
*/
|
|
194
|
+
declare const extractSafeRedirectFromUrl: (searchParams: URLSearchParams | string, defaultPath?: string) => string;
|
|
80
195
|
|
|
81
|
-
export { LoginResult, type NotificationOptions, ProtectedRoute, type ProtectedRouteProps, SessionDebugInfo, SessionProvider, type SessionProviderProps, TokenData, UseSessionOptions, useSessionContext };
|
|
196
|
+
export { AuthRoute, type AuthRouteProps, LoginResult, type NotificationOptions, ProtectedRoute, type ProtectedRouteProps, SessionDebugInfo, SessionLoadingScreen, type SessionLoadingScreenProps, SessionProvider, type SessionProviderProps, TokenData, UseSessionOptions, extractSafeRedirectFromUrl, useSessionContext, validateInternalRedirect };
|
package/dist/index.js
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); }
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _chunkGFZGBKFGjs = require('./chunk-GFZGBKFG.js');var _chunkX3HSMDZ7js = require('./chunk-X3HSMDZ7.js');var _chunkTLGRXZCSjs = require('./chunk-TLGRXZCS.js');var _chunkNNY4A73Vjs = require('./chunk-NNY4A73V.js');var _chunkYIIUEOXCjs = require('./chunk-YIIUEOXC.js');var _chunkAT74WV5Wjs = require('./chunk-AT74WV5W.js');var _crudifybrowser = require('@nocios/crudify-browser'); var _crudifybrowser2 = _interopRequireDefault(_crudifybrowser); _createStarExport(_crudifybrowser);var _reactrouterdom = require('react-router-dom');var _jsxruntime = require('react/jsx-runtime');var ne={border:"5px solid rgba(0, 0, 0, 0.1)",borderTopColor:"#3B82F6",borderRadius:"50%",width:"50px",height:"50px",animation:"spin 1s linear infinite"},ae=()=>_jsxruntime.jsx.call(void 0, "style",{children:`
|
|
2
|
+
@keyframes spin {
|
|
3
|
+
0% { transform: rotate(0deg); }
|
|
4
|
+
100% { transform: rotate(360deg); }
|
|
5
|
+
}
|
|
6
|
+
`});function d({stage:e="loading",message:o}){let t=o||{initializing:"Initializing application...","validating-session":"Validating session...",loading:"Loading..."}[e];return _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment,{children:[_jsxruntime.jsx.call(void 0, ae,{}),_jsxruntime.jsxs.call(void 0, "div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100vh",width:"100vw",backgroundColor:"#f0f2f5",fontFamily:'"Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',color:"#333",textAlign:"center",boxSizing:"border-box",padding:"20px",background:"#fff"},children:[_jsxruntime.jsx.call(void 0, "div",{style:ne}),_jsxruntime.jsx.call(void 0, "p",{style:{fontSize:"1.25em",fontWeight:"500",marginTop:"24px",color:"#1f2937"},children:t})]})]})}var pe=/^[a-zA-Z0-9\-_./\?=&%#]+$/,fe=[/^https?:\/\//i,/^ftp:\/\//i,/^\/\//,/javascript:/i,/data:/i,/vbscript:/i,/about:/i,/\.\.\//,/\.\.\\/,/%2e%2e%2f/i,/%2e%2e%5c/i,/%2f%2f/i,/%5c%5c/i,/[\x00-\x1f\x7f-\x9f]/,/\\/],p= exports.validateInternalRedirect =(e,o="/")=>{if(!e||typeof e!="string")return o;let r=e.trim();if(!r)return o;if(!r.startsWith("/"))return console.warn("\u{1F6A8} Open redirect blocked (relative path):",e),o;if(!pe.test(r))return console.warn("\u{1F6A8} Open redirect blocked (invalid characters):",e),o;let t=r.toLowerCase();for(let i of fe)if(i.test(t))return console.warn("\u{1F6A8} Open redirect blocked (dangerous pattern):",e),o;let s=r.split("?")[0].split("/").filter(Boolean);if(s.length===0)return r;for(let i of s)if(i===".."||i.includes(":")||i.length>100)return console.warn("\u{1F6A8} Open redirect blocked (suspicious path part):",i),o;return r},l= exports.extractSafeRedirectFromUrl =(e,o="/")=>{try{let t=(typeof e=="string"?new URLSearchParams(e):e).get("redirect");if(!t)return o;let s=decodeURIComponent(t);return p(s,o)}catch(r){return console.warn("\u{1F6A8} Error parsing redirect parameter:",r),o}};function x({children:e,loadingComponent:o,loginPath:r="/login"}){let{isAuthenticated:t,isLoading:s,isInitialized:i,tokens:n,error:y}=_chunkTLGRXZCSjs.g.call(void 0, ),u=_reactrouterdom.useLocation.call(void 0, );if(!i||s)return _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment,{children:o||_jsxruntime.jsx.call(void 0, d,{stage:"validating-session"})});let P=t&&_optionalChain([n, 'optionalAccess', _2 => _2.accessToken])&&n.accessToken.length>0;if(y||!t||!P){n&&(!n.accessToken||n.accessToken.length===0)&&localStorage.removeItem("crudify_tokens");let h=u.pathname+u.search,C=p(h),L=encodeURIComponent(C);return _jsxruntime.jsx.call(void 0, _reactrouterdom.Navigate,{to:`${r}?redirect=${L}`,replace:!0})}return _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment,{children:e})}function S({children:e,redirectTo:o="/"}){let{isAuthenticated:r}=_chunkTLGRXZCSjs.g.call(void 0, ),t=_reactrouterdom.useLocation.call(void 0, );if(r){let s=new URLSearchParams(t.search),i=l(s,o);return _jsxruntime.jsx.call(void 0, _reactrouterdom.Navigate,{to:i,replace:!0})}return _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment,{children:e})}exports.AuthRoute = S; exports.CrudifyLogin = _chunkGFZGBKFGjs.a; exports.ERROR_CODES = _chunkYIIUEOXCjs.a; exports.ERROR_SEVERITY_MAP = _chunkYIIUEOXCjs.b; exports.GlobalNotificationProvider = _chunkTLGRXZCSjs.d; exports.LoginComponent = _chunkGFZGBKFGjs.f; exports.POLICY_ACTIONS = _chunkGFZGBKFGjs.c; exports.PREFERRED_POLICY_ORDER = _chunkGFZGBKFGjs.d; exports.Policies = _chunkGFZGBKFGjs.e; exports.ProtectedRoute = x; exports.SessionDebugInfo = _chunkTLGRXZCSjs.h; exports.SessionLoadingScreen = d; exports.SessionManager = _chunkTLGRXZCSjs.b; exports.SessionProvider = _chunkTLGRXZCSjs.f; exports.SessionStatus = _chunkGFZGBKFGjs.g; exports.TokenStorage = _chunkTLGRXZCSjs.a; exports.UserProfileDisplay = _chunkGFZGBKFGjs.b; exports.createErrorTranslator = _chunkAT74WV5Wjs.e; exports.crudify = _crudifybrowser2.default; exports.decodeJwtSafely = _chunkAT74WV5Wjs.h; exports.extractSafeRedirectFromUrl = l; exports.getCookie = _chunkAT74WV5Wjs.a; exports.getCurrentUserEmail = _chunkAT74WV5Wjs.i; exports.getErrorMessage = _chunkYIIUEOXCjs.e; exports.handleCrudifyError = _chunkYIIUEOXCjs.g; exports.isTokenExpired = _chunkAT74WV5Wjs.j; exports.parseApiError = _chunkYIIUEOXCjs.c; exports.parseJavaScriptError = _chunkYIIUEOXCjs.f; exports.parseTransactionError = _chunkYIIUEOXCjs.d; exports.secureLocalStorage = _chunkNNY4A73Vjs.b; exports.secureSessionStorage = _chunkNNY4A73Vjs.a; exports.translateError = _chunkAT74WV5Wjs.d; exports.translateErrorCode = _chunkAT74WV5Wjs.b; exports.translateErrorCodes = _chunkAT74WV5Wjs.c; exports.useAuth = _chunkX3HSMDZ7js.b; exports.useCrudifyWithNotifications = _chunkX3HSMDZ7js.d; exports.useData = _chunkX3HSMDZ7js.c; exports.useGlobalNotification = _chunkTLGRXZCSjs.e; exports.useSession = _chunkTLGRXZCSjs.c; exports.useSessionContext = _chunkTLGRXZCSjs.g; exports.useUserData = _chunkX3HSMDZ7js.a; exports.useUserProfile = _chunkTLGRXZCSjs.i; exports.validateInternalRedirect = p;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
import{a as
|
|
1
|
+
import{a as J,b as $,c as K,d as Z,e as Q,f as X,g as j}from"./chunk-GLR5HDJC.mjs";import{a as ee,b as oe,c as re,d as se}from"./chunk-KNEHDX2M.mjs";import{a as E,b as k,c as D,d as I,e as _,f as z,g as a,h as F,i as Y}from"./chunk-CTDQEJAU.mjs";import{a as te,b as ie}from"./chunk-T2CPA46I.mjs";import{a as M,b as G,c as V,d as q,e as H,f as W,g as B}from"./chunk-BJ6PIVZR.mjs";import{a as v,b as A,c as U,d as T,e as b,h as N,i as w,j as O}from"./chunk-5JKS55SE.mjs";import{default as Ie}from"@nocios/crudify-browser";export*from"@nocios/crudify-browser";import{Navigate as de,useLocation as le}from"react-router-dom";import{Fragment as ce,jsx as c,jsxs as m}from"react/jsx-runtime";var ne={border:"5px solid rgba(0, 0, 0, 0.1)",borderTopColor:"#3B82F6",borderRadius:"50%",width:"50px",height:"50px",animation:"spin 1s linear infinite"},ae=()=>c("style",{children:`
|
|
2
|
+
@keyframes spin {
|
|
3
|
+
0% { transform: rotate(0deg); }
|
|
4
|
+
100% { transform: rotate(360deg); }
|
|
5
|
+
}
|
|
6
|
+
`});function d({stage:e="loading",message:o}){let t=o||{initializing:"Initializing application...","validating-session":"Validating session...",loading:"Loading..."}[e];return m(ce,{children:[c(ae,{}),m("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100vh",width:"100vw",backgroundColor:"#f0f2f5",fontFamily:'"Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',color:"#333",textAlign:"center",boxSizing:"border-box",padding:"20px",background:"#fff"},children:[c("div",{style:ne}),c("p",{style:{fontSize:"1.25em",fontWeight:"500",marginTop:"24px",color:"#1f2937"},children:t})]})]})}var pe=/^[a-zA-Z0-9\-_./\?=&%#]+$/,fe=[/^https?:\/\//i,/^ftp:\/\//i,/^\/\//,/javascript:/i,/data:/i,/vbscript:/i,/about:/i,/\.\.\//,/\.\.\\/,/%2e%2e%2f/i,/%2e%2e%5c/i,/%2f%2f/i,/%5c%5c/i,/[\x00-\x1f\x7f-\x9f]/,/\\/],p=(e,o="/")=>{if(!e||typeof e!="string")return o;let r=e.trim();if(!r)return o;if(!r.startsWith("/"))return console.warn("\u{1F6A8} Open redirect blocked (relative path):",e),o;if(!pe.test(r))return console.warn("\u{1F6A8} Open redirect blocked (invalid characters):",e),o;let t=r.toLowerCase();for(let i of fe)if(i.test(t))return console.warn("\u{1F6A8} Open redirect blocked (dangerous pattern):",e),o;let s=r.split("?")[0].split("/").filter(Boolean);if(s.length===0)return r;for(let i of s)if(i===".."||i.includes(":")||i.length>100)return console.warn("\u{1F6A8} Open redirect blocked (suspicious path part):",i),o;return r},l=(e,o="/")=>{try{let t=(typeof e=="string"?new URLSearchParams(e):e).get("redirect");if(!t)return o;let s=decodeURIComponent(t);return p(s,o)}catch(r){return console.warn("\u{1F6A8} Error parsing redirect parameter:",r),o}};import{Fragment as g,jsx as f}from"react/jsx-runtime";function x({children:e,loadingComponent:o,loginPath:r="/login"}){let{isAuthenticated:t,isLoading:s,isInitialized:i,tokens:n,error:y}=a(),u=le();if(!i||s)return f(g,{children:o||f(d,{stage:"validating-session"})});let P=t&&n?.accessToken&&n.accessToken.length>0;if(y||!t||!P){n&&(!n.accessToken||n.accessToken.length===0)&&localStorage.removeItem("crudify_tokens");let h=u.pathname+u.search,C=p(h),L=encodeURIComponent(C);return f(de,{to:`${r}?redirect=${L}`,replace:!0})}return f(g,{children:e})}import{Navigate as ue,useLocation as me}from"react-router-dom";import{Fragment as ge,jsx as R}from"react/jsx-runtime";function S({children:e,redirectTo:o="/"}){let{isAuthenticated:r}=a(),t=me();if(r){let s=new URLSearchParams(t.search),i=l(s,o);return R(ue,{to:i,replace:!0})}return R(ge,{children:e})}export{S as AuthRoute,J as CrudifyLogin,M as ERROR_CODES,G as ERROR_SEVERITY_MAP,I as GlobalNotificationProvider,X as LoginComponent,K as POLICY_ACTIONS,Z as PREFERRED_POLICY_ORDER,Q as Policies,x as ProtectedRoute,F as SessionDebugInfo,d as SessionLoadingScreen,k as SessionManager,z as SessionProvider,j as SessionStatus,E as TokenStorage,$ as UserProfileDisplay,b as createErrorTranslator,Ie as crudify,N as decodeJwtSafely,l as extractSafeRedirectFromUrl,v as getCookie,w as getCurrentUserEmail,H as getErrorMessage,B as handleCrudifyError,O as isTokenExpired,V as parseApiError,W as parseJavaScriptError,q as parseTransactionError,ie as secureLocalStorage,te as secureSessionStorage,T as translateError,A as translateErrorCode,U as translateErrorCodes,oe as useAuth,se as useCrudifyWithNotifications,re as useData,_ as useGlobalNotification,D as useSession,a as useSessionContext,ee as useUserData,Y as useUserProfile,p as validateInternalRedirect};
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { E as ERROR_CODES, j as ERROR_SEVERITY_MAP,
|
|
1
|
+
export { E as ERROR_CODES, j as ERROR_SEVERITY_MAP, n as ErrorCode, o as ErrorSeverity, q as ErrorTranslationConfig, P as ParsedError, m as createErrorTranslator, d as decodeJwtSafely, a as getCookie, g as getCurrentUserEmail, f as getErrorMessage, h as handleCrudifyError, i as isTokenExpired, p as parseApiError, e as parseJavaScriptError, c as parseTransactionError, b as secureLocalStorage, s as secureSessionStorage, l as translateError, t as translateErrorCode, k as translateErrorCodes } from './errorTranslation-DEn4aqs6.mjs';
|
|
2
2
|
import './api-Djqihi4n.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -10,7 +10,7 @@ import './api-Djqihi4n.mjs';
|
|
|
10
10
|
* - Suscribirse para recibir notificaciones de eventos
|
|
11
11
|
* - Debounce automático para evitar múltiples disparos
|
|
12
12
|
*/
|
|
13
|
-
type AuthEventType = "SESSION_EXPIRED" | "TOKEN_REFRESH_FAILED" | "UNAUTHORIZED";
|
|
13
|
+
type AuthEventType = "SESSION_EXPIRED" | "TOKEN_REFRESH_FAILED" | "UNAUTHORIZED" | "TOKEN_EXPIRED";
|
|
14
14
|
type AuthEventDetails = {
|
|
15
15
|
message?: string;
|
|
16
16
|
error?: any;
|
|
@@ -52,4 +52,78 @@ declare class AuthEventBus {
|
|
|
52
52
|
}
|
|
53
53
|
declare const authEventBus: AuthEventBus;
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Sistema global de tracking de navegación para evitar monkey-patching anidado
|
|
57
|
+
* Usa patrón singleton con reference counting
|
|
58
|
+
*
|
|
59
|
+
* Problema que resuelve:
|
|
60
|
+
* - Si múltiples componentes usan useSession, cada uno crearía su propio monkey-patch
|
|
61
|
+
* - Esto causa anidamiento infinito de patches
|
|
62
|
+
* - NavigationTracker centraliza el patching con reference counting
|
|
63
|
+
*
|
|
64
|
+
* Uso:
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const tracker = NavigationTracker.getInstance();
|
|
67
|
+
* const unsubscribe = tracker.subscribe(() => {
|
|
68
|
+
* console.log("Navigation detected!");
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* // Cleanup
|
|
72
|
+
* unsubscribe();
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
type NavigationCallback = () => void;
|
|
76
|
+
declare class NavigationTracker {
|
|
77
|
+
private static instance;
|
|
78
|
+
private isPatched;
|
|
79
|
+
private refCount;
|
|
80
|
+
private listeners;
|
|
81
|
+
private originalPushState;
|
|
82
|
+
private originalReplaceState;
|
|
83
|
+
private constructor();
|
|
84
|
+
/**
|
|
85
|
+
* Obtener instancia singleton
|
|
86
|
+
*/
|
|
87
|
+
static getInstance(): NavigationTracker;
|
|
88
|
+
/**
|
|
89
|
+
* Suscribirse a eventos de navegación
|
|
90
|
+
* @param callback - Función a llamar cuando hay navegación
|
|
91
|
+
* @returns Función de cleanup para desuscribirse
|
|
92
|
+
*/
|
|
93
|
+
subscribe(callback: NavigationCallback): () => void;
|
|
94
|
+
/**
|
|
95
|
+
* Desuscribirse de eventos de navegación
|
|
96
|
+
* @private
|
|
97
|
+
*/
|
|
98
|
+
private unsubscribe;
|
|
99
|
+
/**
|
|
100
|
+
* Aplicar monkey-patches a history API
|
|
101
|
+
* @private
|
|
102
|
+
*/
|
|
103
|
+
private applyPatches;
|
|
104
|
+
/**
|
|
105
|
+
* Remover monkey-patches y restaurar métodos originales
|
|
106
|
+
* @private
|
|
107
|
+
*/
|
|
108
|
+
private removePatches;
|
|
109
|
+
/**
|
|
110
|
+
* Notificar a todos los listeners
|
|
111
|
+
* @private
|
|
112
|
+
*/
|
|
113
|
+
private notifyListeners;
|
|
114
|
+
/**
|
|
115
|
+
* Para testing: limpiar completamente el tracker
|
|
116
|
+
* ⚠️ SOLO USAR EN TESTS
|
|
117
|
+
*/
|
|
118
|
+
static reset(): void;
|
|
119
|
+
/**
|
|
120
|
+
* Obtener número de suscriptores activos (útil para debugging)
|
|
121
|
+
*/
|
|
122
|
+
getSubscriberCount(): number;
|
|
123
|
+
/**
|
|
124
|
+
* Verificar si los patches están activos
|
|
125
|
+
*/
|
|
126
|
+
isActive(): boolean;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export { type AuthEvent, type AuthEventDetails, type AuthEventType, NavigationTracker, authEventBus };
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { E as ERROR_CODES, j as ERROR_SEVERITY_MAP,
|
|
1
|
+
export { E as ERROR_CODES, j as ERROR_SEVERITY_MAP, n as ErrorCode, o as ErrorSeverity, q as ErrorTranslationConfig, P as ParsedError, m as createErrorTranslator, d as decodeJwtSafely, a as getCookie, g as getCurrentUserEmail, f as getErrorMessage, h as handleCrudifyError, i as isTokenExpired, p as parseApiError, e as parseJavaScriptError, c as parseTransactionError, b as secureLocalStorage, s as secureSessionStorage, l as translateError, t as translateErrorCode, k as translateErrorCodes } from './errorTranslation-DdqZg8JD.js';
|
|
2
2
|
import './api-Djqihi4n.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -10,7 +10,7 @@ import './api-Djqihi4n.js';
|
|
|
10
10
|
* - Suscribirse para recibir notificaciones de eventos
|
|
11
11
|
* - Debounce automático para evitar múltiples disparos
|
|
12
12
|
*/
|
|
13
|
-
type AuthEventType = "SESSION_EXPIRED" | "TOKEN_REFRESH_FAILED" | "UNAUTHORIZED";
|
|
13
|
+
type AuthEventType = "SESSION_EXPIRED" | "TOKEN_REFRESH_FAILED" | "UNAUTHORIZED" | "TOKEN_EXPIRED";
|
|
14
14
|
type AuthEventDetails = {
|
|
15
15
|
message?: string;
|
|
16
16
|
error?: any;
|
|
@@ -52,4 +52,78 @@ declare class AuthEventBus {
|
|
|
52
52
|
}
|
|
53
53
|
declare const authEventBus: AuthEventBus;
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Sistema global de tracking de navegación para evitar monkey-patching anidado
|
|
57
|
+
* Usa patrón singleton con reference counting
|
|
58
|
+
*
|
|
59
|
+
* Problema que resuelve:
|
|
60
|
+
* - Si múltiples componentes usan useSession, cada uno crearía su propio monkey-patch
|
|
61
|
+
* - Esto causa anidamiento infinito de patches
|
|
62
|
+
* - NavigationTracker centraliza el patching con reference counting
|
|
63
|
+
*
|
|
64
|
+
* Uso:
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const tracker = NavigationTracker.getInstance();
|
|
67
|
+
* const unsubscribe = tracker.subscribe(() => {
|
|
68
|
+
* console.log("Navigation detected!");
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* // Cleanup
|
|
72
|
+
* unsubscribe();
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
type NavigationCallback = () => void;
|
|
76
|
+
declare class NavigationTracker {
|
|
77
|
+
private static instance;
|
|
78
|
+
private isPatched;
|
|
79
|
+
private refCount;
|
|
80
|
+
private listeners;
|
|
81
|
+
private originalPushState;
|
|
82
|
+
private originalReplaceState;
|
|
83
|
+
private constructor();
|
|
84
|
+
/**
|
|
85
|
+
* Obtener instancia singleton
|
|
86
|
+
*/
|
|
87
|
+
static getInstance(): NavigationTracker;
|
|
88
|
+
/**
|
|
89
|
+
* Suscribirse a eventos de navegación
|
|
90
|
+
* @param callback - Función a llamar cuando hay navegación
|
|
91
|
+
* @returns Función de cleanup para desuscribirse
|
|
92
|
+
*/
|
|
93
|
+
subscribe(callback: NavigationCallback): () => void;
|
|
94
|
+
/**
|
|
95
|
+
* Desuscribirse de eventos de navegación
|
|
96
|
+
* @private
|
|
97
|
+
*/
|
|
98
|
+
private unsubscribe;
|
|
99
|
+
/**
|
|
100
|
+
* Aplicar monkey-patches a history API
|
|
101
|
+
* @private
|
|
102
|
+
*/
|
|
103
|
+
private applyPatches;
|
|
104
|
+
/**
|
|
105
|
+
* Remover monkey-patches y restaurar métodos originales
|
|
106
|
+
* @private
|
|
107
|
+
*/
|
|
108
|
+
private removePatches;
|
|
109
|
+
/**
|
|
110
|
+
* Notificar a todos los listeners
|
|
111
|
+
* @private
|
|
112
|
+
*/
|
|
113
|
+
private notifyListeners;
|
|
114
|
+
/**
|
|
115
|
+
* Para testing: limpiar completamente el tracker
|
|
116
|
+
* ⚠️ SOLO USAR EN TESTS
|
|
117
|
+
*/
|
|
118
|
+
static reset(): void;
|
|
119
|
+
/**
|
|
120
|
+
* Obtener número de suscriptores activos (útil para debugging)
|
|
121
|
+
*/
|
|
122
|
+
getSubscriberCount(): number;
|
|
123
|
+
/**
|
|
124
|
+
* Verificar si los patches están activos
|
|
125
|
+
*/
|
|
126
|
+
isActive(): boolean;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export { type AuthEvent, type AuthEventDetails, type AuthEventType, NavigationTracker, authEventBus };
|
package/dist/utils.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkNNY4A73Vjs = require('./chunk-NNY4A73V.js');var _chunkYIIUEOXCjs = require('./chunk-YIIUEOXC.js');var
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkNNY4A73Vjs = require('./chunk-NNY4A73V.js');var _chunkYIIUEOXCjs = require('./chunk-YIIUEOXC.js');var _chunkAT74WV5Wjs = require('./chunk-AT74WV5W.js');exports.ERROR_CODES = _chunkYIIUEOXCjs.a; exports.ERROR_SEVERITY_MAP = _chunkYIIUEOXCjs.b; exports.NavigationTracker = _chunkAT74WV5Wjs.g; exports.authEventBus = _chunkAT74WV5Wjs.f; exports.createErrorTranslator = _chunkAT74WV5Wjs.e; exports.decodeJwtSafely = _chunkAT74WV5Wjs.h; exports.getCookie = _chunkAT74WV5Wjs.a; exports.getCurrentUserEmail = _chunkAT74WV5Wjs.i; exports.getErrorMessage = _chunkYIIUEOXCjs.e; exports.handleCrudifyError = _chunkYIIUEOXCjs.g; exports.isTokenExpired = _chunkAT74WV5Wjs.j; exports.parseApiError = _chunkYIIUEOXCjs.c; exports.parseJavaScriptError = _chunkYIIUEOXCjs.f; exports.parseTransactionError = _chunkYIIUEOXCjs.d; exports.secureLocalStorage = _chunkNNY4A73Vjs.b; exports.secureSessionStorage = _chunkNNY4A73Vjs.a; exports.translateError = _chunkAT74WV5Wjs.d; exports.translateErrorCode = _chunkAT74WV5Wjs.b; exports.translateErrorCodes = _chunkAT74WV5Wjs.c;
|
package/dist/utils.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as
|
|
1
|
+
import{a as g,b as v}from"./chunk-T2CPA46I.mjs";import{a as f,b as l,c as m,d as u,e as x,f as d,g as c}from"./chunk-BJ6PIVZR.mjs";import{a as r,b as e,c as o,d as t,e as a,f as E,g as s,h as n,i as p,j as i}from"./chunk-5JKS55SE.mjs";export{f as ERROR_CODES,l as ERROR_SEVERITY_MAP,s as NavigationTracker,E as authEventBus,a as createErrorTranslator,n as decodeJwtSafely,r as getCookie,p as getCurrentUserEmail,x as getErrorMessage,c as handleCrudifyError,i as isTokenExpired,m as parseApiError,d as parseJavaScriptError,u as parseTransactionError,v as secureLocalStorage,g as secureSessionStorage,t as translateError,e as translateErrorCode,o as translateErrorCodes};
|