@pubflow/react 0.2.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +336 -259
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +336 -260
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -209,67 +209,36 @@ const PubflowContext = React.createContext({
|
|
|
209
209
|
defaultInstance: 'default'
|
|
210
210
|
});
|
|
211
211
|
/**
|
|
212
|
-
* Pubflow
|
|
212
|
+
* Pubflow Provider Component
|
|
213
213
|
*/
|
|
214
|
-
function PubflowProvider({ children, config, instances, defaultInstance = 'default',
|
|
215
|
-
const [isInitialized, setIsInitialized] = React.useState(false);
|
|
214
|
+
function PubflowProvider({ children, config, instances, defaultInstance = 'default', enableDebugTools = false, showSessionAlerts = false, persistentCache = { enabled: false }, theme = {}, loginRedirectPath = '/login', publicPaths = [] }) {
|
|
216
215
|
const [contextValue, setContextValue] = React.useState({
|
|
217
216
|
instances: {},
|
|
218
217
|
defaultInstance
|
|
219
218
|
});
|
|
220
|
-
//
|
|
221
|
-
React.useEffect(() => {
|
|
222
|
-
if (enableDebugTools) {
|
|
223
|
-
console.log('Pubflow debug tools enabled');
|
|
224
|
-
// Add debug utilities to window object
|
|
225
|
-
if (typeof window !== 'undefined') {
|
|
226
|
-
window.pubflowDebug = {
|
|
227
|
-
getInstances: () => contextValue.instances,
|
|
228
|
-
getDefaultInstance: () => contextValue.defaultInstance,
|
|
229
|
-
clearStorage: async () => {
|
|
230
|
-
const storage = new BrowserStorageAdapter();
|
|
231
|
-
await storage.removeItem('pubflow_session_id');
|
|
232
|
-
await storage.removeItem('pubflow_user_data');
|
|
233
|
-
console.log('Pubflow storage cleared');
|
|
234
|
-
},
|
|
235
|
-
loginRedirectPath,
|
|
236
|
-
publicPaths,
|
|
237
|
-
theme
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}, [enableDebugTools]); // ✅ OPTIMIZED: Only enableDebugTools as dependency
|
|
242
|
-
// Handle session expiration
|
|
219
|
+
// Session handlers
|
|
243
220
|
const handleSessionExpired = React.useCallback(() => {
|
|
244
|
-
if (showSessionAlerts) {
|
|
245
|
-
|
|
246
|
-
}
|
|
247
|
-
if (onSessionExpired) {
|
|
248
|
-
onSessionExpired();
|
|
221
|
+
if (showSessionAlerts && typeof window !== 'undefined') {
|
|
222
|
+
console.warn('Session expired');
|
|
249
223
|
}
|
|
250
|
-
}, [
|
|
251
|
-
// Handle session refresh
|
|
224
|
+
}, [showSessionAlerts]);
|
|
252
225
|
const handleSessionRefreshed = React.useCallback(() => {
|
|
253
|
-
if (showSessionAlerts) {
|
|
254
|
-
|
|
226
|
+
if (showSessionAlerts && typeof window !== 'undefined') {
|
|
227
|
+
console.log('Session refreshed');
|
|
255
228
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
-
}, [onSessionRefreshed, showSessionAlerts]);
|
|
229
|
+
}, [showSessionAlerts]);
|
|
230
|
+
// Initialize instances
|
|
260
231
|
React.useEffect(() => {
|
|
261
232
|
let isMounted = true;
|
|
262
233
|
const initialize = async () => {
|
|
263
234
|
var _a, _b;
|
|
264
235
|
try {
|
|
265
|
-
// Initialize instances
|
|
266
236
|
const instancesMap = {};
|
|
267
237
|
if (instances && instances.length > 0) {
|
|
268
238
|
// Initialize multiple instances
|
|
269
239
|
for (const instanceConfig of instances) {
|
|
270
240
|
if (!isMounted)
|
|
271
|
-
return;
|
|
272
|
-
// Initialize configuration
|
|
241
|
+
return;
|
|
273
242
|
const fullConfig = core.initConfig({
|
|
274
243
|
...instanceConfig,
|
|
275
244
|
sessionConfig: {
|
|
@@ -278,38 +247,21 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
278
247
|
onSessionRefreshed: handleSessionRefreshed
|
|
279
248
|
}
|
|
280
249
|
}, instanceConfig.id);
|
|
281
|
-
// Create storage adapter
|
|
282
250
|
const storage = new BrowserStorageAdapter({
|
|
283
251
|
prefix: (_a = fullConfig.storageConfig) === null || _a === void 0 ? void 0 : _a.prefix
|
|
284
252
|
});
|
|
285
|
-
// Create API client
|
|
286
253
|
const apiClient = new core.ApiClient(fullConfig, storage);
|
|
287
|
-
// Create auth service
|
|
288
254
|
const authService = new core.AuthService(apiClient, storage, fullConfig);
|
|
289
|
-
// Get current user (
|
|
255
|
+
// Get current user (non-blocking)
|
|
290
256
|
let user = null;
|
|
291
257
|
let isAuthenticated = false;
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
[instanceConfig.id]: {
|
|
300
|
-
...prev.instances[instanceConfig.id],
|
|
301
|
-
user: currentUser,
|
|
302
|
-
isAuthenticated: true,
|
|
303
|
-
isLoading: false
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}));
|
|
307
|
-
}
|
|
308
|
-
}).catch(error => {
|
|
309
|
-
console.error(`Error getting current user for instance ${instanceConfig.id}:`, error);
|
|
310
|
-
});
|
|
311
|
-
// Create instance with optimized functions
|
|
312
|
-
const createInstanceFunctions = (id) => ({
|
|
258
|
+
instancesMap[instanceConfig.id] = {
|
|
259
|
+
config: fullConfig,
|
|
260
|
+
apiClient,
|
|
261
|
+
authService,
|
|
262
|
+
user,
|
|
263
|
+
isAuthenticated,
|
|
264
|
+
isLoading: true,
|
|
313
265
|
login: async (credentials) => {
|
|
314
266
|
const result = await authService.login(credentials);
|
|
315
267
|
if (result.success && result.user && isMounted) {
|
|
@@ -317,10 +269,11 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
317
269
|
...prev,
|
|
318
270
|
instances: {
|
|
319
271
|
...prev.instances,
|
|
320
|
-
[id]: {
|
|
321
|
-
...prev.instances[id],
|
|
272
|
+
[instanceConfig.id]: {
|
|
273
|
+
...prev.instances[instanceConfig.id],
|
|
322
274
|
user: result.user,
|
|
323
|
-
isAuthenticated: true
|
|
275
|
+
isAuthenticated: true,
|
|
276
|
+
isLoading: false
|
|
324
277
|
}
|
|
325
278
|
}
|
|
326
279
|
}));
|
|
@@ -334,10 +287,11 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
334
287
|
...prev,
|
|
335
288
|
instances: {
|
|
336
289
|
...prev.instances,
|
|
337
|
-
[id]: {
|
|
338
|
-
...prev.instances[id],
|
|
290
|
+
[instanceConfig.id]: {
|
|
291
|
+
...prev.instances[instanceConfig.id],
|
|
339
292
|
user: null,
|
|
340
|
-
isAuthenticated: false
|
|
293
|
+
isAuthenticated: false,
|
|
294
|
+
isLoading: false
|
|
341
295
|
}
|
|
342
296
|
}
|
|
343
297
|
}));
|
|
@@ -350,31 +304,52 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
350
304
|
...prev,
|
|
351
305
|
instances: {
|
|
352
306
|
...prev.instances,
|
|
353
|
-
[id]: {
|
|
354
|
-
...prev.instances[id],
|
|
307
|
+
[instanceConfig.id]: {
|
|
308
|
+
...prev.instances[instanceConfig.id],
|
|
355
309
|
user: result.user || null,
|
|
356
|
-
isAuthenticated: result.isValid
|
|
310
|
+
isAuthenticated: result.isValid,
|
|
311
|
+
isLoading: false
|
|
357
312
|
}
|
|
358
313
|
}
|
|
359
314
|
}));
|
|
360
315
|
}
|
|
361
316
|
return result;
|
|
362
317
|
}
|
|
363
|
-
});
|
|
364
|
-
instancesMap[instanceConfig.id] = {
|
|
365
|
-
config: fullConfig,
|
|
366
|
-
apiClient,
|
|
367
|
-
authService,
|
|
368
|
-
user,
|
|
369
|
-
isAuthenticated,
|
|
370
|
-
isLoading: true, // Start as loading
|
|
371
|
-
...createInstanceFunctions(instanceConfig.id)
|
|
372
318
|
};
|
|
319
|
+
// Load user asynchronously
|
|
320
|
+
authService.getCurrentUser().then(currentUser => {
|
|
321
|
+
if (isMounted) {
|
|
322
|
+
setContextValue(prev => ({
|
|
323
|
+
...prev,
|
|
324
|
+
instances: {
|
|
325
|
+
...prev.instances,
|
|
326
|
+
[instanceConfig.id]: {
|
|
327
|
+
...prev.instances[instanceConfig.id],
|
|
328
|
+
user: currentUser,
|
|
329
|
+
isAuthenticated: !!currentUser,
|
|
330
|
+
isLoading: false
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}));
|
|
334
|
+
}
|
|
335
|
+
}).catch(() => {
|
|
336
|
+
if (isMounted) {
|
|
337
|
+
setContextValue(prev => ({
|
|
338
|
+
...prev,
|
|
339
|
+
instances: {
|
|
340
|
+
...prev.instances,
|
|
341
|
+
[instanceConfig.id]: {
|
|
342
|
+
...prev.instances[instanceConfig.id],
|
|
343
|
+
isLoading: false
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}));
|
|
347
|
+
}
|
|
348
|
+
});
|
|
373
349
|
}
|
|
374
350
|
}
|
|
375
351
|
else if (config) {
|
|
376
|
-
//
|
|
377
|
-
// Initialize configuration
|
|
352
|
+
// Single instance mode (simplified)
|
|
378
353
|
const fullConfig = core.initConfig({
|
|
379
354
|
...config,
|
|
380
355
|
sessionConfig: {
|
|
@@ -382,37 +357,22 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
382
357
|
onSessionExpired: handleSessionExpired,
|
|
383
358
|
onSessionRefreshed: handleSessionRefreshed
|
|
384
359
|
}
|
|
385
|
-
}, defaultInstance);
|
|
386
|
-
// Create storage adapter
|
|
360
|
+
}, config.id || defaultInstance);
|
|
387
361
|
const storage = new BrowserStorageAdapter({
|
|
388
362
|
prefix: (_b = fullConfig.storageConfig) === null || _b === void 0 ? void 0 : _b.prefix
|
|
389
363
|
});
|
|
390
|
-
// Create API client
|
|
391
364
|
const apiClient = new core.ApiClient(fullConfig, storage);
|
|
392
|
-
// Create auth service
|
|
393
365
|
const authService = new core.AuthService(apiClient, storage, fullConfig);
|
|
394
|
-
// Get current user
|
|
395
|
-
let user = null;
|
|
396
|
-
let isAuthenticated = false;
|
|
397
|
-
try {
|
|
398
|
-
user = await authService.getCurrentUser();
|
|
399
|
-
isAuthenticated = !!user;
|
|
400
|
-
}
|
|
401
|
-
catch (error) {
|
|
402
|
-
console.error('Error getting current user:', error);
|
|
403
|
-
}
|
|
404
|
-
// Create instance
|
|
405
366
|
instancesMap[defaultInstance] = {
|
|
406
367
|
config: fullConfig,
|
|
407
368
|
apiClient,
|
|
408
369
|
authService,
|
|
409
|
-
user,
|
|
410
|
-
isAuthenticated,
|
|
411
|
-
isLoading:
|
|
370
|
+
user: null,
|
|
371
|
+
isAuthenticated: false,
|
|
372
|
+
isLoading: true,
|
|
412
373
|
login: async (credentials) => {
|
|
413
374
|
const result = await authService.login(credentials);
|
|
414
|
-
if (result.success && result.user) {
|
|
415
|
-
// Update instance
|
|
375
|
+
if (result.success && result.user && isMounted) {
|
|
416
376
|
setContextValue(prev => ({
|
|
417
377
|
...prev,
|
|
418
378
|
instances: {
|
|
@@ -420,7 +380,8 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
420
380
|
[defaultInstance]: {
|
|
421
381
|
...prev.instances[defaultInstance],
|
|
422
382
|
user: result.user,
|
|
423
|
-
isAuthenticated: true
|
|
383
|
+
isAuthenticated: true,
|
|
384
|
+
isLoading: false
|
|
424
385
|
}
|
|
425
386
|
}
|
|
426
387
|
}));
|
|
@@ -429,65 +390,107 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
429
390
|
},
|
|
430
391
|
logout: async () => {
|
|
431
392
|
await authService.logout();
|
|
432
|
-
|
|
393
|
+
if (isMounted) {
|
|
394
|
+
setContextValue(prev => ({
|
|
395
|
+
...prev,
|
|
396
|
+
instances: {
|
|
397
|
+
...prev.instances,
|
|
398
|
+
[defaultInstance]: {
|
|
399
|
+
...prev.instances[defaultInstance],
|
|
400
|
+
user: null,
|
|
401
|
+
isAuthenticated: false,
|
|
402
|
+
isLoading: false
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}));
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
validateSession: async () => {
|
|
409
|
+
const result = await authService.validateSession();
|
|
410
|
+
if (isMounted) {
|
|
411
|
+
setContextValue(prev => ({
|
|
412
|
+
...prev,
|
|
413
|
+
instances: {
|
|
414
|
+
...prev.instances,
|
|
415
|
+
[defaultInstance]: {
|
|
416
|
+
...prev.instances[defaultInstance],
|
|
417
|
+
user: result.user || null,
|
|
418
|
+
isAuthenticated: result.isValid,
|
|
419
|
+
isLoading: false
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}));
|
|
423
|
+
}
|
|
424
|
+
return result;
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
// Load user asynchronously
|
|
428
|
+
authService.getCurrentUser().then(currentUser => {
|
|
429
|
+
if (isMounted) {
|
|
433
430
|
setContextValue(prev => ({
|
|
434
431
|
...prev,
|
|
435
432
|
instances: {
|
|
436
433
|
...prev.instances,
|
|
437
434
|
[defaultInstance]: {
|
|
438
435
|
...prev.instances[defaultInstance],
|
|
439
|
-
user:
|
|
440
|
-
isAuthenticated:
|
|
436
|
+
user: currentUser,
|
|
437
|
+
isAuthenticated: !!currentUser,
|
|
438
|
+
isLoading: false
|
|
441
439
|
}
|
|
442
440
|
}
|
|
443
441
|
}));
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
// Update instance
|
|
442
|
+
}
|
|
443
|
+
}).catch(() => {
|
|
444
|
+
if (isMounted) {
|
|
448
445
|
setContextValue(prev => ({
|
|
449
446
|
...prev,
|
|
450
447
|
instances: {
|
|
451
448
|
...prev.instances,
|
|
452
449
|
[defaultInstance]: {
|
|
453
450
|
...prev.instances[defaultInstance],
|
|
454
|
-
|
|
455
|
-
isAuthenticated: result.isValid
|
|
451
|
+
isLoading: false
|
|
456
452
|
}
|
|
457
453
|
}
|
|
458
454
|
}));
|
|
459
|
-
return result;
|
|
460
455
|
}
|
|
461
|
-
};
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
if (isMounted) {
|
|
459
|
+
setContextValue({
|
|
460
|
+
instances: instancesMap,
|
|
461
|
+
defaultInstance
|
|
462
|
+
});
|
|
462
463
|
}
|
|
463
|
-
// Set context value
|
|
464
|
-
setContextValue({
|
|
465
|
-
instances: instancesMap,
|
|
466
|
-
defaultInstance
|
|
467
|
-
});
|
|
468
|
-
// Set initialized
|
|
469
|
-
setIsInitialized(true);
|
|
470
464
|
}
|
|
471
465
|
catch (error) {
|
|
472
466
|
console.error('Error initializing Pubflow:', error);
|
|
473
467
|
}
|
|
474
468
|
};
|
|
475
469
|
initialize();
|
|
476
|
-
// Cleanup function
|
|
477
470
|
return () => {
|
|
478
471
|
isMounted = false;
|
|
479
472
|
};
|
|
480
473
|
}, [config, instances, defaultInstance, handleSessionExpired, handleSessionRefreshed]);
|
|
481
|
-
//
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
474
|
+
// Debug tools (simplified)
|
|
475
|
+
React.useEffect(() => {
|
|
476
|
+
if (enableDebugTools && typeof window !== 'undefined') {
|
|
477
|
+
window.pubflowDebug = {
|
|
478
|
+
getInstances: () => contextValue.instances,
|
|
479
|
+
getDefaultInstance: () => contextValue.defaultInstance
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
}, [enableDebugTools]);
|
|
483
|
+
// SWR configuration
|
|
484
|
+
const swrConfig = {
|
|
485
|
+
revalidateOnFocus: false,
|
|
486
|
+
revalidateOnReconnect: true,
|
|
487
|
+
...(persistentCache.enabled && {
|
|
488
|
+
provider: () => new Map(),
|
|
489
|
+
isOnline: () => true,
|
|
490
|
+
isVisible: () => true
|
|
491
|
+
})
|
|
492
|
+
};
|
|
493
|
+
return (jsxRuntime.jsx(PubflowContext.Provider, { value: contextValue, children: jsxRuntime.jsx(useSWR.SWRConfig, { value: swrConfig, children: children }) }));
|
|
491
494
|
}
|
|
492
495
|
|
|
493
496
|
/**
|
|
@@ -503,7 +506,6 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
503
506
|
*/
|
|
504
507
|
function useAuth(instanceId) {
|
|
505
508
|
const context = React.useContext(PubflowContext);
|
|
506
|
-
const [isLoading, setIsLoading] = React.useState(false);
|
|
507
509
|
if (!context) {
|
|
508
510
|
throw new Error('useAuth must be used within a PubflowProvider');
|
|
509
511
|
}
|
|
@@ -512,68 +514,14 @@ function useAuth(instanceId) {
|
|
|
512
514
|
if (!pubflowInstance) {
|
|
513
515
|
throw new Error(`Pubflow instance '${instance}' not found`);
|
|
514
516
|
}
|
|
515
|
-
// Wrap login to handle loading state
|
|
516
|
-
const login = React.useCallback(async (credentials) => {
|
|
517
|
-
setIsLoading(true);
|
|
518
|
-
try {
|
|
519
|
-
return await pubflowInstance.login(credentials);
|
|
520
|
-
}
|
|
521
|
-
finally {
|
|
522
|
-
setIsLoading(false);
|
|
523
|
-
}
|
|
524
|
-
}, [pubflowInstance]);
|
|
525
|
-
// Wrap logout to handle loading state
|
|
526
|
-
const logout = React.useCallback(async () => {
|
|
527
|
-
setIsLoading(true);
|
|
528
|
-
try {
|
|
529
|
-
await pubflowInstance.logout();
|
|
530
|
-
}
|
|
531
|
-
finally {
|
|
532
|
-
setIsLoading(false);
|
|
533
|
-
}
|
|
534
|
-
}, [pubflowInstance]);
|
|
535
|
-
// Wrap validateSession to handle loading state
|
|
536
|
-
const validateSession = React.useCallback(async () => {
|
|
537
|
-
setIsLoading(true);
|
|
538
|
-
try {
|
|
539
|
-
return await pubflowInstance.validateSession();
|
|
540
|
-
}
|
|
541
|
-
finally {
|
|
542
|
-
setIsLoading(false);
|
|
543
|
-
}
|
|
544
|
-
}, [pubflowInstance]);
|
|
545
|
-
// Add refreshUser function to manually refresh user data
|
|
546
|
-
const refreshUser = React.useCallback(async () => {
|
|
547
|
-
setIsLoading(true);
|
|
548
|
-
try {
|
|
549
|
-
const result = await pubflowInstance.validateSession();
|
|
550
|
-
return result.user || null;
|
|
551
|
-
}
|
|
552
|
-
finally {
|
|
553
|
-
setIsLoading(false);
|
|
554
|
-
}
|
|
555
|
-
}, [pubflowInstance]);
|
|
556
|
-
// Validate session on mount
|
|
557
|
-
React.useEffect(() => {
|
|
558
|
-
const validate = async () => {
|
|
559
|
-
try {
|
|
560
|
-
await validateSession();
|
|
561
|
-
}
|
|
562
|
-
catch (error) {
|
|
563
|
-
console.error('Error validating session:', error);
|
|
564
|
-
}
|
|
565
|
-
};
|
|
566
|
-
validate();
|
|
567
|
-
}, [validateSession]);
|
|
568
517
|
return {
|
|
569
518
|
// Ensure user is never undefined
|
|
570
519
|
user: pubflowInstance.user || null,
|
|
571
520
|
isAuthenticated: pubflowInstance.isAuthenticated,
|
|
572
|
-
isLoading,
|
|
573
|
-
login,
|
|
574
|
-
logout,
|
|
575
|
-
validateSession
|
|
576
|
-
refreshUser
|
|
521
|
+
isLoading: pubflowInstance.isLoading,
|
|
522
|
+
login: pubflowInstance.login,
|
|
523
|
+
logout: pubflowInstance.logout,
|
|
524
|
+
validateSession: pubflowInstance.validateSession
|
|
577
525
|
};
|
|
578
526
|
}
|
|
579
527
|
|
|
@@ -8612,6 +8560,68 @@ function BridgeList({ renderItem, showPagination = true, showSearch = true, show
|
|
|
8612
8560
|
}) })), renderPagination()] })] })] }));
|
|
8613
8561
|
}
|
|
8614
8562
|
|
|
8563
|
+
/**
|
|
8564
|
+
* Asset Utilities for Pubflow React
|
|
8565
|
+
*
|
|
8566
|
+
* Utilities for handling assets like logos, images, and other media files
|
|
8567
|
+
* Supports both external URLs and internal assets with proper Vite/bundler integration
|
|
8568
|
+
*/
|
|
8569
|
+
/**
|
|
8570
|
+
* Process asset URL - supports both external URLs and internal assets
|
|
8571
|
+
*
|
|
8572
|
+
* @param assetUrl - The asset URL to process
|
|
8573
|
+
* @returns Processed URL ready for use in src attributes
|
|
8574
|
+
*/
|
|
8575
|
+
function processAssetUrl(assetUrl) {
|
|
8576
|
+
// Return non-string values as-is (React components, null, undefined)
|
|
8577
|
+
if (!assetUrl || typeof assetUrl !== 'string') {
|
|
8578
|
+
return assetUrl;
|
|
8579
|
+
}
|
|
8580
|
+
// Return empty string as-is (no logo case)
|
|
8581
|
+
if (assetUrl.trim() === '') {
|
|
8582
|
+
return '';
|
|
8583
|
+
}
|
|
8584
|
+
// Check if it's an external URL (starts with http:// or https://)
|
|
8585
|
+
if (assetUrl.startsWith('http://') || assetUrl.startsWith('https://')) {
|
|
8586
|
+
return assetUrl;
|
|
8587
|
+
}
|
|
8588
|
+
// Check if it's a data URL (base64 encoded image)
|
|
8589
|
+
if (assetUrl.startsWith('data:')) {
|
|
8590
|
+
return assetUrl;
|
|
8591
|
+
}
|
|
8592
|
+
// Check if it's already a processed Vite asset (starts with /)
|
|
8593
|
+
if (assetUrl.startsWith('/')) {
|
|
8594
|
+
return assetUrl;
|
|
8595
|
+
}
|
|
8596
|
+
// Check if it's a blob URL
|
|
8597
|
+
if (assetUrl.startsWith('blob:')) {
|
|
8598
|
+
return assetUrl;
|
|
8599
|
+
}
|
|
8600
|
+
// For relative paths or simple filenames, assume they're in the public directory
|
|
8601
|
+
// This handles cases like 'logo.svg', './logo.png', '../assets/logo.jpg', etc.
|
|
8602
|
+
if (assetUrl.includes('.')) {
|
|
8603
|
+
// Remove leading ./ if present
|
|
8604
|
+
const cleanPath = assetUrl.replace(/^\.\//, '');
|
|
8605
|
+
// If it starts with ../, keep it as is (relative to current directory)
|
|
8606
|
+
if (assetUrl.startsWith('../')) {
|
|
8607
|
+
return assetUrl;
|
|
8608
|
+
}
|
|
8609
|
+
// For simple filenames or paths, prepend with /
|
|
8610
|
+
return `/${cleanPath}`;
|
|
8611
|
+
}
|
|
8612
|
+
// Return as-is for any other cases
|
|
8613
|
+
return assetUrl;
|
|
8614
|
+
}
|
|
8615
|
+
/**
|
|
8616
|
+
* Process logo URL specifically - alias for processAssetUrl with better naming
|
|
8617
|
+
*
|
|
8618
|
+
* @param logoUrl - The logo URL to process
|
|
8619
|
+
* @returns Processed URL ready for use in img src
|
|
8620
|
+
*/
|
|
8621
|
+
function processLogoUrl(logoUrl) {
|
|
8622
|
+
return processAssetUrl(logoUrl);
|
|
8623
|
+
}
|
|
8624
|
+
|
|
8615
8625
|
/**
|
|
8616
8626
|
* Professional login form component
|
|
8617
8627
|
*/
|
|
@@ -8792,7 +8802,7 @@ function LoginForm({ config = {}, onSuccess, onError, onPasswordReset, onAccount
|
|
|
8792
8802
|
textAlign: 'center'
|
|
8793
8803
|
}
|
|
8794
8804
|
};
|
|
8795
|
-
return (jsxRuntime.jsxs("div", { className: className, style: styles.container, children: [jsxRuntime.jsxs("div", { style: styles.logoSection, children: [logo && (typeof logo === 'string' ? (jsxRuntime.jsx("img", { src: logo, alt: `${appName} Logo`, style: styles.logo })) : (logo)), jsxRuntime.jsxs("h1", { style: styles.welcomeText, children: ["Welcome to ", appName] }), jsxRuntime.jsx("p", { style: styles.subtitleText, children: "Sign in to your account" })] }), jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [error && (jsxRuntime.jsxs("div", { style: styles.errorContainer, children: [jsxRuntime.jsx("span", { style: { color: '#ff4757', fontSize: '20px' }, children: "\u26A0" }), jsxRuntime.jsx("span", { style: styles.errorText, children: error })] })), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Email Address" }), jsxRuntime.jsxs("div", { style: styles.inputContainer, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\u2709" }), jsxRuntime.jsx("input", { type: "email", style: styles.input, placeholder: "Enter your email", value: email, onChange: (e) => setEmail(e.target.value), autoCapitalize: "none", autoComplete: "email", disabled: isLoading, required: true })] })] }), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Password" }), jsxRuntime.jsxs("div", { style: styles.inputContainer, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\uD83D\uDD12" }), jsxRuntime.jsx("input", { type: showPassword ? 'text' : 'password', style: styles.input, placeholder: "Enter your password", value: password, onChange: (e) => setPassword(e.target.value), autoComplete: "current-password", disabled: isLoading, required: true }), jsxRuntime.jsx("button", { type: "button", style: styles.eyeButton, onClick: () => setShowPassword(!showPassword), disabled: isLoading, children: showPassword ? '👁' : '👁🗨' })] })] }), jsxRuntime.jsxs("div", { style: styles.checkboxContainer, children: [jsxRuntime.jsxs("label", { style: { display: 'flex', alignItems: 'center', fontSize: '14px', color: '#666' }, children: [jsxRuntime.jsx("input", { type: "checkbox", checked: rememberMe, onChange: (e) => setRememberMe(e.target.checked), style: { marginRight: '8px' } }), "Remember me"] }), showPasswordReset && (jsxRuntime.jsx("button", { type: "button", style: { ...styles.linkButton, fontSize: '14px' }, onClick: onPasswordReset, disabled: isLoading, children: "Forgot password?" }))] }), jsxRuntime.jsx("button", { type: "submit", style: {
|
|
8805
|
+
return (jsxRuntime.jsxs("div", { className: className, style: styles.container, children: [jsxRuntime.jsxs("div", { style: styles.logoSection, children: [logo && (typeof logo === 'string' ? (jsxRuntime.jsx("img", { src: processLogoUrl(logo), alt: `${appName} Logo`, style: styles.logo })) : (logo)), jsxRuntime.jsxs("h1", { style: styles.welcomeText, children: ["Welcome to ", appName] }), jsxRuntime.jsx("p", { style: styles.subtitleText, children: "Sign in to your account" })] }), jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [error && (jsxRuntime.jsxs("div", { style: styles.errorContainer, children: [jsxRuntime.jsx("span", { style: { color: '#ff4757', fontSize: '20px' }, children: "\u26A0" }), jsxRuntime.jsx("span", { style: styles.errorText, children: error })] })), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Email Address" }), jsxRuntime.jsxs("div", { style: styles.inputContainer, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\u2709" }), jsxRuntime.jsx("input", { type: "email", style: styles.input, placeholder: "Enter your email", value: email, onChange: (e) => setEmail(e.target.value), autoCapitalize: "none", autoComplete: "email", disabled: isLoading, required: true })] })] }), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Password" }), jsxRuntime.jsxs("div", { style: styles.inputContainer, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\uD83D\uDD12" }), jsxRuntime.jsx("input", { type: showPassword ? 'text' : 'password', style: styles.input, placeholder: "Enter your password", value: password, onChange: (e) => setPassword(e.target.value), autoComplete: "current-password", disabled: isLoading, required: true }), jsxRuntime.jsx("button", { type: "button", style: styles.eyeButton, onClick: () => setShowPassword(!showPassword), disabled: isLoading, children: showPassword ? '👁' : '👁🗨' })] })] }), jsxRuntime.jsxs("div", { style: styles.checkboxContainer, children: [jsxRuntime.jsxs("label", { style: { display: 'flex', alignItems: 'center', fontSize: '14px', color: '#666' }, children: [jsxRuntime.jsx("input", { type: "checkbox", checked: rememberMe, onChange: (e) => setRememberMe(e.target.checked), style: { marginRight: '8px' } }), "Remember me"] }), showPasswordReset && (jsxRuntime.jsx("button", { type: "button", style: { ...styles.linkButton, fontSize: '14px' }, onClick: onPasswordReset, disabled: isLoading, children: "Forgot password?" }))] }), jsxRuntime.jsx("button", { type: "submit", style: {
|
|
8796
8806
|
...styles.loginButton,
|
|
8797
8807
|
opacity: isLoading ? 0.8 : 1,
|
|
8798
8808
|
cursor: isLoading ? 'not-allowed' : 'pointer'
|
|
@@ -9042,7 +9052,7 @@ function PasswordResetForm({ config = {}, onSuccess, onError, onBackToLogin, res
|
|
|
9042
9052
|
const renderStep = () => {
|
|
9043
9053
|
switch (step) {
|
|
9044
9054
|
case 'request':
|
|
9045
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { style: styles.logoSection, children: [logo && (typeof logo === 'string' ? (jsxRuntime.jsx("img", { src: logo, alt: `${appName} Logo`, style: styles.logo })) : (logo)), jsxRuntime.jsx("h1", { style: styles.title, children: "Reset Password" }), jsxRuntime.jsx("p", { style: styles.subtitle, children: "Enter your email to receive reset instructions" })] }), jsxRuntime.jsxs("form", { onSubmit: handleRequestReset, children: [error && (jsxRuntime.jsxs("div", { style: styles.errorContainer, children: [jsxRuntime.jsx("span", { style: { color: '#ff4757', fontSize: '20px' }, children: "\u26A0" }), jsxRuntime.jsx("span", { style: styles.errorText, children: error })] })), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Email Address" }), jsxRuntime.jsxs("div", { style: styles.inputContainer, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\u2709" }), jsxRuntime.jsx("input", { type: "email", style: styles.input, placeholder: "Enter your email", value: email, onChange: (e) => setEmail(e.target.value), autoCapitalize: "none", autoComplete: "email", disabled: isLoading, required: true })] })] }), jsxRuntime.jsx("button", { type: "submit", style: {
|
|
9055
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { style: styles.logoSection, children: [logo && (typeof logo === 'string' ? (jsxRuntime.jsx("img", { src: processLogoUrl(logo), alt: `${appName} Logo`, style: styles.logo })) : (logo)), jsxRuntime.jsx("h1", { style: styles.title, children: "Reset Password" }), jsxRuntime.jsx("p", { style: styles.subtitle, children: "Enter your email to receive reset instructions" })] }), jsxRuntime.jsxs("form", { onSubmit: handleRequestReset, children: [error && (jsxRuntime.jsxs("div", { style: styles.errorContainer, children: [jsxRuntime.jsx("span", { style: { color: '#ff4757', fontSize: '20px' }, children: "\u26A0" }), jsxRuntime.jsx("span", { style: styles.errorText, children: error })] })), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Email Address" }), jsxRuntime.jsxs("div", { style: styles.inputContainer, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\u2709" }), jsxRuntime.jsx("input", { type: "email", style: styles.input, placeholder: "Enter your email", value: email, onChange: (e) => setEmail(e.target.value), autoCapitalize: "none", autoComplete: "email", disabled: isLoading, required: true })] })] }), jsxRuntime.jsx("button", { type: "submit", style: {
|
|
9046
9056
|
...styles.button,
|
|
9047
9057
|
opacity: isLoading ? 0.8 : 1,
|
|
9048
9058
|
cursor: isLoading ? 'not-allowed' : 'pointer'
|
|
@@ -9306,7 +9316,7 @@ function AccountCreationForm({ config = {}, onSuccess, onError, onBackToLogin })
|
|
|
9306
9316
|
const renderStep = () => {
|
|
9307
9317
|
switch (step) {
|
|
9308
9318
|
case 'form':
|
|
9309
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { style: styles.logoSection, children: [logo && (typeof logo === 'string' ? (jsxRuntime.jsx("img", { src: logo, alt: `${appName} Logo`, style: styles.logo })) : (logo)), jsxRuntime.jsx("h1", { style: styles.title, children: "Create Account" }), jsxRuntime.jsxs("p", { style: styles.subtitle, children: ["Join ", appName, " today"] })] }), jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [errors.general && (jsxRuntime.jsxs("div", { style: { ...styles.successContainer, backgroundColor: '#fef2f2', borderColor: '#fecaca' }, children: [jsxRuntime.jsx("span", { style: { color: '#ff4757', fontSize: '20px' }, children: "\u26A0" }), jsxRuntime.jsx("span", { style: { ...styles.successText, color: '#dc2626' }, children: errors.general })] })), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "First Name *" }), jsxRuntime.jsxs("div", { style: { ...styles.inputContainer, ...(errors.name ? styles.inputError : {}) }, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\uD83D\uDC64" }), jsxRuntime.jsx("input", { type: "text", style: styles.input, placeholder: "Enter your first name", value: formData.name, onChange: (e) => updateField('name', e.target.value), autoComplete: "given-name", disabled: isLoading, required: true })] }), errors.name && jsxRuntime.jsx("div", { style: styles.errorText, children: errors.name })] }), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Last Name *" }), jsxRuntime.jsxs("div", { style: { ...styles.inputContainer, ...(errors.lastName ? styles.inputError : {}) }, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\uD83D\uDC64" }), jsxRuntime.jsx("input", { type: "text", style: styles.input, placeholder: "Enter your last name", value: formData.lastName, onChange: (e) => updateField('lastName', e.target.value), autoComplete: "family-name", disabled: isLoading, required: true })] }), errors.lastName && jsxRuntime.jsx("div", { style: styles.errorText, children: errors.lastName })] }), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Email Address *" }), jsxRuntime.jsxs("div", { style: { ...styles.inputContainer, ...(errors.email ? styles.inputError : {}) }, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\u2709" }), jsxRuntime.jsx("input", { type: "email", style: styles.input, placeholder: "Enter your email", value: formData.email, onChange: (e) => updateField('email', e.target.value), autoCapitalize: "none", autoComplete: "email", disabled: isLoading, required: true })] }), errors.email && jsxRuntime.jsx("div", { style: styles.errorText, children: errors.email })] }), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Password *" }), jsxRuntime.jsxs("div", { style: { ...styles.inputContainer, ...(errors.password ? styles.inputError : {}) }, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\uD83D\uDD12" }), jsxRuntime.jsx("input", { type: showPassword ? 'text' : 'password', style: styles.input, placeholder: "Create a password", value: formData.password, onChange: (e) => updateField('password', e.target.value), autoComplete: "new-password", disabled: isLoading, required: true }), jsxRuntime.jsx("button", { type: "button", style: styles.eyeButton, onClick: () => setShowPassword(!showPassword), disabled: isLoading, children: showPassword ? '👁' : '👁🗨' })] }), errors.password && jsxRuntime.jsx("div", { style: styles.errorText, children: errors.password })] }), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Confirm Password *" }), jsxRuntime.jsxs("div", { style: { ...styles.inputContainer, ...(errors.confirmPassword ? styles.inputError : {}) }, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\uD83D\uDD12" }), jsxRuntime.jsx("input", { type: showConfirmPassword ? 'text' : 'password', style: styles.input, placeholder: "Confirm your password", value: formData.confirmPassword, onChange: (e) => updateField('confirmPassword', e.target.value), autoComplete: "new-password", disabled: isLoading, required: true }), jsxRuntime.jsx("button", { type: "button", style: styles.eyeButton, onClick: () => setShowConfirmPassword(!showConfirmPassword), disabled: isLoading, children: showConfirmPassword ? '👁' : '👁🗨' })] }), errors.confirmPassword && jsxRuntime.jsx("div", { style: styles.errorText, children: errors.confirmPassword })] }), jsxRuntime.jsx("button", { type: "submit", style: {
|
|
9319
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { style: styles.logoSection, children: [logo && (typeof logo === 'string' ? (jsxRuntime.jsx("img", { src: processLogoUrl(logo), alt: `${appName} Logo`, style: styles.logo })) : (logo)), jsxRuntime.jsx("h1", { style: styles.title, children: "Create Account" }), jsxRuntime.jsxs("p", { style: styles.subtitle, children: ["Join ", appName, " today"] })] }), jsxRuntime.jsxs("form", { onSubmit: handleSubmit, children: [errors.general && (jsxRuntime.jsxs("div", { style: { ...styles.successContainer, backgroundColor: '#fef2f2', borderColor: '#fecaca' }, children: [jsxRuntime.jsx("span", { style: { color: '#ff4757', fontSize: '20px' }, children: "\u26A0" }), jsxRuntime.jsx("span", { style: { ...styles.successText, color: '#dc2626' }, children: errors.general })] })), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "First Name *" }), jsxRuntime.jsxs("div", { style: { ...styles.inputContainer, ...(errors.name ? styles.inputError : {}) }, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\uD83D\uDC64" }), jsxRuntime.jsx("input", { type: "text", style: styles.input, placeholder: "Enter your first name", value: formData.name, onChange: (e) => updateField('name', e.target.value), autoComplete: "given-name", disabled: isLoading, required: true })] }), errors.name && jsxRuntime.jsx("div", { style: styles.errorText, children: errors.name })] }), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Last Name *" }), jsxRuntime.jsxs("div", { style: { ...styles.inputContainer, ...(errors.lastName ? styles.inputError : {}) }, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\uD83D\uDC64" }), jsxRuntime.jsx("input", { type: "text", style: styles.input, placeholder: "Enter your last name", value: formData.lastName, onChange: (e) => updateField('lastName', e.target.value), autoComplete: "family-name", disabled: isLoading, required: true })] }), errors.lastName && jsxRuntime.jsx("div", { style: styles.errorText, children: errors.lastName })] }), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Email Address *" }), jsxRuntime.jsxs("div", { style: { ...styles.inputContainer, ...(errors.email ? styles.inputError : {}) }, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\u2709" }), jsxRuntime.jsx("input", { type: "email", style: styles.input, placeholder: "Enter your email", value: formData.email, onChange: (e) => updateField('email', e.target.value), autoCapitalize: "none", autoComplete: "email", disabled: isLoading, required: true })] }), errors.email && jsxRuntime.jsx("div", { style: styles.errorText, children: errors.email })] }), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Password *" }), jsxRuntime.jsxs("div", { style: { ...styles.inputContainer, ...(errors.password ? styles.inputError : {}) }, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\uD83D\uDD12" }), jsxRuntime.jsx("input", { type: showPassword ? 'text' : 'password', style: styles.input, placeholder: "Create a password", value: formData.password, onChange: (e) => updateField('password', e.target.value), autoComplete: "new-password", disabled: isLoading, required: true }), jsxRuntime.jsx("button", { type: "button", style: styles.eyeButton, onClick: () => setShowPassword(!showPassword), disabled: isLoading, children: showPassword ? '👁' : '👁🗨' })] }), errors.password && jsxRuntime.jsx("div", { style: styles.errorText, children: errors.password })] }), jsxRuntime.jsxs("div", { style: styles.inputGroup, children: [jsxRuntime.jsx("label", { style: styles.inputLabel, children: "Confirm Password *" }), jsxRuntime.jsxs("div", { style: { ...styles.inputContainer, ...(errors.confirmPassword ? styles.inputError : {}) }, children: [jsxRuntime.jsx("span", { style: { marginRight: '12px', opacity: 0.7, color: '#666' }, children: "\uD83D\uDD12" }), jsxRuntime.jsx("input", { type: showConfirmPassword ? 'text' : 'password', style: styles.input, placeholder: "Confirm your password", value: formData.confirmPassword, onChange: (e) => updateField('confirmPassword', e.target.value), autoComplete: "new-password", disabled: isLoading, required: true }), jsxRuntime.jsx("button", { type: "button", style: styles.eyeButton, onClick: () => setShowConfirmPassword(!showConfirmPassword), disabled: isLoading, children: showConfirmPassword ? '👁' : '👁🗨' })] }), errors.confirmPassword && jsxRuntime.jsx("div", { style: styles.errorText, children: errors.confirmPassword })] }), jsxRuntime.jsx("button", { type: "submit", style: {
|
|
9310
9320
|
...styles.button,
|
|
9311
9321
|
opacity: isLoading ? 0.8 : 1,
|
|
9312
9322
|
cursor: isLoading ? 'not-allowed' : 'pointer'
|
|
@@ -9583,6 +9593,131 @@ function createStyles(theme) {
|
|
|
9583
9593
|
};
|
|
9584
9594
|
}
|
|
9585
9595
|
|
|
9596
|
+
/**
|
|
9597
|
+
* Authentication Guard Hook for React
|
|
9598
|
+
*
|
|
9599
|
+
* Framework-agnostic hook for handling authentication validation and redirects
|
|
9600
|
+
*/
|
|
9601
|
+
/**
|
|
9602
|
+
* Hook for handling authentication validation and redirects
|
|
9603
|
+
*
|
|
9604
|
+
* This hook is framework-agnostic and requires the user to provide
|
|
9605
|
+
* their own redirect function (e.g., Next.js router, React Router, etc.)
|
|
9606
|
+
*
|
|
9607
|
+
* @param options Hook options
|
|
9608
|
+
* @returns Authentication guard result
|
|
9609
|
+
*/
|
|
9610
|
+
function useAuthGuard({ validateOnMount = true, allowedTypes = ['authenticated'], instanceId, onRedirect, onSessionExpired, loginRedirectPath = '/login', accessDeniedPath = '/access-denied', enableLogging = false } = {}) {
|
|
9611
|
+
const { user, isAuthenticated, isLoading, validateSession } = useAuth(instanceId);
|
|
9612
|
+
// Check if user is authorized based on user type
|
|
9613
|
+
const isAuthorized = React.useCallback(() => {
|
|
9614
|
+
if (!isAuthenticated || !user) {
|
|
9615
|
+
return false;
|
|
9616
|
+
}
|
|
9617
|
+
// If allowedTypes includes 'authenticated', any authenticated user is allowed
|
|
9618
|
+
if (allowedTypes.includes('authenticated')) {
|
|
9619
|
+
return true;
|
|
9620
|
+
}
|
|
9621
|
+
// Check specific user types
|
|
9622
|
+
const userType = user.userType || user.user_type || '';
|
|
9623
|
+
return allowedTypes.some(type => type.toLowerCase() === userType.toLowerCase());
|
|
9624
|
+
}, [isAuthenticated, user, allowedTypes]);
|
|
9625
|
+
const authorized = isAuthorized();
|
|
9626
|
+
// Determine redirect reason
|
|
9627
|
+
const getRedirectReason = React.useCallback(() => {
|
|
9628
|
+
if (isLoading) {
|
|
9629
|
+
return null;
|
|
9630
|
+
}
|
|
9631
|
+
if (!isAuthenticated) {
|
|
9632
|
+
return 'unauthenticated';
|
|
9633
|
+
}
|
|
9634
|
+
if (!authorized) {
|
|
9635
|
+
return 'unauthorized';
|
|
9636
|
+
}
|
|
9637
|
+
return null;
|
|
9638
|
+
}, [isLoading, isAuthenticated, authorized]);
|
|
9639
|
+
const redirectReason = getRedirectReason();
|
|
9640
|
+
// Validate session on mount
|
|
9641
|
+
React.useEffect(() => {
|
|
9642
|
+
if (validateOnMount && isAuthenticated) {
|
|
9643
|
+
validateSession().then(({ isValid }) => {
|
|
9644
|
+
if (!isValid) {
|
|
9645
|
+
if (enableLogging) {
|
|
9646
|
+
console.warn('useAuthGuard: Session validation failed');
|
|
9647
|
+
}
|
|
9648
|
+
// Call session expired handler
|
|
9649
|
+
if (onSessionExpired) {
|
|
9650
|
+
onSessionExpired();
|
|
9651
|
+
}
|
|
9652
|
+
// Redirect to login
|
|
9653
|
+
if (onRedirect) {
|
|
9654
|
+
onRedirect(loginRedirectPath, 'session-expired');
|
|
9655
|
+
}
|
|
9656
|
+
}
|
|
9657
|
+
}).catch(error => {
|
|
9658
|
+
if (enableLogging) {
|
|
9659
|
+
console.error('useAuthGuard: Session validation error:', error);
|
|
9660
|
+
}
|
|
9661
|
+
});
|
|
9662
|
+
}
|
|
9663
|
+
}, [validateOnMount, isAuthenticated, validateSession, onSessionExpired, onRedirect, loginRedirectPath, enableLogging]);
|
|
9664
|
+
// Handle authentication redirects
|
|
9665
|
+
React.useEffect(() => {
|
|
9666
|
+
if (isLoading || !onRedirect) {
|
|
9667
|
+
return;
|
|
9668
|
+
}
|
|
9669
|
+
if (!isAuthenticated) {
|
|
9670
|
+
if (enableLogging) {
|
|
9671
|
+
console.warn('useAuthGuard: User not authenticated, redirecting to login');
|
|
9672
|
+
}
|
|
9673
|
+
onRedirect(loginRedirectPath, 'unauthenticated');
|
|
9674
|
+
return;
|
|
9675
|
+
}
|
|
9676
|
+
if (!authorized) {
|
|
9677
|
+
if (enableLogging) {
|
|
9678
|
+
console.warn('useAuthGuard: User not authorized for this page, redirecting to access denied');
|
|
9679
|
+
}
|
|
9680
|
+
onRedirect(accessDeniedPath, 'unauthorized');
|
|
9681
|
+
return;
|
|
9682
|
+
}
|
|
9683
|
+
}, [isLoading, isAuthenticated, authorized, onRedirect, loginRedirectPath, accessDeniedPath, enableLogging]);
|
|
9684
|
+
return {
|
|
9685
|
+
user,
|
|
9686
|
+
isAuthenticated,
|
|
9687
|
+
isLoading,
|
|
9688
|
+
isAuthorized: authorized,
|
|
9689
|
+
validateSession,
|
|
9690
|
+
redirectReason
|
|
9691
|
+
};
|
|
9692
|
+
}
|
|
9693
|
+
/**
|
|
9694
|
+
* Simple authentication guard hook with automatic redirects
|
|
9695
|
+
*
|
|
9696
|
+
* This is a simplified version that uses window.location for redirects
|
|
9697
|
+
* Suitable for simple React apps without complex routing
|
|
9698
|
+
*
|
|
9699
|
+
* @param options Hook options
|
|
9700
|
+
* @returns Authentication guard result
|
|
9701
|
+
*/
|
|
9702
|
+
function useSimpleAuthGuard(options = {}) {
|
|
9703
|
+
var _a;
|
|
9704
|
+
const handleRedirect = React.useCallback((path, reason) => {
|
|
9705
|
+
if (typeof window !== 'undefined') {
|
|
9706
|
+
// Add current path as redirect parameter
|
|
9707
|
+
const currentPath = window.location.pathname + window.location.search;
|
|
9708
|
+
const redirectUrl = reason === 'unauthenticated'
|
|
9709
|
+
? `${path}?redirect=${encodeURIComponent(currentPath)}`
|
|
9710
|
+
: path;
|
|
9711
|
+
window.location.href = redirectUrl;
|
|
9712
|
+
}
|
|
9713
|
+
}, []);
|
|
9714
|
+
return useAuthGuard({
|
|
9715
|
+
...options,
|
|
9716
|
+
onRedirect: handleRedirect,
|
|
9717
|
+
enableLogging: (_a = options.enableLogging) !== null && _a !== void 0 ? _a : true
|
|
9718
|
+
});
|
|
9719
|
+
}
|
|
9720
|
+
|
|
9586
9721
|
/**
|
|
9587
9722
|
* Bridge API Raw Hook for React
|
|
9588
9723
|
*
|
|
@@ -9662,65 +9797,6 @@ function useBridgeApiRaw(instanceId) {
|
|
|
9662
9797
|
};
|
|
9663
9798
|
}
|
|
9664
9799
|
|
|
9665
|
-
/**
|
|
9666
|
-
* Server Authentication Hook for React
|
|
9667
|
-
*
|
|
9668
|
-
* Provides a hook for handling authentication with automatic redirects
|
|
9669
|
-
*/
|
|
9670
|
-
/**
|
|
9671
|
-
* Hook for handling authentication with automatic redirects
|
|
9672
|
-
*
|
|
9673
|
-
* @param options Hook options
|
|
9674
|
-
* @returns Authentication hook result
|
|
9675
|
-
*/
|
|
9676
|
-
function useServerAuth({ loginRedirectPath = '/login', allowedTypes = ['authenticated'], validateOnMount = true, instanceId, onRedirect } = {}) {
|
|
9677
|
-
const { user, isAuthenticated, isLoading, validateSession } = useAuth(instanceId);
|
|
9678
|
-
// Default redirect function
|
|
9679
|
-
const defaultRedirect = (path) => {
|
|
9680
|
-
if (typeof window !== 'undefined') {
|
|
9681
|
-
const currentPath = window.location.pathname;
|
|
9682
|
-
const redirectUrl = `${path}?redirect=${encodeURIComponent(currentPath)}`;
|
|
9683
|
-
window.location.href = redirectUrl;
|
|
9684
|
-
}
|
|
9685
|
-
};
|
|
9686
|
-
const redirect = onRedirect || defaultRedirect;
|
|
9687
|
-
React.useEffect(() => {
|
|
9688
|
-
// Validate session on mount if configured
|
|
9689
|
-
if (validateOnMount) {
|
|
9690
|
-
validateSession().then(({ isValid }) => {
|
|
9691
|
-
if (!isValid) {
|
|
9692
|
-
redirect(loginRedirectPath);
|
|
9693
|
-
}
|
|
9694
|
-
});
|
|
9695
|
-
}
|
|
9696
|
-
}, [validateOnMount, loginRedirectPath, validateSession, redirect]);
|
|
9697
|
-
React.useEffect(() => {
|
|
9698
|
-
// Skip if still loading
|
|
9699
|
-
if (isLoading) {
|
|
9700
|
-
return;
|
|
9701
|
-
}
|
|
9702
|
-
// Redirect if not authenticated
|
|
9703
|
-
if (!isAuthenticated) {
|
|
9704
|
-
redirect(loginRedirectPath);
|
|
9705
|
-
return;
|
|
9706
|
-
}
|
|
9707
|
-
// Check user type if allowedTypes doesn't include 'authenticated'
|
|
9708
|
-
if (!allowedTypes.includes('authenticated') && user) {
|
|
9709
|
-
const userType = user.userType || '';
|
|
9710
|
-
const isAllowed = allowedTypes.some(type => type.toLowerCase() === userType.toLowerCase());
|
|
9711
|
-
if (!isAllowed) {
|
|
9712
|
-
redirect('/access-denied');
|
|
9713
|
-
}
|
|
9714
|
-
}
|
|
9715
|
-
}, [isLoading, isAuthenticated, user, allowedTypes, loginRedirectPath, redirect]);
|
|
9716
|
-
return {
|
|
9717
|
-
user,
|
|
9718
|
-
isAuthenticated,
|
|
9719
|
-
isLoading,
|
|
9720
|
-
validateSession
|
|
9721
|
-
};
|
|
9722
|
-
}
|
|
9723
|
-
|
|
9724
9800
|
/**
|
|
9725
9801
|
* Search Query Builder Hook for React
|
|
9726
9802
|
*
|
|
@@ -9958,6 +10034,7 @@ exports.ThemeProvider = ThemeProvider;
|
|
|
9958
10034
|
exports.createStyles = createStyles;
|
|
9959
10035
|
exports.generateCSSVariables = generateCSSVariables;
|
|
9960
10036
|
exports.useAuth = useAuth;
|
|
10037
|
+
exports.useAuthGuard = useAuthGuard;
|
|
9961
10038
|
exports.useBridgeApi = useBridgeApi;
|
|
9962
10039
|
exports.useBridgeApiRaw = useBridgeApiRaw;
|
|
9963
10040
|
exports.useBridgeCrud = useBridgeCrud;
|
|
@@ -9966,7 +10043,7 @@ exports.useBridgeQuery = useBridgeQuery;
|
|
|
9966
10043
|
exports.useNetworkStatus = useNetworkStatus;
|
|
9967
10044
|
exports.useRequireAuth = useRequireAuth;
|
|
9968
10045
|
exports.useSearchQueryBuilder = useSearchQueryBuilder;
|
|
9969
|
-
exports.
|
|
10046
|
+
exports.useSimpleAuthGuard = useSimpleAuthGuard;
|
|
9970
10047
|
exports.useTheme = useTheme;
|
|
9971
10048
|
Object.keys(core).forEach(function (k) {
|
|
9972
10049
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|