@nocios/crudify-components 1.0.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/.github/workflows/test.yml +59 -0
- package/.nvmrc +1 -0
- package/README.md +398 -0
- package/README_DEPTH.md +1230 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/coverage-final.json +85 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +506 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/dist/CrudiaMarkdownField-C54-A_J3.d.mts +328 -0
- package/dist/CrudiaMarkdownField-C8HQh7s5.d.ts +328 -0
- package/dist/GlobalNotificationProvider-Zq18OkpI.d.mts +96 -0
- package/dist/GlobalNotificationProvider-Zq18OkpI.d.ts +96 -0
- package/dist/api-B4uXiHF0.d.mts +118 -0
- package/dist/api-B4uXiHF0.d.ts +118 -0
- package/dist/chunk-2XOTIEKS.js +1 -0
- package/dist/chunk-5HFI5CZ5.js +1 -0
- package/dist/chunk-CHDM7KGH.js +1 -0
- package/dist/chunk-HVTRRU4W.mjs +1 -0
- package/dist/chunk-JAPL7EZJ.mjs +1 -0
- package/dist/chunk-JNEWPO2J.mjs +1 -0
- package/dist/chunk-MFYHD6S5.js +1 -0
- package/dist/chunk-MGJZTOEM.mjs +1 -0
- package/dist/chunk-NBQH6QOU.mjs +1 -0
- package/dist/chunk-NSV6ECYO.js +1 -0
- package/dist/chunk-PNI3ZBZV.js +1 -0
- package/dist/chunk-U4RS66TB.mjs +1 -0
- package/dist/components.d.mts +24 -0
- package/dist/components.d.ts +24 -0
- package/dist/components.js +1 -0
- package/dist/components.mjs +1 -0
- package/dist/errorTranslation-DGdrMidg.d.ts +143 -0
- package/dist/errorTranslation-qwwQTvCO.d.mts +143 -0
- package/dist/hooks.d.mts +6 -0
- package/dist/hooks.d.ts +6 -0
- package/dist/hooks.js +1 -0
- package/dist/hooks.mjs +1 -0
- package/dist/index-BUKX3duW.d.ts +854 -0
- package/dist/index-Y9tTsinC.d.mts +854 -0
- package/dist/index.d.mts +1274 -0
- package/dist/index.d.ts +1274 -0
- package/dist/index.js +6 -0
- package/dist/index.mjs +6 -0
- package/dist/utils.d.mts +175 -0
- package/dist/utils.d.ts +175 -0
- package/dist/utils.js +1 -0
- package/dist/utils.mjs +1 -0
- package/package.json +88 -0
- package/vitest.config.ts +28 -0
|
@@ -0,0 +1,854 @@
|
|
|
1
|
+
import { U as UserProfile, e as CrudifyRequestOptions, C as CrudifyApiResponse, g as TransactionInput, d as CrudifyOperationOptions } from './api-B4uXiHF0.js';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
import { b as NotificationSeverity } from './GlobalNotificationProvider-Zq18OkpI.js';
|
|
5
|
+
import { CrudifyResponse } from '@nocios/crudify-sdk';
|
|
6
|
+
|
|
7
|
+
type TokenData = {
|
|
8
|
+
accessToken: string;
|
|
9
|
+
refreshToken: string;
|
|
10
|
+
expiresAt: number;
|
|
11
|
+
refreshExpiresAt: number;
|
|
12
|
+
apiEndpointAdmin?: string;
|
|
13
|
+
apiKeyEndpointAdmin?: string;
|
|
14
|
+
};
|
|
15
|
+
type StorageType = "localStorage" | "sessionStorage" | "none";
|
|
16
|
+
declare class TokenStorage {
|
|
17
|
+
private static readonly TOKEN_KEY;
|
|
18
|
+
private static readonly ENCRYPTION_KEY_STORAGE;
|
|
19
|
+
private static readonly SALT_KEY;
|
|
20
|
+
private static encryptionKey;
|
|
21
|
+
private static salt;
|
|
22
|
+
private static fingerprint;
|
|
23
|
+
private static storageType;
|
|
24
|
+
private static initPromise;
|
|
25
|
+
private static lastSuccessfulLoginTime;
|
|
26
|
+
private static readonly LOGIN_GRACE_PERIOD_MS;
|
|
27
|
+
/**
|
|
28
|
+
* Configurar tipo de almacenamiento
|
|
29
|
+
*/
|
|
30
|
+
static setStorageType(type: StorageType): void;
|
|
31
|
+
/**
|
|
32
|
+
* Initialize encryption key (async)
|
|
33
|
+
* Must be called before encrypt/decrypt operations
|
|
34
|
+
*
|
|
35
|
+
* Incluye lógica de retry para manejar casos donde localStorage
|
|
36
|
+
* puede no estar disponible momentáneamente (ej: durante hydration)
|
|
37
|
+
*/
|
|
38
|
+
private static initialize;
|
|
39
|
+
/**
|
|
40
|
+
* Check storage version and clear if outdated (migration)
|
|
41
|
+
*/
|
|
42
|
+
private static checkStorageVersion;
|
|
43
|
+
/**
|
|
44
|
+
* Get or create salt for key derivation
|
|
45
|
+
*/
|
|
46
|
+
private static getOrCreateSalt;
|
|
47
|
+
/**
|
|
48
|
+
* Generate browser fingerprint for encryption key derivation
|
|
49
|
+
* IMPORTANTE: Esta función genera un fingerprint DETERMINÍSTICO basado en
|
|
50
|
+
* características estables del navegador. NO usa valores aleatorios para
|
|
51
|
+
* garantizar que los tokens puedan desencriptarse después de un page reload.
|
|
52
|
+
*
|
|
53
|
+
* Flujo:
|
|
54
|
+
* 1. Si existe un hash guardado en localStorage, lo usa (consistencia)
|
|
55
|
+
* 2. Si no existe, genera uno basado SOLO en características estables del navegador
|
|
56
|
+
* 3. Guarda el hash para futuras sesiones
|
|
57
|
+
*/
|
|
58
|
+
private static generateFingerprint;
|
|
59
|
+
/**
|
|
60
|
+
* Verificar si el storage está disponible
|
|
61
|
+
*/
|
|
62
|
+
private static isStorageAvailable;
|
|
63
|
+
/**
|
|
64
|
+
* Obtener instancia de storage
|
|
65
|
+
*/
|
|
66
|
+
private static getStorage;
|
|
67
|
+
/**
|
|
68
|
+
* Encrypt data (async)
|
|
69
|
+
*/
|
|
70
|
+
private static encryptData;
|
|
71
|
+
/**
|
|
72
|
+
* Decrypt data (async)
|
|
73
|
+
*/
|
|
74
|
+
private static decryptData;
|
|
75
|
+
/**
|
|
76
|
+
* Guardar tokens de forma segura (async)
|
|
77
|
+
*/
|
|
78
|
+
static saveTokens(tokens: TokenData): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Obtener tokens guardados (async)
|
|
81
|
+
*/
|
|
82
|
+
static getTokens(): Promise<TokenData | null>;
|
|
83
|
+
/**
|
|
84
|
+
* Limpiar tokens almacenados (async for consistency)
|
|
85
|
+
*/
|
|
86
|
+
static clearTokens(): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Rotar clave de encriptación (limpia tokens existentes por seguridad)
|
|
89
|
+
*/
|
|
90
|
+
static rotateEncryptionKey(): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Verificar si hay tokens válidos guardados (async)
|
|
93
|
+
*/
|
|
94
|
+
static hasValidTokens(): Promise<boolean>;
|
|
95
|
+
/**
|
|
96
|
+
* Asegura que TokenStorage esté inicializado
|
|
97
|
+
* Útil para cross-tab sync donde necesitamos esperar
|
|
98
|
+
* a que la clave de encriptación esté lista antes de leer tokens
|
|
99
|
+
*/
|
|
100
|
+
static ensureInitialized(): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Obtener información de expiración (async)
|
|
103
|
+
*/
|
|
104
|
+
static getExpirationInfo(): Promise<{
|
|
105
|
+
accessExpired: boolean;
|
|
106
|
+
refreshExpired: boolean;
|
|
107
|
+
accessExpiresIn: number;
|
|
108
|
+
refreshExpiresIn: number;
|
|
109
|
+
} | null>;
|
|
110
|
+
/**
|
|
111
|
+
* Actualizar solo el access token (después de refresh) - async
|
|
112
|
+
*/
|
|
113
|
+
static updateAccessToken(newAccessToken: string, newExpiresAt: number): Promise<void>;
|
|
114
|
+
/**
|
|
115
|
+
* Event types for cross-tab synchronization
|
|
116
|
+
*/
|
|
117
|
+
static readonly SYNC_EVENTS: {
|
|
118
|
+
readonly TOKENS_CLEARED: "TOKENS_CLEARED";
|
|
119
|
+
readonly TOKENS_UPDATED: "TOKENS_UPDATED";
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Cross-tab sync event details
|
|
123
|
+
*/
|
|
124
|
+
static createSyncEvent(type: (typeof TokenStorage.SYNC_EVENTS)[keyof typeof TokenStorage.SYNC_EVENTS], tokens: TokenData | null, hadPreviousTokens: boolean): {
|
|
125
|
+
type: "TOKENS_CLEARED" | "TOKENS_UPDATED";
|
|
126
|
+
tokens: TokenData | null;
|
|
127
|
+
hadPreviousTokens: boolean;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Suscribirse a cambios de tokens entre tabs
|
|
131
|
+
* Permite sincronizar logout/login entre múltiples tabs/ventanas
|
|
132
|
+
*
|
|
133
|
+
* Note: This remains sync as it's event-based, but the callback receives
|
|
134
|
+
* tokens that are already decrypted asynchronously
|
|
135
|
+
*/
|
|
136
|
+
/**
|
|
137
|
+
* Flag interno para ignorar eventos de storage generados por esta pestaña
|
|
138
|
+
* Se usa para prevenir que cambios locales disparen callbacks de cross-tab sync
|
|
139
|
+
*/
|
|
140
|
+
private static ignoreNextStorageEvent;
|
|
141
|
+
private static ignoreStorageEventTimeout;
|
|
142
|
+
/**
|
|
143
|
+
* Marca que el próximo evento de storage debe ser ignorado
|
|
144
|
+
* Útil cuando hacemos cambios locales que no queremos sincronizar como cross-tab
|
|
145
|
+
*/
|
|
146
|
+
static markLocalChange(): void;
|
|
147
|
+
/**
|
|
148
|
+
* Marca que se acaba de hacer un login exitoso
|
|
149
|
+
* Inicia el grace period durante el cual se ignoran eventos TOKENS_CLEARED
|
|
150
|
+
*/
|
|
151
|
+
static markSuccessfulLogin(): void;
|
|
152
|
+
/**
|
|
153
|
+
* Verifica si estamos dentro del grace period del login
|
|
154
|
+
* @returns true si el login exitoso fue hace menos de LOGIN_GRACE_PERIOD_MS
|
|
155
|
+
*/
|
|
156
|
+
static isWithinLoginGracePeriod(): boolean;
|
|
157
|
+
static subscribeToChanges(callback: (tokens: TokenData | null, eventType: (typeof TokenStorage.SYNC_EVENTS)[keyof typeof TokenStorage.SYNC_EVENTS], hadPreviousTokens: boolean) => void): () => void;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
type SessionConfig = {
|
|
161
|
+
storageType?: StorageType;
|
|
162
|
+
autoRestore?: boolean;
|
|
163
|
+
enableLogging?: boolean;
|
|
164
|
+
onSessionExpired?: () => void;
|
|
165
|
+
onSessionRestored?: (tokens: TokenData) => void;
|
|
166
|
+
onLoginSuccess?: (tokens: TokenData) => void;
|
|
167
|
+
onLogout?: () => void;
|
|
168
|
+
showNotification?: (message: string, severity?: "error" | "info" | "success" | "warning") => void;
|
|
169
|
+
translateFn?: (key: string) => string;
|
|
170
|
+
apiEndpointAdmin?: string;
|
|
171
|
+
apiKeyEndpointAdmin?: string;
|
|
172
|
+
publicApiKey?: string;
|
|
173
|
+
env?: "dev" | "stg" | "api" | "prod";
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Response data from a successful login
|
|
177
|
+
*/
|
|
178
|
+
interface LoginResponseData {
|
|
179
|
+
token: string;
|
|
180
|
+
refreshToken: string;
|
|
181
|
+
expiresAt: number;
|
|
182
|
+
refreshExpiresAt: number;
|
|
183
|
+
[key: string]: unknown;
|
|
184
|
+
}
|
|
185
|
+
type LoginResult = {
|
|
186
|
+
success: boolean;
|
|
187
|
+
tokens?: TokenData;
|
|
188
|
+
data?: LoginResponseData;
|
|
189
|
+
error?: string;
|
|
190
|
+
rawResponse?: Record<string, unknown>;
|
|
191
|
+
};
|
|
192
|
+
declare class SessionManager {
|
|
193
|
+
private static instance;
|
|
194
|
+
private config;
|
|
195
|
+
private initialized;
|
|
196
|
+
private crudifyInitialized;
|
|
197
|
+
private lastActivityTime;
|
|
198
|
+
private isRefreshingLocally;
|
|
199
|
+
private refreshPromise;
|
|
200
|
+
private constructor();
|
|
201
|
+
static getInstance(): SessionManager;
|
|
202
|
+
/**
|
|
203
|
+
* Initialize SessionManager with configuration
|
|
204
|
+
*/
|
|
205
|
+
initialize(config?: SessionConfig): Promise<void>;
|
|
206
|
+
/**
|
|
207
|
+
* Login with automatic token persistence
|
|
208
|
+
*/
|
|
209
|
+
login(email: string, password: string): Promise<LoginResult>;
|
|
210
|
+
/**
|
|
211
|
+
* Logout con limpieza de tokens
|
|
212
|
+
*/
|
|
213
|
+
logout(): Promise<void>;
|
|
214
|
+
/**
|
|
215
|
+
* ✅ MEJORADO: Restaurar sesión desde storage con validación robusta
|
|
216
|
+
*/
|
|
217
|
+
restoreSession(): Promise<boolean>;
|
|
218
|
+
/**
|
|
219
|
+
* Verificar si el usuario está autenticado
|
|
220
|
+
*/
|
|
221
|
+
isAuthenticated(): Promise<boolean>;
|
|
222
|
+
/**
|
|
223
|
+
* Obtener información de tokens actuales
|
|
224
|
+
*/
|
|
225
|
+
getTokenInfo(): Promise<{
|
|
226
|
+
isLoggedIn: boolean;
|
|
227
|
+
crudifyTokens: {
|
|
228
|
+
accessToken: string;
|
|
229
|
+
refreshToken: string;
|
|
230
|
+
expiresAt: number;
|
|
231
|
+
refreshExpiresAt: number;
|
|
232
|
+
isExpired: boolean;
|
|
233
|
+
isRefreshExpired: boolean;
|
|
234
|
+
isValid: boolean;
|
|
235
|
+
expiresIn: number;
|
|
236
|
+
willExpireSoon: boolean;
|
|
237
|
+
};
|
|
238
|
+
storageInfo: {
|
|
239
|
+
accessExpired: boolean;
|
|
240
|
+
refreshExpired: boolean;
|
|
241
|
+
accessExpiresIn: number;
|
|
242
|
+
refreshExpiresIn: number;
|
|
243
|
+
} | null;
|
|
244
|
+
hasValidTokens: boolean;
|
|
245
|
+
apiEndpointAdmin: string | undefined;
|
|
246
|
+
apiKeyEndpointAdmin: string | undefined;
|
|
247
|
+
}>;
|
|
248
|
+
/**
|
|
249
|
+
* ✅ FASE 4: Refrescar tokens con protección contra concurrencia
|
|
250
|
+
*/
|
|
251
|
+
refreshTokens(): Promise<boolean>;
|
|
252
|
+
/**
|
|
253
|
+
* ✅ FASE 4: Método privado que realiza el refresh real
|
|
254
|
+
*/
|
|
255
|
+
private _performRefresh;
|
|
256
|
+
/**
|
|
257
|
+
* ✅ FASE 4: Verificar si hay un refresh en progreso
|
|
258
|
+
*/
|
|
259
|
+
isRefreshing(): boolean;
|
|
260
|
+
/**
|
|
261
|
+
* ✅ MEJORADO FASE 3: Configurar interceptor de respuesta NON-BLOCKING
|
|
262
|
+
* El interceptor NO debe hacer await, solo detectar y emitir eventos
|
|
263
|
+
*/
|
|
264
|
+
setupResponseInterceptor(): void;
|
|
265
|
+
/**
|
|
266
|
+
* Ensure crudify SDK is initialized
|
|
267
|
+
* Thread-safe: multiple calls will wait for the same initialization
|
|
268
|
+
*/
|
|
269
|
+
private ensureCrudifyInitialized;
|
|
270
|
+
/**
|
|
271
|
+
* ✅ FASE 3.1: Detectar errores de autorización en todos los formatos posibles (mejorado)
|
|
272
|
+
*
|
|
273
|
+
* JUSTIFICACIÓN PARA `any`:
|
|
274
|
+
* El backend retorna respuestas en 5 formatos incompatibles:
|
|
275
|
+
* 1. GraphQL Array: { errors: [{ errorType?, message?, extensions.code? }] }
|
|
276
|
+
* 2. GraphQL Object: { errors: { fieldName: [messages] } }
|
|
277
|
+
* 3. REST Status: { data: { response: { status } } }
|
|
278
|
+
* 4. Parsed JSON: { data: { response: { data: JSON string } } }
|
|
279
|
+
* 5. Error Code: { errorCode: "CODE" }
|
|
280
|
+
*
|
|
281
|
+
* @param response - API response with dynamic structure that varies by error format
|
|
282
|
+
*/
|
|
283
|
+
private detectAuthorizationError;
|
|
284
|
+
/**
|
|
285
|
+
* ✅ FASE 2: Actualizar timestamp de última actividad del usuario
|
|
286
|
+
* Debe llamarse cuando el usuario realiza cualquier acción (CRUD, navegación, etc.)
|
|
287
|
+
*/
|
|
288
|
+
updateLastActivity(): void;
|
|
289
|
+
/**
|
|
290
|
+
* ✅ FASE 2: Obtener tiempo transcurrido desde última actividad (en milisegundos)
|
|
291
|
+
*/
|
|
292
|
+
getTimeSinceLastActivity(): number;
|
|
293
|
+
/**
|
|
294
|
+
* ✅ MEJORADO FASE 3: Verificar inactividad simplificada
|
|
295
|
+
* Solo verifica timeout de inactividad absoluta
|
|
296
|
+
* La renovación de tokens se maneja en useSession con lógica de TTL
|
|
297
|
+
* @returns 'logout' si debe desloguear por inactividad, 'none' si no hace nada
|
|
298
|
+
*/
|
|
299
|
+
checkInactivity(): "logout" | "none";
|
|
300
|
+
/**
|
|
301
|
+
* Limpiar sesión completamente
|
|
302
|
+
*/
|
|
303
|
+
clearSession(): Promise<void>;
|
|
304
|
+
/**
|
|
305
|
+
* Obtener mensaje de sesión expirada traducido
|
|
306
|
+
*/
|
|
307
|
+
private getSessionExpiredMessage;
|
|
308
|
+
private log;
|
|
309
|
+
private formatError;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Tipos e interfaces para el hook useSession
|
|
314
|
+
*/
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Estado del hook useSession
|
|
318
|
+
*/
|
|
319
|
+
type SessionState = {
|
|
320
|
+
isAuthenticated: boolean;
|
|
321
|
+
isLoading: boolean;
|
|
322
|
+
isLoggingOut: boolean;
|
|
323
|
+
isInitialized: boolean;
|
|
324
|
+
tokens: TokenData | null;
|
|
325
|
+
error: string | null;
|
|
326
|
+
};
|
|
327
|
+
/**
|
|
328
|
+
* Opciones de configuración para useSession
|
|
329
|
+
*/
|
|
330
|
+
type UseSessionOptions = {
|
|
331
|
+
autoRestore?: boolean;
|
|
332
|
+
enableLogging?: boolean;
|
|
333
|
+
onSessionExpired?: () => void;
|
|
334
|
+
onSessionRestored?: (tokens: TokenData) => void;
|
|
335
|
+
showNotification?: (message: string, severity?: "error" | "info" | "success" | "warning") => void;
|
|
336
|
+
translateFn?: (key: string) => string;
|
|
337
|
+
apiEndpointAdmin?: string;
|
|
338
|
+
apiKeyEndpointAdmin?: string;
|
|
339
|
+
publicApiKey?: string;
|
|
340
|
+
env?: "dev" | "stg" | "api" | "prod";
|
|
341
|
+
};
|
|
342
|
+
/**
|
|
343
|
+
* Retorno completo del hook useSession
|
|
344
|
+
*/
|
|
345
|
+
type UseSessionReturn = SessionState & {
|
|
346
|
+
login: (email: string, password: string) => Promise<LoginResult>;
|
|
347
|
+
logout: () => Promise<void>;
|
|
348
|
+
refreshTokens: () => Promise<boolean>;
|
|
349
|
+
clearError: () => void;
|
|
350
|
+
getTokenInfo: () => Promise<TokenInfoResult>;
|
|
351
|
+
updateActivity: () => void;
|
|
352
|
+
isExpiringSoon: boolean;
|
|
353
|
+
expiresIn: number;
|
|
354
|
+
refreshExpiresIn: number;
|
|
355
|
+
};
|
|
356
|
+
/**
|
|
357
|
+
* Resultado de getTokenInfo
|
|
358
|
+
*/
|
|
359
|
+
type TokenInfoResult = {
|
|
360
|
+
crudifyTokens: {
|
|
361
|
+
accessToken: string | null;
|
|
362
|
+
refreshToken: string | null;
|
|
363
|
+
expiresAt: number;
|
|
364
|
+
refreshExpiresAt: number;
|
|
365
|
+
expiresIn: number;
|
|
366
|
+
};
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Hook de React para manejo de sesiones con Refresh Token Pattern
|
|
371
|
+
* Proporciona una API simple para manejar autenticación en componentes React
|
|
372
|
+
*
|
|
373
|
+
* @param options - Opciones de configuración del hook
|
|
374
|
+
* @returns Estado de sesión y funciones de control
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* ```tsx
|
|
378
|
+
* const { isAuthenticated, login, logout } = useSession({
|
|
379
|
+
* onSessionExpired: () => navigate('/login')
|
|
380
|
+
* });
|
|
381
|
+
* ```
|
|
382
|
+
*/
|
|
383
|
+
declare function useSession(options?: UseSessionOptions): UseSessionReturn;
|
|
384
|
+
|
|
385
|
+
type SessionData = {
|
|
386
|
+
_id: string;
|
|
387
|
+
email: string;
|
|
388
|
+
subscriberKey: string;
|
|
389
|
+
[key: string]: unknown;
|
|
390
|
+
} | null;
|
|
391
|
+
type CrudifyConfig = {
|
|
392
|
+
publicApiKey?: string;
|
|
393
|
+
env?: "dev" | "stg" | "api" | "prod";
|
|
394
|
+
appName?: string;
|
|
395
|
+
loginActions?: string[];
|
|
396
|
+
logo?: string;
|
|
397
|
+
};
|
|
398
|
+
type SessionContextType = {
|
|
399
|
+
isAuthenticated: boolean;
|
|
400
|
+
isLoading: boolean;
|
|
401
|
+
isLoggingOut: boolean;
|
|
402
|
+
isInitialized: boolean;
|
|
403
|
+
tokens: TokenData | null;
|
|
404
|
+
error: string | null;
|
|
405
|
+
sessionData: SessionData;
|
|
406
|
+
config: CrudifyConfig;
|
|
407
|
+
login: (email: string, password: string) => Promise<LoginResult>;
|
|
408
|
+
logout: () => Promise<void>;
|
|
409
|
+
refreshTokens: () => Promise<boolean>;
|
|
410
|
+
clearError: () => void;
|
|
411
|
+
getTokenInfo: () => ReturnType<typeof useSession>["getTokenInfo"] extends () => infer R ? R : unknown;
|
|
412
|
+
isExpiringSoon: boolean;
|
|
413
|
+
expiresIn: number;
|
|
414
|
+
refreshExpiresIn: number;
|
|
415
|
+
};
|
|
416
|
+
type NotificationOptions = {
|
|
417
|
+
enabled?: boolean;
|
|
418
|
+
maxNotifications?: number;
|
|
419
|
+
defaultAutoHideDuration?: number;
|
|
420
|
+
position?: {
|
|
421
|
+
vertical: "top" | "bottom";
|
|
422
|
+
horizontal: "left" | "center" | "right";
|
|
423
|
+
};
|
|
424
|
+
allowHtml?: boolean;
|
|
425
|
+
};
|
|
426
|
+
type SessionProviderProps = {
|
|
427
|
+
children: ReactNode;
|
|
428
|
+
options?: UseSessionOptions;
|
|
429
|
+
config?: CrudifyConfig;
|
|
430
|
+
showNotifications?: boolean;
|
|
431
|
+
notificationOptions?: NotificationOptions;
|
|
432
|
+
};
|
|
433
|
+
/**
|
|
434
|
+
* Main session provider to wrap the application.
|
|
435
|
+
* Auto-initializes internal CrudifyProvider if config.publicApiKey is provided.
|
|
436
|
+
*/
|
|
437
|
+
declare function SessionProvider(props: SessionProviderProps): react_jsx_runtime.JSX.Element;
|
|
438
|
+
/**
|
|
439
|
+
* Hook para usar el contexto de sesión
|
|
440
|
+
*/
|
|
441
|
+
declare function useSessionContext(): SessionContextType;
|
|
442
|
+
/**
|
|
443
|
+
* Componente para mostrar información de la sesión (debug)
|
|
444
|
+
*/
|
|
445
|
+
declare function SessionDebugInfo(): react_jsx_runtime.JSX.Element;
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Complete user data structure (compatible con legacy)
|
|
449
|
+
*/
|
|
450
|
+
interface UserData {
|
|
451
|
+
session: Record<string, unknown> | null;
|
|
452
|
+
data: UserProfile | null;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Return type compatible con useCrudifyUser legacy
|
|
456
|
+
*/
|
|
457
|
+
interface UseUserDataReturn {
|
|
458
|
+
user: UserData;
|
|
459
|
+
loading: boolean;
|
|
460
|
+
error: string | null;
|
|
461
|
+
refreshProfile: () => Promise<void>;
|
|
462
|
+
clearProfile: () => void;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Options compatible con useCrudifyUser legacy
|
|
466
|
+
*/
|
|
467
|
+
interface UseUserDataOptions {
|
|
468
|
+
autoFetch?: boolean;
|
|
469
|
+
retryOnError?: boolean;
|
|
470
|
+
maxRetries?: number;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* useUserData - Hook completo que reemplaza useCrudifyUser del sistema legacy
|
|
474
|
+
*
|
|
475
|
+
* Funcionalidades completas:
|
|
476
|
+
* - Auto-fetch de datos del usuario desde la base de datos
|
|
477
|
+
* - Manejo inteligente de caché y deduplicación
|
|
478
|
+
* - Mecanismo de retry para errores de red
|
|
479
|
+
* - Sincronización cross-tab vía SessionProvider
|
|
480
|
+
* - Formateo extendido de datos para display
|
|
481
|
+
* - Limpieza apropiada y gestión de memoria
|
|
482
|
+
* - Compatible 100% con API de useCrudifyUser legacy
|
|
483
|
+
* - Usa el nuevo sistema de refresh tokens por debajo
|
|
484
|
+
*/
|
|
485
|
+
declare const useUserData: (options?: UseUserDataOptions) => UseUserDataReturn;
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Return type compatible con useCrudifyAuth legacy
|
|
489
|
+
*/
|
|
490
|
+
interface UseAuthReturn {
|
|
491
|
+
isAuthenticated: boolean;
|
|
492
|
+
loading: boolean;
|
|
493
|
+
error: string | null;
|
|
494
|
+
token: string | null;
|
|
495
|
+
user: Record<string, unknown> | null;
|
|
496
|
+
tokenExpiration: Date | null;
|
|
497
|
+
setToken: (token: string | null) => void;
|
|
498
|
+
logout: () => Promise<void>;
|
|
499
|
+
refreshToken: () => Promise<boolean>;
|
|
500
|
+
login: (email: string, password: string) => Promise<LoginResult>;
|
|
501
|
+
isExpiringSoon: boolean;
|
|
502
|
+
expiresIn: number;
|
|
503
|
+
refreshExpiresIn: number;
|
|
504
|
+
getTokenInfo: () => ReturnType<SessionContextType["getTokenInfo"]>;
|
|
505
|
+
clearError: () => void;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* useAuth - Hook de autenticación completo
|
|
509
|
+
*
|
|
510
|
+
* Este hook reemplaza completamente a useCrudifyAuth del sistema legacy
|
|
511
|
+
* manteniendo 100% compatibilidad de API pero usando el nuevo SessionProvider
|
|
512
|
+
* que incluye Refresh Token Pattern, almacenamiento seguro, y gestión automática
|
|
513
|
+
* de expiración de tokens.
|
|
514
|
+
*
|
|
515
|
+
* Funcionalidades completas:
|
|
516
|
+
* - Estado de autenticación en tiempo real
|
|
517
|
+
* - Validación automática de tokens
|
|
518
|
+
* - Sincronización cross-tab
|
|
519
|
+
* - Acciones simples login/logout
|
|
520
|
+
* - Acceso al payload JWT vía sessionData
|
|
521
|
+
* - Refresh automático de tokens
|
|
522
|
+
* - Gestión de expiración de sesiones
|
|
523
|
+
* - Almacenamiento seguro y encriptado
|
|
524
|
+
* - Compatibilidad 100% con API legacy
|
|
525
|
+
*
|
|
526
|
+
* @example
|
|
527
|
+
* ```tsx
|
|
528
|
+
* function LoginComponent() {
|
|
529
|
+
* const { isAuthenticated, login, logout, user } = useAuth();
|
|
530
|
+
*
|
|
531
|
+
* if (isAuthenticated) {
|
|
532
|
+
* return (
|
|
533
|
+
* <div>
|
|
534
|
+
* Welcome {user?.email}!
|
|
535
|
+
* <button onClick={logout}>Logout</button>
|
|
536
|
+
* </div>
|
|
537
|
+
* );
|
|
538
|
+
* }
|
|
539
|
+
*
|
|
540
|
+
* return <LoginForm onLogin={login} />;
|
|
541
|
+
* }
|
|
542
|
+
* ```
|
|
543
|
+
*/
|
|
544
|
+
declare const useAuth: () => UseAuthReturn;
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Return type compatible con useCrudifyData legacy
|
|
548
|
+
*/
|
|
549
|
+
interface UseDataReturn {
|
|
550
|
+
readItems: (moduleKey: string, filter?: object, options?: CrudifyRequestOptions) => Promise<CrudifyApiResponse>;
|
|
551
|
+
readItem: (moduleKey: string, filter: object, options?: CrudifyRequestOptions) => Promise<CrudifyApiResponse>;
|
|
552
|
+
createItem: (moduleKey: string, data: object, options?: CrudifyRequestOptions) => Promise<CrudifyApiResponse>;
|
|
553
|
+
updateItem: (moduleKey: string, data: object, options?: CrudifyRequestOptions) => Promise<CrudifyApiResponse>;
|
|
554
|
+
deleteItem: (moduleKey: string, id: string, options?: CrudifyRequestOptions) => Promise<CrudifyApiResponse>;
|
|
555
|
+
transaction: (operations: TransactionInput, options?: CrudifyRequestOptions) => Promise<CrudifyApiResponse>;
|
|
556
|
+
login: (email: string, password: string) => Promise<CrudifyApiResponse>;
|
|
557
|
+
isInitialized: boolean;
|
|
558
|
+
isInitializing: boolean;
|
|
559
|
+
initializationError: string | null;
|
|
560
|
+
isReady: () => boolean;
|
|
561
|
+
waitForReady: () => Promise<void>;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* useData - Hook completo para operaciones de datos
|
|
565
|
+
*
|
|
566
|
+
* Este hook reemplaza completamente a useCrudifyData del sistema legacy
|
|
567
|
+
* manteniendo 100% compatibilidad de API pero usando el nuevo SessionProvider
|
|
568
|
+
* que proporciona mejor manejo de estados y errores.
|
|
569
|
+
*
|
|
570
|
+
* Funcionalidades completas:
|
|
571
|
+
* - Verificación automática de inicialización
|
|
572
|
+
* - Operaciones CRUD type-safe
|
|
573
|
+
* - Soporte para transacciones
|
|
574
|
+
* - Operaciones de login
|
|
575
|
+
* - Gestión de estados ready
|
|
576
|
+
* - Manejo apropiado de errores
|
|
577
|
+
* - Compatible 100% con API legacy
|
|
578
|
+
*
|
|
579
|
+
* Todas las operaciones verifican que el sistema esté inicializado correctamente,
|
|
580
|
+
* asegurando integridad de datos y previniendo fallas silenciosas.
|
|
581
|
+
*
|
|
582
|
+
* @example
|
|
583
|
+
* ```tsx
|
|
584
|
+
* function DataComponent() {
|
|
585
|
+
* const {
|
|
586
|
+
* readItems,
|
|
587
|
+
* createItem,
|
|
588
|
+
* isInitialized,
|
|
589
|
+
* isReady
|
|
590
|
+
* } = useData();
|
|
591
|
+
*
|
|
592
|
+
* const loadUsers = async () => {
|
|
593
|
+
* if (!isReady()) {
|
|
594
|
+
* console.warn("System not ready yet");
|
|
595
|
+
* return;
|
|
596
|
+
* }
|
|
597
|
+
*
|
|
598
|
+
* try {
|
|
599
|
+
* const response = await readItems("users", { limit: 10 });
|
|
600
|
+
* if (response.success) {
|
|
601
|
+
* console.log("Users:", response.data);
|
|
602
|
+
* }
|
|
603
|
+
* } catch (error) {
|
|
604
|
+
* console.error("Error loading users:", error);
|
|
605
|
+
* }
|
|
606
|
+
* };
|
|
607
|
+
*
|
|
608
|
+
* return (
|
|
609
|
+
* <div>
|
|
610
|
+
* <button onClick={loadUsers} disabled={!isInitialized}>
|
|
611
|
+
* Load Users
|
|
612
|
+
* </button>
|
|
613
|
+
* </div>
|
|
614
|
+
* );
|
|
615
|
+
* }
|
|
616
|
+
* ```
|
|
617
|
+
*/
|
|
618
|
+
declare const useData: () => UseDataReturn;
|
|
619
|
+
|
|
620
|
+
interface UseUserProfileOptions {
|
|
621
|
+
autoFetch?: boolean;
|
|
622
|
+
retryOnError?: boolean;
|
|
623
|
+
maxRetries?: number;
|
|
624
|
+
}
|
|
625
|
+
interface UseUserProfileReturn {
|
|
626
|
+
userProfile: UserProfile | null;
|
|
627
|
+
loading: boolean;
|
|
628
|
+
error: string | null;
|
|
629
|
+
extendedData: Record<string, any>;
|
|
630
|
+
refreshProfile: () => Promise<void>;
|
|
631
|
+
clearProfile: () => void;
|
|
632
|
+
}
|
|
633
|
+
declare const useUserProfile: (options?: UseUserProfileOptions) => UseUserProfileReturn;
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Complete hook for file handling with:
|
|
637
|
+
* - Progressive upload to S3 with pre-signed URLs
|
|
638
|
+
* - Per-file progress tracking
|
|
639
|
+
* - Type and size validation
|
|
640
|
+
* - Soft delete (disableFile)
|
|
641
|
+
* - Multiple file support
|
|
642
|
+
*/
|
|
643
|
+
/**
|
|
644
|
+
* Individual file status
|
|
645
|
+
*/
|
|
646
|
+
type FileStatus = "pending" | "uploading" | "completed" | "error" | "removing" | "pendingDeletion";
|
|
647
|
+
/**
|
|
648
|
+
* Represents a file in the system
|
|
649
|
+
*/
|
|
650
|
+
interface FileItem {
|
|
651
|
+
/** Unique file ID (generated or from server) */
|
|
652
|
+
id: string;
|
|
653
|
+
/** Original file name */
|
|
654
|
+
name: string;
|
|
655
|
+
/** Size in bytes */
|
|
656
|
+
size: number;
|
|
657
|
+
/** MIME content type */
|
|
658
|
+
contentType: string;
|
|
659
|
+
/** Current file status */
|
|
660
|
+
status: FileStatus;
|
|
661
|
+
/** Upload progress (0-100) */
|
|
662
|
+
progress: number;
|
|
663
|
+
/**
|
|
664
|
+
* Relative file path (includes visibility)
|
|
665
|
+
* Format: "public/path/file.ext" or "private/path/file.ext"
|
|
666
|
+
*/
|
|
667
|
+
filePath?: string;
|
|
668
|
+
/**
|
|
669
|
+
* File visibility
|
|
670
|
+
* Extracted from filePath for convenience
|
|
671
|
+
*/
|
|
672
|
+
visibility?: "public" | "private";
|
|
673
|
+
/** Public URL for public files */
|
|
674
|
+
publicUrl?: string;
|
|
675
|
+
/** Preview URL (for images) */
|
|
676
|
+
previewUrl?: string;
|
|
677
|
+
/** Error message if failed */
|
|
678
|
+
errorMessage?: string;
|
|
679
|
+
/** Creation timestamp */
|
|
680
|
+
createdAt: number;
|
|
681
|
+
/** Original file (only during upload) */
|
|
682
|
+
file?: File;
|
|
683
|
+
/** Whether this file existed before (was loaded from server) */
|
|
684
|
+
isExisting?: boolean;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Hook configuration
|
|
688
|
+
*/
|
|
689
|
+
interface UseFileUploadOptions {
|
|
690
|
+
/** Allowed MIME types (e.g., ["image/png", "image/jpeg", "application/pdf"]) */
|
|
691
|
+
acceptedTypes?: string[];
|
|
692
|
+
/** Maximum file size in bytes (default: 10MB) */
|
|
693
|
+
maxFileSize?: number;
|
|
694
|
+
/** Maximum number of files (undefined = no limit) */
|
|
695
|
+
maxFiles?: number;
|
|
696
|
+
/** Minimum number of required files (default: 0) */
|
|
697
|
+
minFiles?: number;
|
|
698
|
+
/**
|
|
699
|
+
* Visibility of uploaded files
|
|
700
|
+
* @default "private"
|
|
701
|
+
*/
|
|
702
|
+
visibility?: "public" | "private";
|
|
703
|
+
/** Callback when an upload completes successfully */
|
|
704
|
+
onUploadComplete?: (file: FileItem) => void;
|
|
705
|
+
/** Callback when an upload fails */
|
|
706
|
+
onUploadError?: (file: FileItem, error: string) => void;
|
|
707
|
+
/** Callback when a file is removed */
|
|
708
|
+
onFileRemoved?: (file: FileItem) => void;
|
|
709
|
+
/** Callback when the file list changes */
|
|
710
|
+
onFilesChange?: (files: FileItem[]) => void;
|
|
711
|
+
/** Form mode: 'create' or 'edit' - affects delete behavior */
|
|
712
|
+
mode?: "create" | "edit";
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Hook return type
|
|
716
|
+
*/
|
|
717
|
+
interface UseFileUploadReturn {
|
|
718
|
+
/** Current file list */
|
|
719
|
+
files: FileItem[];
|
|
720
|
+
/** Active files (excluding pendingDeletion) */
|
|
721
|
+
activeFiles: FileItem[];
|
|
722
|
+
/** Count of active files */
|
|
723
|
+
activeFileCount: number;
|
|
724
|
+
/** Whether uploads are in progress */
|
|
725
|
+
isUploading: boolean;
|
|
726
|
+
/** Number of pending uploads */
|
|
727
|
+
pendingCount: number;
|
|
728
|
+
/** Add files (triggers automatic upload) */
|
|
729
|
+
addFiles: (files: FileList | File[]) => Promise<void>;
|
|
730
|
+
/** Remove a file - returns whether confirmation is needed */
|
|
731
|
+
removeFile: (fileId: string) => Promise<{
|
|
732
|
+
needsConfirmation: boolean;
|
|
733
|
+
isExisting: boolean;
|
|
734
|
+
}>;
|
|
735
|
+
/** Delete a file immediately from server (for new files or create mode) */
|
|
736
|
+
deleteFileImmediately: (fileId: string) => Promise<{
|
|
737
|
+
success: boolean;
|
|
738
|
+
error?: string;
|
|
739
|
+
}>;
|
|
740
|
+
/** Restore a file that was marked for deletion */
|
|
741
|
+
restoreFile: (fileId: string) => boolean;
|
|
742
|
+
/** Clear all files */
|
|
743
|
+
clearFiles: () => void;
|
|
744
|
+
/** Retry upload for a failed file */
|
|
745
|
+
retryUpload: (fileId: string) => Promise<void>;
|
|
746
|
+
/** Validate if minimum requirements are met */
|
|
747
|
+
isValid: boolean;
|
|
748
|
+
/** Validation error message (i18n key) */
|
|
749
|
+
validationError: string | null;
|
|
750
|
+
/** Validation error i18n key */
|
|
751
|
+
validationErrorKey: string | null;
|
|
752
|
+
/** Validation error params for i18n interpolation */
|
|
753
|
+
validationErrorParams: Record<string, string | number>;
|
|
754
|
+
/** Wait for all uploads to complete and return completed file paths */
|
|
755
|
+
waitForUploads: () => Promise<string[]>;
|
|
756
|
+
/**
|
|
757
|
+
* Completed file paths (for saving in form)
|
|
758
|
+
* Relative paths with visibility - subscriberKey is added in backend
|
|
759
|
+
*/
|
|
760
|
+
completedFilePaths: string[];
|
|
761
|
+
/** Initialize with existing files (for editing) */
|
|
762
|
+
initializeFiles: (existingFiles: Array<{
|
|
763
|
+
filePath: string;
|
|
764
|
+
name: string;
|
|
765
|
+
size?: number;
|
|
766
|
+
contentType?: string;
|
|
767
|
+
}>, baseUrl?: string) => void;
|
|
768
|
+
/** Whether the user has interacted with the field */
|
|
769
|
+
isTouched: boolean;
|
|
770
|
+
/** Mark the field as touched (to show validation errors) */
|
|
771
|
+
markAsTouched: () => void;
|
|
772
|
+
/** Whether the form has been submitted */
|
|
773
|
+
isSubmitted: boolean;
|
|
774
|
+
/** Mark the form as submitted (to show all validation errors) */
|
|
775
|
+
markAsSubmitted: () => void;
|
|
776
|
+
/**
|
|
777
|
+
* Get URL for file preview
|
|
778
|
+
* - Public: returns publicUrl directly
|
|
779
|
+
* - Private: requests signed URL from backend
|
|
780
|
+
*/
|
|
781
|
+
getPreviewUrl: (fileId: string) => Promise<string | null>;
|
|
782
|
+
/** List of file IDs pending deletion */
|
|
783
|
+
pendingDeletions: string[];
|
|
784
|
+
/** Whether there are files pending deletion */
|
|
785
|
+
hasPendingDeletions: boolean;
|
|
786
|
+
/** Execute all pending deletions (call this on form submit) */
|
|
787
|
+
commitDeletions: () => Promise<{
|
|
788
|
+
success: boolean;
|
|
789
|
+
errors: string[];
|
|
790
|
+
}>;
|
|
791
|
+
/** Cancel all pending deletions and restore files */
|
|
792
|
+
restorePendingDeletions: () => void;
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Hook for complete file handling with S3 upload
|
|
796
|
+
*
|
|
797
|
+
* @example
|
|
798
|
+
* ```tsx
|
|
799
|
+
* const {
|
|
800
|
+
* files,
|
|
801
|
+
* addFiles,
|
|
802
|
+
* removeFile,
|
|
803
|
+
* isUploading,
|
|
804
|
+
* isValid,
|
|
805
|
+
* completedS3Keys
|
|
806
|
+
* } = useFileUpload({
|
|
807
|
+
* acceptedTypes: ["image/png", "image/jpeg", "application/pdf"],
|
|
808
|
+
* maxFileSize: 5 * 1024 * 1024, // 5MB
|
|
809
|
+
* maxFiles: 3,
|
|
810
|
+
* minFiles: 1
|
|
811
|
+
* });
|
|
812
|
+
*
|
|
813
|
+
* // In form submit
|
|
814
|
+
* const handleSubmit = async () => {
|
|
815
|
+
* await waitForUploads(); // Wait for pending uploads
|
|
816
|
+
* if (!isValid) return;
|
|
817
|
+
*
|
|
818
|
+
* await crudify.createItem("documents", {
|
|
819
|
+
* files: completedS3Keys
|
|
820
|
+
* });
|
|
821
|
+
* };
|
|
822
|
+
* ```
|
|
823
|
+
*/
|
|
824
|
+
declare const useFileUpload: (options?: UseFileUploadOptions) => UseFileUploadReturn;
|
|
825
|
+
|
|
826
|
+
/** App structure action configuration */
|
|
827
|
+
interface AppStructureAction {
|
|
828
|
+
key: string;
|
|
829
|
+
moduleKey?: string;
|
|
830
|
+
[key: string]: unknown;
|
|
831
|
+
}
|
|
832
|
+
interface CrudifyWithNotificationsOptions {
|
|
833
|
+
showSuccessNotifications?: boolean;
|
|
834
|
+
showErrorNotifications?: boolean;
|
|
835
|
+
customErrorMessages?: Record<string, string>;
|
|
836
|
+
defaultErrorMessage?: string;
|
|
837
|
+
autoHideDuration?: number;
|
|
838
|
+
appStructure?: AppStructureAction[];
|
|
839
|
+
translateFn?: (key: string, options?: Record<string, unknown>) => string;
|
|
840
|
+
}
|
|
841
|
+
declare const useCrudifyWithNotifications: (options?: CrudifyWithNotificationsOptions) => {
|
|
842
|
+
createItem: (moduleKey: string, data: object, options?: CrudifyOperationOptions) => Promise<CrudifyResponse>;
|
|
843
|
+
updateItem: (moduleKey: string, data: object, options?: CrudifyOperationOptions) => Promise<CrudifyResponse>;
|
|
844
|
+
deleteItem: (moduleKey: string, id: string, options?: CrudifyOperationOptions) => Promise<CrudifyResponse>;
|
|
845
|
+
readItem: (moduleKey: string, filter: object, options?: CrudifyOperationOptions) => Promise<CrudifyResponse>;
|
|
846
|
+
readItems: (moduleKey: string, filter: object, options?: CrudifyOperationOptions) => Promise<CrudifyResponse>;
|
|
847
|
+
transaction: (data: TransactionInput, options?: CrudifyOperationOptions) => Promise<CrudifyResponse>;
|
|
848
|
+
handleResponse: (response: CrudifyResponse, successMessage?: string) => CrudifyResponse;
|
|
849
|
+
getErrorMessage: (response: CrudifyResponse) => string;
|
|
850
|
+
getErrorSeverity: (response: CrudifyResponse) => NotificationSeverity;
|
|
851
|
+
shouldShowNotification: (response: CrudifyResponse) => boolean;
|
|
852
|
+
};
|
|
853
|
+
|
|
854
|
+
export { type FileItem as F, type LoginResult as L, type NotificationOptions as N, SessionManager as S, TokenStorage as T, type UseSessionOptions as U, type SessionConfig as a, type TokenData as b, type StorageType as c, type SessionState as d, SessionProvider as e, useSessionContext as f, SessionDebugInfo as g, type SessionProviderProps as h, useUserData as i, type UseUserDataReturn as j, type UseUserDataOptions as k, type UserData as l, useAuth as m, type UseAuthReturn as n, useData as o, type UseDataReturn as p, useUserProfile as q, useFileUpload as r, type UseFileUploadOptions as s, type UseFileUploadReturn as t, useSession as u, type FileStatus as v, useCrudifyWithNotifications as w };
|