@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.
Files changed (53) hide show
  1. package/.github/workflows/test.yml +59 -0
  2. package/.nvmrc +1 -0
  3. package/README.md +398 -0
  4. package/README_DEPTH.md +1230 -0
  5. package/coverage/base.css +224 -0
  6. package/coverage/block-navigation.js +87 -0
  7. package/coverage/coverage-final.json +85 -0
  8. package/coverage/favicon.png +0 -0
  9. package/coverage/index.html +506 -0
  10. package/coverage/prettify.css +1 -0
  11. package/coverage/prettify.js +2 -0
  12. package/coverage/sort-arrow-sprite.png +0 -0
  13. package/coverage/sorter.js +210 -0
  14. package/dist/CrudiaMarkdownField-C54-A_J3.d.mts +328 -0
  15. package/dist/CrudiaMarkdownField-C8HQh7s5.d.ts +328 -0
  16. package/dist/GlobalNotificationProvider-Zq18OkpI.d.mts +96 -0
  17. package/dist/GlobalNotificationProvider-Zq18OkpI.d.ts +96 -0
  18. package/dist/api-B4uXiHF0.d.mts +118 -0
  19. package/dist/api-B4uXiHF0.d.ts +118 -0
  20. package/dist/chunk-2XOTIEKS.js +1 -0
  21. package/dist/chunk-5HFI5CZ5.js +1 -0
  22. package/dist/chunk-CHDM7KGH.js +1 -0
  23. package/dist/chunk-HVTRRU4W.mjs +1 -0
  24. package/dist/chunk-JAPL7EZJ.mjs +1 -0
  25. package/dist/chunk-JNEWPO2J.mjs +1 -0
  26. package/dist/chunk-MFYHD6S5.js +1 -0
  27. package/dist/chunk-MGJZTOEM.mjs +1 -0
  28. package/dist/chunk-NBQH6QOU.mjs +1 -0
  29. package/dist/chunk-NSV6ECYO.js +1 -0
  30. package/dist/chunk-PNI3ZBZV.js +1 -0
  31. package/dist/chunk-U4RS66TB.mjs +1 -0
  32. package/dist/components.d.mts +24 -0
  33. package/dist/components.d.ts +24 -0
  34. package/dist/components.js +1 -0
  35. package/dist/components.mjs +1 -0
  36. package/dist/errorTranslation-DGdrMidg.d.ts +143 -0
  37. package/dist/errorTranslation-qwwQTvCO.d.mts +143 -0
  38. package/dist/hooks.d.mts +6 -0
  39. package/dist/hooks.d.ts +6 -0
  40. package/dist/hooks.js +1 -0
  41. package/dist/hooks.mjs +1 -0
  42. package/dist/index-BUKX3duW.d.ts +854 -0
  43. package/dist/index-Y9tTsinC.d.mts +854 -0
  44. package/dist/index.d.mts +1274 -0
  45. package/dist/index.d.ts +1274 -0
  46. package/dist/index.js +6 -0
  47. package/dist/index.mjs +6 -0
  48. package/dist/utils.d.mts +175 -0
  49. package/dist/utils.d.ts +175 -0
  50. package/dist/utils.js +1 -0
  51. package/dist/utils.mjs +1 -0
  52. package/package.json +88 -0
  53. 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.mjs';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+ import { ReactNode } from 'react';
4
+ import { b as NotificationSeverity } from './GlobalNotificationProvider-Zq18OkpI.mjs';
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 };