@jmruthers/pace-core 0.5.93 → 0.5.95
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/{DataTable-HC5S4RKB.js → DataTable-XENXNMCP.js} +6 -6
- package/dist/{PublicLoadingSpinner-n74JgA9h.d.ts → PublicLoadingSpinner-B84QWsvB.d.ts} +31 -3
- package/dist/{UnifiedAuthProvider-ZM7VUC45.js → UnifiedAuthProvider-H7RI4KYD.js} +3 -3
- package/dist/{chunk-AZ2QJYKU.js → chunk-2KLAOD4M.js} +3 -3
- package/dist/{chunk-HW5BGOWB.js → chunk-2ZYHCFUO.js} +4 -4
- package/dist/{chunk-AAM57AEU.js → chunk-5RYPBJYL.js} +16 -19
- package/dist/chunk-5RYPBJYL.js.map +1 -0
- package/dist/{chunk-XIBSVWJW.js → chunk-7TQDRDSM.js} +5 -5
- package/dist/{chunk-TZXYSZT3.js → chunk-EPKHU5SS.js} +314 -245
- package/dist/{chunk-TZXYSZT3.js.map → chunk-EPKHU5SS.js.map} +1 -1
- package/dist/{chunk-GP3HU6WS.js → chunk-G7UUVEAP.js} +3 -3
- package/dist/{chunk-M52CQP5W.js → chunk-MKMKUCPF.js} +762 -12
- package/dist/chunk-MKMKUCPF.js.map +1 -0
- package/dist/{chunk-OXFOS62D.js → chunk-MVNOAHOP.js} +2 -2
- package/dist/{chunk-AYC2P377.js → chunk-ORACUZ7H.js} +2 -2
- package/dist/{chunk-SVMPR5IV.js → chunk-V5CTX4FR.js} +963 -788
- package/dist/chunk-V5CTX4FR.js.map +1 -0
- package/dist/{chunk-6WFM22A4.js → chunk-ZGCVJ7WW.js} +2 -2
- package/dist/components.d.ts +1 -1
- package/dist/components.js +8 -8
- package/dist/hooks.d.ts +94 -3
- package/dist/hooks.js +20 -8
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +17 -11
- package/dist/index.js.map +1 -1
- package/dist/providers.js +2 -2
- package/dist/rbac/index.js +7 -7
- package/dist/{usePublicRouteParams-BlgwXweB.d.ts → usePublicRouteParams-BwMR2uub.d.ts} +93 -1
- package/dist/utils.js +1 -1
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +52 -11
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +24 -11
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
- package/docs/api/interfaces/UseEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UseEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +47 -0
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +120 -0
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +102 -16
- package/docs/implementation-guides/file-reference-system.md +15 -0
- package/docs/implementation-guides/file-upload-storage.md +16 -0
- package/package.json +1 -1
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +9 -7
- package/src/components/DataTable/components/DataTableCore.tsx +35 -10
- package/src/components/DataTable/components/EditableRow.tsx +62 -22
- package/src/components/DataTable/components/UnifiedTableBody.tsx +25 -101
- package/src/components/FileDisplay/FileDisplay.test.tsx +263 -39
- package/src/components/FileDisplay/FileDisplay.tsx +667 -103
- package/src/components/PublicLayout/PublicPageHeader.tsx +15 -8
- package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +71 -28
- package/src/components/Select/Select.test.tsx +83 -6
- package/src/components/Select/Select.tsx +236 -16
- package/src/examples/CorrectPublicPageImplementation.tsx +16 -13
- package/src/examples/PublicEventPage.tsx +9 -6
- package/src/examples/PublicPageApp.tsx +9 -6
- package/src/examples/PublicPageUsageExample.tsx +9 -7
- package/src/hooks/index.ts +4 -0
- package/src/hooks/public/index.ts +2 -0
- package/src/hooks/public/usePublicFileDisplay.ts +355 -0
- package/src/hooks/useFileDisplay.ts +370 -0
- package/src/hooks/useFileUrl.ts +130 -0
- package/src/services/AuthService.ts +19 -22
- package/dist/chunk-AAM57AEU.js.map +0 -1
- package/dist/chunk-M52CQP5W.js.map +0 -1
- package/dist/chunk-SVMPR5IV.js.map +0 -1
- /package/dist/{DataTable-HC5S4RKB.js.map → DataTable-XENXNMCP.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-ZM7VUC45.js.map → UnifiedAuthProvider-H7RI4KYD.js.map} +0 -0
- /package/dist/{chunk-AZ2QJYKU.js.map → chunk-2KLAOD4M.js.map} +0 -0
- /package/dist/{chunk-HW5BGOWB.js.map → chunk-2ZYHCFUO.js.map} +0 -0
- /package/dist/{chunk-XIBSVWJW.js.map → chunk-7TQDRDSM.js.map} +0 -0
- /package/dist/{chunk-GP3HU6WS.js.map → chunk-G7UUVEAP.js.map} +0 -0
- /package/dist/{chunk-OXFOS62D.js.map → chunk-MVNOAHOP.js.map} +0 -0
- /package/dist/{chunk-AYC2P377.js.map → chunk-ORACUZ7H.js.map} +0 -0
- /package/dist/{chunk-6WFM22A4.js.map → chunk-ZGCVJ7WW.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/services/base/BaseService.ts","../src/services/AuthService.ts","../src/providers/services/AuthServiceProvider.tsx","../src/services/OrganisationService.ts","../src/providers/services/OrganisationServiceProvider.tsx","../src/services/EventService.ts","../src/providers/services/EventServiceProvider.tsx","../src/services/InactivityService.ts","../src/providers/services/InactivityServiceProvider.tsx","../src/hooks/services/useAuthService.ts","../src/hooks/services/useOrganisationService.ts","../src/hooks/services/useEventService.ts","../src/hooks/services/useInactivityService.ts","../src/hooks/useSessionRestoration.ts","../src/providers/services/UnifiedAuthProvider.tsx"],"sourcesContent":["/**\n * @file Base Service Class\n * @package @jmruthers/pace-core\n * @module Services/Base\n * @since 0.1.0\n *\n * Base service class implementing the observable pattern for React subscriptions.\n * All services extend this class to provide state change notifications.\n */\n\nexport type StateChangeCallback = () => void;\n\nexport abstract class BaseService {\n private subscribers: Array<StateChangeCallback> = [];\n private isInitialized = false;\n\n /**\n * Subscribe to state changes\n * @param callback Function to call when state changes\n * @returns Unsubscribe function\n */\n subscribe(callback: StateChangeCallback): () => void {\n this.subscribers.push(callback);\n \n // Return unsubscribe function that removes only the first occurrence\n return () => {\n const index = this.subscribers.indexOf(callback);\n if (index > -1) {\n this.subscribers.splice(index, 1);\n }\n };\n }\n\n /**\n * Notify all subscribers of state changes\n * This triggers React re-renders\n */\n protected notify(): void {\n this.subscribers.forEach(callback => {\n try {\n callback();\n } catch (error) {\n console.error('[BaseService] Error in subscriber callback:', error);\n }\n });\n }\n\n /**\n * Initialize the service\n * Override in subclasses to implement initialization logic\n */\n async initialize(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n \n await this.doInitialize();\n this.isInitialized = true;\n }\n\n /**\n * Cleanup the service\n * Override in subclasses to implement cleanup logic\n */\n cleanup(): void {\n this.subscribers = [];\n this.doCleanup();\n this.isInitialized = false;\n }\n\n /**\n * Check if service is initialized\n */\n protected getInitialized(): boolean {\n return this.isInitialized;\n }\n\n /**\n * Reset initialization state (allows re-initialization)\n * Use when dependencies change and service needs to re-initialize\n */\n protected resetInitialization(): void {\n this.isInitialized = false;\n }\n\n /**\n * Override in subclasses to implement initialization logic\n */\n protected abstract doInitialize(): Promise<void>;\n\n /**\n * Override in subclasses to implement cleanup logic\n */\n protected abstract doCleanup(): void;\n}","/**\n * @file Authentication Service\n * @package @jmruthers/pace-core\n * @module Services\n * @since 0.1.0\n *\n * Authentication service implementation.\n * Handles user authentication, session management, and auth-related operations.\n */\n\nimport { type SupabaseClient, type User, type Session, AuthError } from '@supabase/supabase-js';\nimport type { SessionRestorationState } from '../types/auth';\nimport { BaseService } from './base/BaseService';\nimport { IAuthService, AuthResult } from './interfaces/IAuthService';\n\nexport class AuthService extends BaseService implements IAuthService {\n private user: User | null = null;\n private session: Session | null = null;\n private authLoading = false;\n private authError: AuthError | null = null;\n private supabaseClient: SupabaseClient | null = null;\n private authStateSubscription: any = null;\n private sessionRestorationState: SessionRestorationState = {\n isRestoring: false,\n restorationComplete: false,\n restorationError: null,\n };\n private restorationTimeoutId: ReturnType<typeof setTimeout> | null = null;\n private readonly restorationTimeoutMs = 5000;\n private restorationStartTime: number | null = null;\n\n constructor(supabaseClient: SupabaseClient) {\n super();\n this.supabaseClient = supabaseClient;\n }\n\n // Auth state getters\n getUser(): User | null {\n return this.user;\n }\n\n getSession(): Session | null {\n return this.session;\n }\n\n isAuthenticated(): boolean {\n return !!(this.user && this.session);\n }\n\n isLoading(): boolean {\n return this.authLoading;\n }\n\n getError(): AuthError | null {\n return this.authError;\n }\n\n getSupabaseClient(): SupabaseClient | null {\n return this.supabaseClient;\n }\n\n getSessionRestorationState(): SessionRestorationState {\n return { ...this.sessionRestorationState };\n }\n\n // Auth methods\n async signIn(email: string, password?: string): Promise<AuthResult> {\n if (!this.supabaseClient) {\n const error = new AuthError('Supabase client not available');\n this.authError = error;\n this.notify();\n return { user: null, session: null, error };\n }\n\n try {\n const { data, error } = await this.supabaseClient.auth.signInWithPassword({\n email,\n password: password || '',\n });\n \n if (error) {\n this.authError = error;\n this.user = null;\n this.session = null;\n } else {\n this.authError = null;\n this.user = data.user;\n this.session = data.session;\n }\n \n this.notify();\n return { user: data.user, session: data.session, error };\n } catch (error) {\n // Convert regular Error to AuthError if needed\n const authError = error instanceof AuthError \n ? error \n : new AuthError(error instanceof Error ? error.message : 'Authentication failed');\n this.authError = authError;\n this.user = null;\n this.session = null;\n this.notify();\n return { user: null, session: null, error: authError };\n }\n }\n\n async signUp(email: string, password: string): Promise<AuthResult> {\n if (!this.supabaseClient) {\n const error = new AuthError('Supabase client not available');\n this.authError = error;\n this.notify();\n return { user: null, session: null, error };\n }\n\n try {\n const { data, error } = await this.supabaseClient.auth.signUp({\n email,\n password,\n });\n \n if (error) {\n this.authError = error;\n this.user = null;\n this.session = null;\n } else {\n this.authError = null;\n this.user = data.user;\n this.session = data.session;\n }\n \n this.notify();\n return { user: data.user, session: data.session, error };\n } catch (error) {\n // Convert regular Error to AuthError if needed\n const authError = error instanceof AuthError \n ? error \n : new AuthError(error instanceof Error ? error.message : 'Authentication failed');\n this.authError = authError;\n this.user = null;\n this.session = null;\n this.notify();\n return { user: null, session: null, error: authError };\n }\n }\n\n async signOut(): Promise<AuthResult> {\n if (!this.supabaseClient) {\n const error = new AuthError('Supabase client not available');\n this.authError = error;\n this.notify();\n return { user: null, session: null, error };\n }\n\n try {\n const { error } = await this.supabaseClient.auth.signOut();\n \n if (error) {\n this.authError = error;\n } else {\n this.authError = null;\n this.user = null;\n this.session = null;\n }\n \n this.notify();\n return { user: null, session: null, error };\n } catch (error) {\n // Convert regular Error to AuthError if needed\n const authError = error instanceof AuthError \n ? error \n : new AuthError(error instanceof Error ? error.message : 'Authentication failed');\n this.authError = authError;\n this.user = null;\n this.session = null;\n this.notify();\n return { user: null, session: null, error: authError };\n }\n }\n\n async resetPassword(email: string): Promise<AuthResult> {\n if (!this.supabaseClient) {\n const error = new AuthError('Supabase client not available');\n this.authError = error;\n this.notify();\n return { user: null, session: null, error };\n }\n\n try {\n const { error } = await this.supabaseClient.auth.resetPasswordForEmail(email);\n \n if (error) {\n this.authError = error;\n } else {\n this.authError = null;\n }\n \n this.notify();\n return { user: null, session: null, error };\n } catch (error) {\n // Convert regular Error to AuthError if needed\n const authError = error instanceof AuthError \n ? error \n : new AuthError(error instanceof Error ? error.message : 'Authentication failed');\n this.authError = authError;\n this.notify();\n return { user: null, session: null, error: authError };\n }\n }\n\n async updatePassword(password: string): Promise<AuthResult> {\n if (!this.supabaseClient) {\n const error = new AuthError('Supabase client not available');\n this.authError = error;\n this.notify();\n return { user: null, session: null, error };\n }\n\n try {\n const { error } = await this.supabaseClient.auth.updateUser({\n password,\n });\n \n if (error) {\n this.authError = error;\n } else {\n this.authError = null;\n }\n \n this.notify();\n return { user: null, session: null, error };\n } catch (error) {\n const authError = error as AuthError;\n this.authError = authError;\n this.notify();\n return { user: null, session: null, error: authError };\n }\n }\n\n async refreshSession(): Promise<AuthResult> {\n if (!this.supabaseClient) {\n const error = new AuthError('Supabase client not available');\n this.authError = error;\n this.notify();\n return { user: null, session: null, error };\n }\n\n try {\n const { data, error } = await this.supabaseClient.auth.refreshSession();\n \n if (error) {\n this.authError = error;\n this.user = null;\n this.session = null;\n } else {\n this.authError = null;\n // Only update user and session if both are present (valid session)\n if (data?.user && data?.session) {\n this.user = data.user;\n this.session = data.session;\n } else {\n // If no valid session, clear everything\n this.user = null;\n this.session = null;\n }\n }\n \n this.notify();\n // Only return user if we have a valid session\n return { \n user: (data?.user && data?.session) ? data.user : null, \n session: data?.session ?? null, \n error \n };\n } catch (error) {\n // Convert regular Error to AuthError if needed\n const authError = error instanceof AuthError \n ? error \n : new AuthError(error instanceof Error ? error.message : 'Authentication failed');\n this.authError = authError;\n this.user = null;\n this.session = null;\n this.notify();\n return { user: null, session: null, error: authError };\n }\n }\n\n // Lifecycle methods\n async initialize(): Promise<void> {\n await super.initialize();\n await this.setupAuthStateListener();\n await this.restoreSession();\n }\n\n cleanup(): void {\n if (this.authStateSubscription && typeof this.authStateSubscription.unsubscribe === 'function') {\n this.authStateSubscription.unsubscribe();\n this.authStateSubscription = null;\n }\n this.clearRestorationTimeout();\n this.restorationStartTime = null;\n this.sessionRestorationState = {\n isRestoring: false,\n restorationComplete: false,\n restorationError: null,\n };\n this.authLoading = false;\n super.cleanup();\n }\n\n protected async doInitialize(): Promise<void> {\n // Setup global error handlers\n this.setupErrorHandlers();\n }\n\n protected doCleanup(): void {\n // Remove global error handlers\n this.removeErrorHandlers();\n }\n\n private startSessionRestoration(): void {\n this.clearRestorationTimeout();\n this.sessionRestorationState = {\n isRestoring: true,\n restorationComplete: false,\n restorationError: null,\n };\n this.authLoading = true;\n this.restorationStartTime = Date.now();\n console.debug('[AuthService] Starting session restoration at', this.restorationStartTime);\n this.notify();\n\n this.restorationTimeoutId = setTimeout(() => {\n console.warn('[AuthService] Session restoration timed out after', this.restorationTimeoutMs, 'ms');\n const timeoutError = new Error(`Session restoration timed out after ${this.restorationTimeoutMs}ms`);\n timeoutError.name = 'SessionRestorationTimeoutError';\n this.finishSessionRestoration(timeoutError);\n }, this.restorationTimeoutMs);\n }\n\n private finishSessionRestoration(error?: Error): void {\n if (!this.sessionRestorationState.isRestoring && !error) {\n return;\n }\n\n this.clearRestorationTimeout();\n const completedAt = Date.now();\n const duration = this.restorationStartTime ? completedAt - this.restorationStartTime : null;\n this.restorationStartTime = null;\n const restorationComplete = !error;\n this.sessionRestorationState = {\n isRestoring: false,\n restorationComplete,\n restorationError: error ?? null,\n };\n this.authLoading = false;\n\n if (error) {\n console.warn('[AuthService] Session restoration finished with error:', error, 'duration(ms):', duration ?? 'unknown');\n } else {\n console.debug('[AuthService] Session restoration completed successfully in', duration ?? 'unknown', 'ms');\n }\n\n this.notify();\n }\n\n private clearRestorationTimeout(): void {\n if (this.restorationTimeoutId) {\n clearTimeout(this.restorationTimeoutId);\n this.restorationTimeoutId = null;\n }\n }\n\n private async setupAuthStateListener(): Promise<void> {\n if (!this.supabaseClient) {\n this.authLoading = false;\n this.notify();\n return;\n }\n\n try {\n this.authStateSubscription = this.supabaseClient.auth.onAuthStateChange(\n (event, session) => {\n try {\n console.debug('[AuthService] Auth state change event received:', event);\n // Handle different auth events\n if (event === 'SIGNED_OUT') {\n this.session = null;\n this.user = null;\n this.authError = null;\n } else if (event === 'SIGNED_IN' || event === 'TOKEN_REFRESHED') {\n this.session = session;\n this.user = session?.user ?? null;\n\n // Only clear auth error if we have a valid session\n if (session) {\n this.authError = null;\n }\n } else if (event === 'INITIAL_SESSION') {\n if (session) {\n this.session = session;\n this.user = session.user ?? null;\n this.authError = null;\n }\n\n if (this.sessionRestorationState.isRestoring) {\n this.finishSessionRestoration();\n return;\n }\n }\n\n // Always set loading to false after any auth state change\n this.authLoading = false;\n this.notify();\n } catch (error) {\n console.warn('[AuthService] Error in auth state change handler:', error);\n this.authLoading = false;\n this.notify();\n }\n }\n );\n } catch (error) {\n console.error('[AuthService] Failed to setup auth state listener:', error);\n throw error; // Re-throw to propagate to the provider\n }\n }\n\n private async restoreSession(): Promise<void> {\n if (!this.supabaseClient) {\n const error = new Error('Supabase client not available during session restoration');\n console.error('[AuthService] Unable to restore session:', error);\n this.finishSessionRestoration(error);\n return;\n }\n\n this.startSessionRestoration();\n\n try {\n console.debug('[AuthService] Fetching existing session from Supabase');\n // Safely call getSession without destructuring to avoid runtime errors if undefined\n let currentSession: Session | null = null;\n let sessionError: AuthError | null = null;\n const getSessionFn = (this.supabaseClient.auth as any)?.getSession as (() => Promise<{ data?: { session?: Session | null }, error?: AuthError | null }>) | undefined;\n if (typeof getSessionFn === 'function') {\n const sessionResult = await getSessionFn();\n currentSession = sessionResult?.data?.session ?? null;\n sessionError = sessionResult?.error ?? null;\n } else {\n // If getSession is unavailable in this environment/mocked client, treat as no active session\n currentSession = null;\n sessionError = null;\n }\n\n if (sessionError) {\n // Record error but continue to attempt getUser to satisfy edge cases\n console.debug('[AuthService] getSession returned error, attempting to fetch user anyway');\n this.authError = sessionError;\n \n // Attempt getUser as fallback when getSession fails\n try {\n const getUserFn = (this.supabaseClient.auth as any)?.getUser as (() => Promise<{ data?: { user?: User | null }, error?: AuthError | null }>) | undefined;\n if (typeof getUserFn === 'function') {\n const userResult = await getUserFn();\n const currentUser = userResult?.data?.user ?? null;\n const userError = userResult?.error ?? null;\n \n if (currentUser) {\n this.user = currentUser;\n // If we got a user but no session, we still don't have a valid session\n this.session = null;\n }\n if (userError && !this.authError) {\n this.authError = userError;\n }\n }\n } catch (getUserError) {\n // If getUser also fails, we've already recorded the sessionError\n console.debug('[AuthService] getUser also failed:', getUserError);\n }\n }\n\n if (currentSession) {\n this.session = currentSession;\n this.user = currentSession.user;\n this.authError = null;\n } else if (!sessionError) {\n // Only skip getUser if we didn't already attempt it due to a sessionError\n // Treat missing session as a normal cold-start state on public pages (e.g., login)\n // Do not call getUser() which can raise AuthSessionMissingError and surface a noisy banner\n console.debug('[AuthService] No active session found; treating as normal unauthenticated state');\n this.session = null;\n this.user = null;\n this.authError = null;\n }\n\n // Finish successfully even if earlier calls reported an error, to avoid noisy warnings in benign cases\n this.finishSessionRestoration();\n } catch (error) {\n const restorationError = error instanceof Error\n ? error\n : new Error('Unknown error during auth initialization');\n console.error('[AuthService] Error during auth initialization:', restorationError);\n if (restorationError instanceof AuthError) {\n this.authError = restorationError;\n }\n this.finishSessionRestoration(restorationError);\n }\n }\n\n private setupErrorHandlers(): void {\n if (typeof window === 'undefined') return;\n\n const handleError = (event: ErrorEvent) => {\n if (event.error?.message?.includes('AuthSessionMissingError') || \n event.error?.message?.includes('Auth session missing')) {\n console.warn('[AuthService] Suppressing AuthSessionMissingError during logout');\n event.preventDefault();\n return false;\n }\n };\n\n const handleUnhandledRejection = (event: PromiseRejectionEvent) => {\n if (event.reason?.message?.includes('AuthSessionMissingError') ||\n event.reason?.message?.includes('Auth session missing')) {\n console.warn('[AuthService] Suppressing unhandled AuthSessionMissingError');\n event.preventDefault();\n return false;\n }\n };\n\n window.addEventListener('error', handleError);\n window.addEventListener('unhandledrejection', handleUnhandledRejection);\n }\n\n private removeErrorHandlers(): void {\n if (typeof window === 'undefined') return;\n\n // Note: We can't remove specific handlers without storing references\n // In a real implementation, you'd store the handler references\n // For now, we'll rely on the service being cleaned up\n }\n}","/**\n * @file Auth Service Provider\n * @package @jmruthers/pace-core\n * @module Providers/Services\n * @since 0.1.0\n *\n * React provider for AuthService.\n * Provides authentication service instance to React components.\n */\n\nimport React, { createContext, useContext, useMemo, useEffect, useState } from 'react';\nimport { type SupabaseClient } from '@supabase/supabase-js';\nimport { AuthService } from '../../services/AuthService';\nimport type { SessionRestorationState } from '../../types/auth';\n\n// Context type\nexport interface AuthServiceContextType {\n authService: AuthService;\n sessionRestoration: SessionRestorationState;\n}\n\nexport const AuthServiceContext = createContext<AuthServiceContextType | null>(null);\n\nexport interface AuthServiceProviderProps {\n children: React.ReactNode;\n supabaseClient: SupabaseClient;\n}\n\nexport function AuthServiceProvider({ children, supabaseClient }: AuthServiceProviderProps) {\n // Create service instance with useMemo to prevent recreation on every render\n const authService = useMemo(\n () => new AuthService(supabaseClient),\n [supabaseClient]\n );\n\n const [sessionRestoration, setSessionRestoration] = useState<SessionRestorationState>(\n () => authService.getSessionRestorationState()\n );\n\n // Subscribe to service updates to keep restoration state in sync\n useEffect(() => {\n const unsubscribe = authService.subscribe(() => {\n const restorationState = authService.getSessionRestorationState();\n setSessionRestoration(restorationState);\n\n const isDev = typeof import.meta !== 'undefined' && (import.meta.env.DEV || import.meta.env.MODE === 'development');\n if (isDev) {\n console.debug('[AuthServiceProvider] Session restoration state updated', restorationState);\n }\n });\n\n return () => {\n unsubscribe();\n };\n }, [authService]);\n\n // Initialize service on mount\n useEffect(() => {\n authService.initialize().catch(error => {\n console.error('[AuthServiceProvider] Failed to initialize auth service:', error);\n });\n\n // Cleanup on unmount\n return () => {\n authService.cleanup();\n };\n }, [authService]);\n\n const contextValue = useMemo(() => ({\n authService,\n sessionRestoration\n }), [authService, sessionRestoration]);\n\n return (\n <AuthServiceContext.Provider value={contextValue}>\n {children}\n </AuthServiceContext.Provider>\n );\n}\n\nexport const useAuthService = (): AuthService => {\n const context = useContext(AuthServiceContext);\n \n if (!context) {\n throw new Error('useAuthService must be used within AuthServiceProvider');\n }\n \n return context.authService;\n};","/**\n * @file Organisation Service\n * @package @jmruthers/pace-core\n * @module Services\n * @since 0.1.0\n *\n * Organisation service implementation.\n * Handles organisation management and selection with security-first approach.\n */\n\nimport { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';\nimport { BaseService } from './base/BaseService';\nimport { IOrganisationService } from './interfaces/IOrganisationService';\nimport type {\n Organisation,\n OrganisationMembership,\n OrganisationSecurityError,\n OrganisationHierarchy\n} from '../types/organisation';\nimport { setOrganisationContext } from '../utils/organisationContext';\n\nexport class OrganisationService extends BaseService implements IOrganisationService {\n private _selectedOrganisation: Organisation | null = null;\n private _organisations: Organisation[] = [];\n private _userMemberships: OrganisationMembership[] = [];\n private _roleMapState: Map<string, string> = new Map();\n private _isLoading = false;\n private _error: Error | null = null;\n private _isContextReady = false;\n private retryCount = 0;\n\n // Dependencies\n private supabaseClient: SupabaseClient | null = null;\n private user: User | null = null;\n private session: Session | null = null;\n\n // Internal state management\n private isLoadingRef = false;\n private lastLoadTimeRef = 0;\n private hasFailedRef = false;\n private abortControllerRef: AbortController | null = null;\n\n constructor(supabaseClient: SupabaseClient, user: User | null, session: Session | null) {\n super();\n this.supabaseClient = supabaseClient;\n this.user = user;\n this.session = session;\n }\n\n // Interface implementation\n getSelectedOrganisation(): Organisation | null { return this._selectedOrganisation; }\n getOrganisations(): Organisation[] { return this._organisations; }\n getUserMemberships(): OrganisationMembership[] { return this._userMemberships; }\n isLoading(): boolean { \n return this._isLoading;\n }\n getError(): Error | null { return this._error; }\n hasValidOrganisationContext(): boolean { return !!(this._selectedOrganisation && !this._isLoading && !this._error && this._isContextReady); }\n isContextReady(): boolean { return this._isContextReady; }\n\n // Additional methods for testing\n setSelectedOrganisation(organisation: Organisation | null): void {\n this._selectedOrganisation = organisation;\n if (organisation) {\n localStorage.setItem('pace-core-selected-organisation', JSON.stringify(organisation));\n this.setDatabaseOrganisationContext(organisation);\n } else {\n localStorage.removeItem('pace-core-selected-organisation');\n this._isContextReady = false;\n }\n this.notify();\n }\n\n // For testing: expose dependencies\n getDependencies(): { user: User | null; session: Session | null; supabaseClient: SupabaseClient | null } {\n return {\n user: this.user,\n session: this.session,\n supabaseClient: this.supabaseClient\n };\n }\n\n // For testing: manually set state\n setTestState(\n organisations: Organisation[],\n memberships: OrganisationMembership[],\n roleMap: Map<string, string>,\n selectedOrg: Organisation | null = null\n ): void {\n this._organisations = organisations;\n this._userMemberships = memberships;\n this._roleMapState = roleMap;\n if (selectedOrg) {\n this._selectedOrganisation = selectedOrg;\n } else if (organisations.length > 0) {\n this._selectedOrganisation = organisations[0];\n }\n this._isLoading = false;\n this._error = null;\n this.notify();\n }\n\n // Update dependencies\n updateDependencies(user: User | null, session: Session | null): void {\n const wasAuthenticated = !!(this.user && this.session);\n const isAuthenticated = !!(user && session);\n \n this.user = user;\n this.session = session;\n \n // If user logs out, allow re-initialization when they log back in\n if (wasAuthenticated && !isAuthenticated) {\n // Reset BaseService initialization state to allow re-initialization\n (this as any).isInitialized = false;\n }\n \n this.notify();\n }\n\n // Organisation methods\n async switchOrganisation(orgId: string): Promise<void> {\n // Validate access\n if (!this.validateOrganisationAccess(orgId)) {\n throw new Error(`User does not have access to organisation ${orgId}`) as OrganisationSecurityError;\n }\n \n const targetOrg = this._organisations.find(org => org.id === orgId);\n if (!targetOrg) {\n throw new Error(`Organisation ${orgId} not found in user's organisations`) as OrganisationSecurityError;\n }\n \n this._selectedOrganisation = targetOrg;\n \n // Persist selection\n localStorage.setItem('pace-core-selected-organisation', JSON.stringify(targetOrg));\n \n // Set database organisation context\n await this.setDatabaseOrganisationContext(targetOrg);\n \n this.notify();\n }\n\n getUserRole(orgId?: string): string {\n const targetOrgId = orgId || this._selectedOrganisation?.id;\n if (!targetOrgId) return 'no_access';\n \n // Use roleMapState to get the role for this organisation\n return this._roleMapState.get(targetOrgId) || 'no_access';\n }\n\n validateOrganisationAccess(orgId: string): boolean {\n return this._userMemberships.some((m: any) => \n m.organisation_id === orgId && \n m.status === 'active' &&\n m.revoked_at === null\n );\n }\n\n async refreshOrganisations(): Promise<void> {\n if (!this.user || !this.session || !this.supabaseClient) return;\n \n // Force reload by triggering the effect\n this._isLoading = true;\n this.notify();\n await this.loadUserOrganisations();\n }\n\n ensureOrganisationContext(): Organisation {\n if (!this._selectedOrganisation) {\n throw new Error('Organisation context is required but not available') as OrganisationSecurityError;\n }\n return this._selectedOrganisation;\n }\n\n isOrganisationSecure(): boolean {\n return !!(this._selectedOrganisation && this.user);\n }\n\n getPrimaryOrganisation(): Organisation | null {\n // Look for org_admin role first, then leader, then member\n const rolePriority = ['org_admin', 'leader', 'member'];\n \n for (const role of rolePriority) {\n const membership = this._userMemberships.find((m: any) => m.role === role);\n if (membership) {\n return this._organisations.find((org: any) => org.id === membership.organisation_id) || null;\n }\n }\n \n return null;\n }\n\n buildOrganisationHierarchy(orgs: Organisation[]): OrganisationHierarchy[] {\n const orgMap = new Map<string, Organisation>();\n orgs.forEach(org => orgMap.set(org.id, org));\n \n const roots: OrganisationHierarchy[] = [];\n \n orgs.forEach(org => {\n if (!org.parent_id) {\n // Root organisation\n roots.push({\n organisation: org,\n children: [],\n depth: 0\n });\n }\n });\n \n // For now, return flat structure - hierarchy building can be added later\n return roots;\n }\n\n // Lifecycle methods\n async initialize(): Promise<void> {\n await super.initialize();\n \n // Don't load if already loading (prevents duplicate loads during rapid auth events)\n if (!this.isLoadingRef) {\n await this.loadUserOrganisations();\n }\n }\n\n cleanup(): void {\n // Cleanup on unmount\n this.isLoadingRef = false;\n this.hasFailedRef = false;\n this.lastLoadTimeRef = 0;\n // Don't abort pending requests - let them complete naturally\n // Aborting causes React StrictMode issues where requests are cancelled mid-flight\n // The requests will complete on their own and update state if needed\n if (this.abortControllerRef) {\n // Clear the reference but don't abort - let requests complete\n this.abortControllerRef = null;\n }\n // Reset state\n this._selectedOrganisation = null;\n this._organisations = [];\n this._userMemberships = [];\n this._roleMapState = new Map();\n this._isLoading = false;\n this._error = null;\n this._isContextReady = false;\n super.cleanup();\n }\n\n protected async doInitialize(): Promise<void> {\n // Initial setup\n }\n\n protected doCleanup(): void {\n // Cleanup any resources\n }\n\n private async setDatabaseOrganisationContext(organisation: Organisation): Promise<void> {\n if (!this.supabaseClient || !this.session) {\n console.warn('[OrganisationService] No Supabase client or session available for setting organisation context');\n this._isContextReady = false;\n this.notify();\n return;\n }\n\n try {\n console.log('[OrganisationService] Setting database organisation context for:', organisation.id);\n \n // Add timeout to prevent hanging\n const timeoutPromise = new Promise((_, reject) => {\n setTimeout(() => reject(new Error('Context setting timeout after 5 seconds')), 5000);\n });\n \n const contextPromise = setOrganisationContext(this.supabaseClient, organisation.id);\n \n await Promise.race([contextPromise, timeoutPromise]);\n \n console.log('[OrganisationService] Database organisation context set successfully');\n this._isContextReady = true;\n this.notify();\n } catch (error) {\n console.error('[OrganisationService] Failed to set database organisation context:', error);\n // Set context ready to true anyway - this is a non-critical operation\n // The app should still work without database context\n this._isContextReady = true;\n this.notify();\n // Don't throw - this is a non-critical operation\n }\n }\n\n private async loadUserOrganisations(): Promise<void> {\n // Add call tracking to detect race conditions\n const callId = Math.random().toString(36).substr(2, 9);\n console.log(`[OrganisationService] Starting loadUserOrganisations call ${callId}`);\n \n if (!this.user || !this.session || !this.supabaseClient) {\n // Clear state when no user, session, or supabase client\n this._selectedOrganisation = null;\n this._organisations = [];\n this._userMemberships = [];\n this._isLoading = false;\n this._error = null;\n this.notify();\n return;\n }\n\n // Additional check to prevent loading during auth state changes\n if (this.isLoadingRef) {\n console.log(\"OrganisationService\", \"Already loading, skipping duplicate load\");\n // Ensure loading state is correct\n this._isLoading = true;\n this.notify();\n return;\n }\n\n // Prevent rapid retries - minimum 2 seconds between attempts\n const now = Date.now();\n if (now - this.lastLoadTimeRef < 2000) {\n console.log(\"OrganisationService\", \"Too soon since last load, skipping\");\n // Ensure loading state is correct\n if (this._organisations.length > 0 || this._selectedOrganisation) {\n this._isLoading = false;\n } else {\n this._isLoading = true;\n }\n this.notify();\n return;\n }\n\n // Cancel any existing request\n if (this.abortControllerRef) {\n this.abortControllerRef.abort();\n }\n\n // Create new abort controller for this request\n this.abortControllerRef = new AbortController();\n const abortSignal = this.abortControllerRef.signal;\n\n this.lastLoadTimeRef = now;\n this.isLoadingRef = true;\n this._isLoading = true;\n this._error = null;\n this.notify();\n \n try {\n console.log(\"[OrganisationService] Supabase client ready:\", {\n isConnected: !!this.supabaseClient,\n hasAuth: !!this.supabaseClient.auth,\n hasRpc: !!this.supabaseClient.rpc\n });\n \n // Get user's organisation memberships using secure RPC function\n // Only get actual members (org_admin, leader, member) - exclude supporters\n let memberships, membershipError;\n try {\n console.log(\"[OrganisationService] Making RPC call to data_user_organisation_roles_get...\");\n \n // Add timeout and abort signal to prevent hanging RPC calls\n const timeoutPromise = new Promise((_, reject) => {\n const timeoutId = setTimeout(() => reject(new Error('RPC call timeout after 10 seconds')), 10000);\n abortSignal.addEventListener('abort', () => {\n clearTimeout(timeoutId);\n reject(new Error('Request aborted'));\n });\n });\n \n const rpcPromise = this.supabaseClient.rpc('data_user_organisation_roles_get', {\n p_user_id: this.user.id,\n p_organisation_id: null\n });\n \n // Check if request was aborted before making the call\n if (abortSignal.aborted) {\n throw new Error('Request aborted');\n }\n \n const result = await Promise.race([rpcPromise, timeoutPromise]) as any;\n \n console.log(\"[OrganisationService] RPC call completed:\", {\n hasData: !!result.data,\n hasError: !!result.error,\n dataLength: result.data?.length || 0,\n errorMessage: result.error?.message || 'No error'\n });\n \n // Filter to only actual members (org_admin, leader, member) - exclude supporters\n memberships = result.data?.filter((role: any) => \n ['org_admin', 'leader', 'member'].includes(role.role)\n ) || [];\n membershipError = result.error;\n } catch (queryError: any) {\n membershipError = queryError;\n }\n\n if (membershipError) {\n console.error(\"[OrganisationService] Error loading memberships:\", membershipError);\n \n // If RPC fails with timeout, try direct database query as fallback\n if (membershipError.message?.includes('timeout')) {\n console.log(\"[OrganisationService] RPC timed out, trying direct database query as fallback...\");\n try {\n // Check if request was aborted before making fallback query\n if (abortSignal.aborted) {\n throw new Error('Request aborted');\n }\n\n const { data: fallbackData, error: fallbackError } = await this.supabaseClient\n .from('rbac_organisation_roles')\n .select(`\n id,\n user_id,\n organisation_id,\n role,\n status,\n granted_at,\n granted_by,\n revoked_at,\n revoked_by,\n notes,\n created_at,\n updated_at,\n organisations!inner(\n id,\n name,\n display_name,\n subscription_tier,\n settings,\n is_active,\n parent_id,\n created_at,\n updated_at\n )\n `)\n .eq('user_id', this.user.id)\n .eq('status', 'active')\n .is('revoked_at', null)\n .in('role', ['org_admin', 'leader', 'member']);\n \n if (fallbackError) {\n console.error(\"[OrganisationService] Fallback query also failed:\", fallbackError);\n throw membershipError; // Throw original error\n }\n \n console.log(\"[OrganisationService] Fallback query successful, got\", fallbackData?.length || 0, \"memberships\");\n memberships = fallbackData || [];\n membershipError = null;\n } catch (fallbackErr) {\n console.error(\"[OrganisationService] Fallback query failed:\", fallbackErr);\n throw membershipError; // Throw original error\n }\n } else {\n throw membershipError;\n }\n }\n \n if (!memberships || memberships.length === 0) {\n throw new Error('User has no active organisation memberships') as OrganisationSecurityError;\n }\n\n // Get organisation details for the memberships\n const organisationIds = memberships\n .map((m: any) => m.organisation_id)\n .filter((id: string) => {\n // Better validation to prevent empty string UUID errors\n if (!id || typeof id !== 'string') {\n console.warn(\"[OrganisationService] Invalid organisation ID (not string):\", id);\n return false;\n }\n const trimmedId = id.trim();\n if (trimmedId === '') {\n console.warn(\"[OrganisationService] Empty organisation ID found\");\n return false;\n }\n // Validate UUID format\n const isValidUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(trimmedId);\n if (!isValidUuid) {\n console.warn(\"[OrganisationService] Invalid UUID format:\", trimmedId);\n }\n return isValidUuid;\n });\n \n if (organisationIds.length === 0) {\n console.warn(\"[OrganisationService] No valid organisation IDs found in memberships:\", memberships);\n throw new Error('No valid organisation IDs found in memberships') as OrganisationSecurityError;\n }\n \n // Check if request was aborted before making organisations query\n if (abortSignal.aborted) {\n throw new Error('Request aborted');\n }\n \n const { data: allOrganisations, error: orgError } = await this.supabaseClient\n .from('organisations')\n .select('id, name, display_name, subscription_tier, settings, is_active, parent_id, created_at, updated_at');\n \n if (orgError) {\n console.error(\"[OrganisationService] Error loading organisations:\", orgError);\n throw orgError;\n }\n \n // Filter manually on the client side\n const organisations = allOrganisations?.filter(org => \n organisationIds.includes(org.id)\n ) || [];\n\n // Create a map of organisation_id to role from the memberships data\n const roleMap = new Map<string, string>();\n memberships?.forEach((membership: any) => {\n roleMap.set(membership.organisation_id, membership.role);\n });\n\n // Extract organisations and memberships\n const orgs = organisations as Organisation[];\n const activeOrgs = orgs.filter(org => org.is_active);\n \n if (activeOrgs.length === 0) {\n throw new Error('User has no access to active organisations') as OrganisationSecurityError;\n }\n\n this._organisations = activeOrgs;\n this._userMemberships = memberships as OrganisationMembership[];\n \n // Store role map in component state for later use\n this._roleMapState = roleMap;\n \n // Auto-select organisation: try persisted, then primary, then first\n let initialOrg: Organisation | null = null;\n \n // 1. Try to restore from localStorage\n try {\n const persistedOrgString = localStorage.getItem('pace-core-selected-organisation');\n if (persistedOrgString) {\n const persistedOrg = JSON.parse(persistedOrgString) as Organisation;\n // Validate persisted org ID before using it\n if (persistedOrg.id && typeof persistedOrg.id === 'string' && persistedOrg.id.trim() !== '') {\n const validPersistedOrg = activeOrgs.find(org => org.id === persistedOrg.id);\n if (validPersistedOrg) {\n initialOrg = validPersistedOrg;\n } else {\n console.warn(\"[OrganisationService] Persisted organisation not found in active orgs, clearing cache\");\n localStorage.removeItem('pace-core-selected-organisation');\n }\n } else {\n console.warn(\"[OrganisationService] Invalid persisted organisation ID, clearing cache\");\n localStorage.removeItem('pace-core-selected-organisation');\n }\n }\n } catch (storageError) {\n console.warn(\"[OrganisationService] Failed to restore persisted organisation:\", storageError);\n // Clear potentially corrupted cache\n localStorage.removeItem('pace-core-selected-organisation');\n }\n \n // 2. Fall back to org_admin role organisation (highest privilege)\n if (!initialOrg) {\n const adminMembership = memberships.find((m: any) => m.role === 'org_admin');\n if (adminMembership) {\n const foundOrg = organisations.find((org) => org.id === adminMembership.organisation_id);\n if (foundOrg) {\n initialOrg = foundOrg;\n }\n }\n }\n \n // 3. Fall back to first organisation\n if (!initialOrg) {\n initialOrg = activeOrgs[0];\n }\n \n if (!initialOrg) {\n throw new Error('No valid organisation found for user') as OrganisationSecurityError;\n }\n\n this._selectedOrganisation = initialOrg;\n \n // Persist selection\n localStorage.setItem('pace-core-selected-organisation', JSON.stringify(initialOrg));\n \n // Set database organisation context\n await this.setDatabaseOrganisationContext(initialOrg);\n \n // Reset retry count and failed flag on success\n this.retryCount = 0;\n this.hasFailedRef = false;\n \n } catch (err) {\n console.error(\"[OrganisationService] Failed to load organisations:\", err);\n this._error = err as Error;\n // Increment retry count on error\n this.retryCount = this.retryCount + 1;\n // Set failed flag to prevent further attempts\n this.hasFailedRef = true;\n // Clear all cached data on error to prevent corruption\n this.clearAllCachedData();\n } finally {\n // Always cleanup refs and abort controller\n this.isLoadingRef = false;\n this._isLoading = false;\n this.abortControllerRef = null;\n this.notify();\n }\n }\n\n private clearAllCachedData(): void {\n localStorage.removeItem('pace-core-selected-organisation');\n localStorage.removeItem('pace-core-organisation-context');\n this._selectedOrganisation = null;\n this._organisations = [];\n this._userMemberships = [];\n this._roleMapState = new Map();\n this.retryCount = 0;\n this._isContextReady = false;\n // Don't clear _error here - let it persist for error reporting\n }\n}","/**\n * @file Organisation Service Provider\n * @package @jmruthers/pace-core\n * @module Providers/Services\n * @since 0.1.0\n *\n * React provider for OrganisationService.\n * Provides organisation service instance to React components.\n */\n\nimport React, { createContext, useContext, useMemo, useEffect, useRef } from 'react';\nimport { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';\nimport { OrganisationService } from '../../services/OrganisationService';\n\n// Context type\nexport interface OrganisationServiceContextType {\n organisationService: OrganisationService;\n}\n\nexport const OrganisationServiceContext = createContext<OrganisationServiceContextType | null>(null);\n\nexport interface OrganisationServiceProviderProps {\n children: React.ReactNode;\n supabaseClient: SupabaseClient;\n user: User | null;\n session: Session | null;\n}\n\nexport function OrganisationServiceProvider({ \n children, \n supabaseClient, \n user, \n session \n}: OrganisationServiceProviderProps) {\n // Create service instance once with useRef to avoid recreation on auth state changes\n const organisationServiceRef = useRef<OrganisationService | null>(null);\n \n if (!organisationServiceRef.current) {\n organisationServiceRef.current = new OrganisationService(supabaseClient, user, session);\n }\n \n const organisationService = organisationServiceRef.current;\n\n // Update service dependencies when they change without recreation\n useEffect(() => {\n organisationService.updateDependencies(user, session);\n \n // Re-initialize service when user/session changes\n let isMounted = true;\n \n organisationService.initialize().catch(error => {\n if (isMounted) {\n console.error('[OrganisationServiceProvider] Failed to initialize organisation service:', error);\n }\n });\n\n return () => {\n isMounted = false;\n };\n }, [organisationService, user, session]);\n\n const contextValue = useMemo(() => ({\n organisationService\n }), [organisationService]);\n\n return (\n <OrganisationServiceContext.Provider value={contextValue}>\n {children}\n </OrganisationServiceContext.Provider>\n );\n}\n\nexport const useOrganisationService = (): OrganisationService => {\n const context = useContext(OrganisationServiceContext);\n \n if (!context) {\n throw new Error('useOrganisationService must be used within OrganisationServiceProvider');\n }\n \n return context.organisationService;\n};","/**\n * @file Event Service\n * @package @jmruthers/pace-core\n * @module Services\n * @since 0.1.0\n *\n * Event service implementation.\n * Handles event management and selection with organisation context validation.\n */\n\nimport { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';\nimport { BaseService } from './base/BaseService';\nimport { IEventService } from './interfaces/IEventService';\nimport { Event } from '../types/unified';\nimport { Organisation } from '../types/organisation';\nimport { DebugLogger } from '../utils/debugLogger';\nimport { applyPalette, clearPalette } from '../theming/runtime';\n\nexport class EventService extends BaseService implements IEventService {\n private events: Event[] = [];\n private selectedEvent: Event | null = null;\n private _isLoading = false; // Start as false to avoid blocking UI\n private error: Error | null = null;\n\n // Dependencies\n private supabaseClient: SupabaseClient | null = null;\n private user: User | null = null;\n private session: Session | null = null;\n private appName: string = '';\n private selectedOrganisation: Organisation | null = null;\n private setSelectedEventId: ((eventId: string | null) => void) | null = null;\n\n // Internal state management\n private isInitializedRef = false;\n private isFetchingRef = false;\n private hasAutoSelectedRef = false;\n private userClearedEventRef = false;\n\n constructor(\n supabaseClient: SupabaseClient,\n user: User | null,\n session: Session | null,\n appName: string,\n selectedOrganisation: Organisation | null,\n setSelectedEventId: (eventId: string | null) => void\n ) {\n super();\n this.supabaseClient = supabaseClient;\n this.user = user;\n this.session = session;\n this.appName = appName;\n this.selectedOrganisation = selectedOrganisation;\n this.setSelectedEventId = setSelectedEventId;\n }\n\n // Update dependencies\n updateDependencies(\n supabaseClient: SupabaseClient,\n user: User | null,\n session: Session | null,\n appName: string,\n selectedOrganisation: Organisation | null,\n setSelectedEventId: (eventId: string | null) => void\n ): void {\n const previousOrgId = this.selectedOrganisation?.id;\n const newOrgId = selectedOrganisation?.id;\n \n this.supabaseClient = supabaseClient;\n this.user = user;\n this.session = session;\n this.appName = appName;\n this.selectedOrganisation = selectedOrganisation;\n this.setSelectedEventId = setSelectedEventId;\n \n // If organisation changed (from null to value, or different org), reset initialization\n // This ensures events are re-fetched when organisation context becomes available\n if (previousOrgId !== newOrgId) {\n this.resetInitialization(); // Reset BaseService's isInitialized flag\n this.isInitializedRef = false;\n this.isFetchingRef = false;\n // Clear events when switching organisations\n if (previousOrgId !== null && newOrgId !== previousOrgId) {\n this.events = [];\n this.selectedEvent = null;\n }\n }\n \n this.notify();\n }\n\n // Event state getters\n getEvents(): Event[] {\n return this.events;\n }\n\n getSelectedEvent(): Event | null {\n return this.selectedEvent;\n }\n\n isLoading(): boolean {\n return this._isLoading;\n }\n\n getError(): Error | null {\n return this.error;\n }\n\n // Event methods\n setSelectedEvent(event: Event | null): void {\n if (event) {\n // SECURITY: Validate event belongs to current organisation\n try {\n console.log('[EventService] Event selection validation:', {\n eventId: event.event_id,\n eventName: event.event_name,\n eventOrganisationId: event.organisation_id,\n selectedOrganisationId: this.selectedOrganisation?.id,\n selectedOrganisationName: this.selectedOrganisation?.display_name,\n match: event.organisation_id === this.selectedOrganisation?.id\n });\n \n if (this.selectedOrganisation && event.organisation_id !== this.selectedOrganisation.id) {\n console.error('[EventService] Event organisation_id does not match selected organisation', {\n eventOrganisationId: event.organisation_id,\n selectedOrganisationId: this.selectedOrganisation.id,\n eventName: event.event_name\n });\n return;\n }\n } catch (error) {\n console.error('[EventService] Error during event validation:', error);\n }\n\n this.selectedEvent = event;\n this.setSelectedEventId?.(event.event_id);\n this.persistEventSelection(event.event_id);\n // Reset the user cleared flag when selecting an event\n this.userClearedEventRef = false;\n // Apply theme for the newly selected event\n this.updateThemeForSelectedEvent();\n } else {\n this.selectedEvent = null;\n this.setSelectedEventId?.(null);\n // Clear both sessionStorage and localStorage\n sessionStorage.removeItem('pace-core-selected-event');\n localStorage.removeItem('pace-core-selected-event');\n // Reset the auto-selection flag when clearing the event\n this.hasAutoSelectedRef = false;\n // Mark that user explicitly cleared the event to prevent auto-selection\n this.userClearedEventRef = true;\n // Clear theme when event is cleared\n this.updateThemeForSelectedEvent();\n }\n this.notify();\n }\n\n async refreshEvents(): Promise<void> {\n this.isInitializedRef = false;\n this.isFetchingRef = false;\n // Don't reset the user cleared flag - respect user's choice\n await this.fetchEvents();\n }\n\n async loadPersistedEvent(events: Event[]): Promise<boolean> {\n try {\n // Try sessionStorage first (tab-specific)\n let persistedEventId = sessionStorage.getItem('pace-core-selected-event');\n \n // Fallback to localStorage if no sessionStorage value (for new tabs)\n if (!persistedEventId) {\n persistedEventId = localStorage.getItem('pace-core-selected-event');\n // If we found a value in localStorage, also store it in sessionStorage for this tab\n if (persistedEventId) {\n sessionStorage.setItem('pace-core-selected-event', persistedEventId);\n }\n }\n \n if (persistedEventId && events.length > 0) {\n const persistedEvent = events.find(event => event.event_id === persistedEventId);\n if (persistedEvent) {\n this.selectedEvent = persistedEvent;\n this.setSelectedEventId?.(persistedEventId);\n // Apply theme for persisted event\n this.updateThemeForSelectedEvent();\n return true;\n } else {\n // Clear invalid persisted event\n sessionStorage.removeItem('pace-core-selected-event');\n localStorage.removeItem('pace-core-selected-event');\n }\n }\n } catch (error) {\n console.warn('[EventService] Failed to load persisted event:', error);\n }\n return false;\n }\n\n persistEventSelection(eventId: string): void {\n try {\n // Store in sessionStorage for tab-specific persistence\n sessionStorage.setItem('pace-core-selected-event', eventId);\n // Also store in localStorage as fallback for new tabs\n localStorage.setItem('pace-core-selected-event', eventId);\n } catch (error) {\n console.warn('[EventService] Failed to persist event selection:', error);\n }\n }\n\n clearEventSelection(): void {\n try {\n // Clear from both storage locations\n sessionStorage.removeItem('pace-core-selected-event');\n localStorage.removeItem('pace-core-selected-event');\n // Clear the selected event\n this.selectedEvent = null;\n this.setSelectedEventId?.(null);\n } catch (error) {\n console.warn('[EventService] Failed to clear event selection:', error);\n }\n }\n\n autoSelectNextEvent(events: Event[]): void {\n const nextEvent = this.getNextEventByDate(events);\n if (nextEvent) {\n this.selectedEvent = nextEvent;\n this.setSelectedEventId?.(nextEvent.event_id);\n this.persistEventSelection(nextEvent.event_id);\n // Apply theme for auto-selected event\n this.updateThemeForSelectedEvent();\n }\n }\n\n // Lifecycle methods\n async initialize(): Promise<void> {\n await super.initialize();\n await this.fetchEvents();\n }\n\n cleanup(): void {\n super.cleanup();\n }\n\n protected async doInitialize(): Promise<void> {\n // Initial setup - fetch events on initialization\n await this.fetchEvents();\n }\n\n protected doCleanup(): void {\n // Cleanup any resources\n }\n\n private async fetchEvents(): Promise<void> {\n if (!this.user || !this.session || !this.supabaseClient || !this.appName || !this.selectedOrganisation) {\n // Already false from initialization, just notify\n this.notify();\n return;\n }\n \n // Only set loading to true if we actually have dependencies and are going to fetch\n this._isLoading = true;\n this.notify();\n\n // Prevent multiple simultaneous fetches\n if (this.isFetchingRef) {\n return;\n }\n\n this.isFetchingRef = true;\n let isMounted = true;\n\n try {\n // Call the RPC function following the established pattern\n const { data, error: rpcError } = await this.supabaseClient.rpc('data_user_events_get', {\n p_user_id: this.user.id,\n p_organisation_id: this.selectedOrganisation.id,\n p_app_name: this.appName\n });\n\n if (rpcError) {\n throw new Error(rpcError.message || 'Failed to fetch events');\n }\n\n if (isMounted) {\n const eventsData = data || [];\n console.log('[EventService] Loaded events:', eventsData.map((event: any) => ({\n eventId: event.event_id,\n eventName: event.event_name,\n organisationId: event.organisation_id,\n selectedOrganisationId: this.selectedOrganisation?.id\n })));\n\n // Transform the data to match our Event interface\n const transformedEvents: Event[] = eventsData.map((event: any) => ({\n id: event.event_id, // Use event_id as the primary id\n event_id: event.event_id,\n event_name: event.event_name,\n event_date: event.event_date,\n event_venue: event.event_venue,\n event_participants: event.event_participants,\n event_colours: event.event_colours,\n event_logo: '', // No logo field in event table\n organisation_id: event.organisation_id,\n is_visible: event.is_visible,\n // Legacy compatibility\n name: event.event_name,\n start_date: event.event_date\n }));\n\n this.events = transformedEvents;\n console.log('[EventService] Set events in service:', {\n count: transformedEvents.length,\n events: transformedEvents.map(e => ({ id: e.event_id, name: e.event_name }))\n });\n this.error = null;\n\n // Reset auto-selection ref for new events\n this.hasAutoSelectedRef = false;\n\n // Try to restore persisted event first\n const persistedEventLoaded = await this.loadPersistedEvent(transformedEvents);\n \n // If no persisted event was loaded and user hasn't explicitly cleared an event, auto-select the next event\n if (!persistedEventLoaded && !this.userClearedEventRef) {\n const nextEvent = this.getNextEventByDate(transformedEvents);\n if (nextEvent) {\n this.hasAutoSelectedRef = true;\n this.selectedEvent = nextEvent;\n this.setSelectedEventId?.(nextEvent.event_id);\n this.persistEventSelection(nextEvent.event_id);\n }\n }\n }\n } catch (err) {\n console.error('[EventService] Error fetching events:', err);\n const _error = err instanceof Error ? err : new Error('Unknown error occurred');\n \n if (isMounted) {\n this.error = _error;\n this.events = [];\n }\n } finally {\n if (isMounted) {\n this._isLoading = false;\n }\n this.isFetchingRef = false;\n this.notify();\n }\n }\n\n /**\n * Parse and normalize event_colours to PaletteData (supports ev-* keys and string JSON)\n */\n private parseAndNormalizeEventColours(input: unknown): { main: any; sec: any; acc: any } | null {\n try {\n if (!input) return null;\n let obj: any = input;\n if (typeof input === 'string') {\n try {\n obj = JSON.parse(input);\n } catch {\n return null;\n }\n } else if (typeof input !== 'object') {\n return null;\n }\n\n const pick = (o: any, pref: string, plain: string) => (o?.[pref] ?? o?.[plain]) || null;\n const main = pick(obj, 'ev-main', 'main');\n const sec = pick(obj, 'ev-sec', 'sec');\n const acc = pick(obj, 'ev-acc', 'acc');\n if (!main && !sec && !acc) return null;\n\n // Fill helper: ensure all TW shades exist using raw or 500 as fallback\n const shades = ['50','100','200','300','400','500','600','700','800','900','950'];\n const fill = (p: any) => {\n if (!p) return {} as any;\n const out: any = {};\n for (const s of shades) out[s] = p[s] || p?.raw || p?.['500'];\n if (p?.raw) out.raw = p.raw;\n return out;\n };\n\n return { main: fill(main), sec: fill(sec), acc: fill(acc) };\n } catch (error) {\n console.warn('[EventService] Failed to parse/normalize event colours:', error);\n return null;\n }\n }\n\n /**\n * Apply or clear runtime theme variables based on the current selected event's colours\n */\n private updateThemeForSelectedEvent(): void {\n try {\n const normalized = this.parseAndNormalizeEventColours(this.selectedEvent?.event_colours);\n if (normalized) {\n applyPalette(normalized);\n } else {\n clearPalette();\n }\n } catch (error) {\n console.warn('[EventService] Failed to update theme from event colours:', error);\n }\n }\n\n getNextEventByDate(events?: Event[]): Event | null {\n const eventsToUse = events || this.events;\n if (!eventsToUse || eventsToUse.length === 0) {\n return null;\n }\n\n // Get start of today (midnight) to compare dates only (ignore time)\n const now = new Date();\n const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();\n \n const futureEvents = eventsToUse.filter(event => {\n if (!event.event_date) return false;\n const eventDate = new Date(event.event_date);\n // Compare by date only (start of day), not by time\n const startOfEventDate = new Date(eventDate.getFullYear(), eventDate.getMonth(), eventDate.getDate()).getTime();\n return startOfEventDate >= startOfToday;\n });\n\n if (futureEvents.length === 0) {\n return null;\n }\n\n // Sort by date (ascending) to get the next event\n const sortedFutureEvents = futureEvents.sort((a, b) => {\n const dateA = new Date(a.event_date!);\n const dateB = new Date(b.event_date!);\n return dateA.getTime() - dateB.getTime();\n });\n\n return sortedFutureEvents[0];\n }\n}","/**\n * @file Event Service Provider\n * @package @jmruthers/pace-core\n * @module Providers/Services\n * @since 0.1.0\n *\n * React provider for EventService.\n * Provides event service instance to React components.\n */\n\nimport React, { createContext, useContext, useMemo, useEffect, useRef } from 'react';\nimport { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';\nimport { EventService } from '../../services/EventService';\n\n// Context type\nexport interface EventServiceContextType {\n eventService: EventService;\n}\n\n// Backward compatibility type alias\nexport type EventContextType = EventServiceContextType;\n\nexport const EventServiceContext = createContext<EventServiceContextType | null>(null);\n\nexport interface EventServiceProviderProps {\n children: React.ReactNode;\n supabaseClient: SupabaseClient;\n user: User | null;\n session: Session | null;\n appName: string;\n selectedOrganisation: any;\n setSelectedEventId: (eventId: string | null) => void;\n}\n\nexport function EventServiceProvider({ \n children, \n supabaseClient, \n user, \n session, \n appName,\n selectedOrganisation,\n setSelectedEventId\n}: EventServiceProviderProps) {\n // Create service instance once with useRef to avoid recreation on dependency changes\n const eventServiceRef = useRef<EventService | null>(null);\n \n if (!eventServiceRef.current) {\n eventServiceRef.current = new EventService(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);\n }\n \n const eventService = eventServiceRef.current;\n\n // Update service dependencies and initialize when dependencies change\n useEffect(() => {\n eventService.updateDependencies(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);\n \n // Re-initialize service when dependencies change\n let isMounted = true;\n \n eventService.initialize().catch(error => {\n if (isMounted) {\n console.error('[EventServiceProvider] Failed to initialize event service:', error);\n }\n });\n\n return () => {\n isMounted = false;\n };\n }, [eventService, supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId]);\n\n const contextValue = useMemo(() => ({\n eventService\n }), [eventService]);\n\n return (\n <EventServiceContext.Provider value={contextValue}>\n {children}\n </EventServiceContext.Provider>\n );\n}\n\nexport const useEventService = (): EventService => {\n const context = useContext(EventServiceContext);\n \n if (!context) {\n throw new Error('useEventService must be used within EventServiceProvider');\n }\n \n return context.eventService;\n};","/**\n * @file Inactivity Service\n * @package @jmruthers/pace-core\n * @module Services\n * @since 0.1.0\n *\n * Inactivity service implementation.\n * Handles inactivity tracking, auto-logout, and warning modals.\n */\n\nimport { BaseService } from './base/BaseService';\nimport { IInactivityService } from './interfaces/IInactivityService';\n\nexport class InactivityService extends BaseService implements IInactivityService {\n private _showInactivityWarning = false;\n private _inactivityTimeRemaining = 0;\n private _isIdle = false;\n private _timeRemaining = 0;\n private _showWarning = false;\n private _isTracking = false;\n\n // Dependencies\n private supabaseClient: any = null;\n private user: any = null;\n private session: any = null;\n private idleTimeoutMs = 30 * 60 * 1000; // 30 minutes\n private warnBeforeMs = 60 * 1000; // 60 seconds\n private onIdleLogout: ((reason: 'inactivity') => void) | null = null;\n\n // Internal state management\n private inactivityTracker: any = null;\n private isInactivityEnabled = true;\n\n constructor(\n supabaseClient: any,\n user: any,\n session: any,\n idleTimeoutMs: number = 30 * 60 * 1000,\n warnBeforeMs: number = 60 * 1000,\n onIdleLogout: (reason: 'inactivity') => void\n ) {\n super();\n this.supabaseClient = supabaseClient;\n this.user = user;\n this.session = session;\n this.idleTimeoutMs = idleTimeoutMs;\n this.warnBeforeMs = warnBeforeMs;\n this.onIdleLogout = onIdleLogout;\n \n // Initialize time remaining to idle timeout\n this._timeRemaining = idleTimeoutMs;\n }\n\n // Interface implementation\n isIdle(): boolean { return this._isIdle; }\n getTimeRemaining(): number { return this._timeRemaining; }\n isWarningShown(): boolean { return this._showWarning; }\n isTracking(): boolean { return this._isTracking; }\n getShowInactivityWarning(): boolean { return this._showInactivityWarning; }\n getInactivityTimeRemaining(): number { return this._inactivityTimeRemaining; }\n\n // Additional getter methods that tests expect\n getIsIdle(): boolean { return this._isIdle; }\n getIsTracking(): boolean { return this._isTracking; }\n getShowWarning(): boolean { return this._showWarning; }\n\n // Additional methods for testing\n setShowInactivityWarning(value: boolean): void {\n this._showInactivityWarning = value;\n this.notify();\n }\n\n setInactivityTimeRemaining(value: number): void {\n this._inactivityTimeRemaining = value;\n this.notify();\n }\n\n setIsIdle(value: boolean): void {\n this._isIdle = value;\n this.notify();\n }\n\n setTimeRemaining(value: number): void {\n this._timeRemaining = value;\n this.notify();\n }\n\n setShowWarning(value: boolean): void {\n this._showWarning = value;\n this.notify();\n }\n\n setIsTracking(value: boolean): void {\n this._isTracking = value;\n this.notify();\n }\n\n triggerWarning(timeRemaining: number): void {\n this._showInactivityWarning = true;\n this._inactivityTimeRemaining = Math.ceil(timeRemaining / 1000);\n this._showWarning = true;\n this.notify();\n }\n\n triggerIdle(): void {\n this._isIdle = true;\n this.handleIdleLogout();\n this.notify();\n }\n\n // Update dependencies\n updateDependencies(\n supabaseClient: any,\n user: any,\n session: any,\n idleTimeoutMs?: number,\n warnBeforeMs?: number,\n onIdleLogout?: (reason: 'inactivity') => void\n ): void {\n this.supabaseClient = supabaseClient;\n this.user = user;\n this.session = session;\n if (idleTimeoutMs !== undefined) this.idleTimeoutMs = idleTimeoutMs;\n if (warnBeforeMs !== undefined) this.warnBeforeMs = warnBeforeMs;\n if (onIdleLogout !== undefined) this.onIdleLogout = onIdleLogout;\n this.notify();\n }\n\n // Inactivity methods\n resetActivity(): void {\n if (this.inactivityTracker) {\n this.inactivityTracker.resetActivity();\n }\n this._isIdle = false;\n this._showWarning = false;\n this._showInactivityWarning = false;\n this._inactivityTimeRemaining = 0;\n this._timeRemaining = this.idleTimeoutMs;\n this.notify();\n }\n\n startTracking(): void {\n if (this.inactivityTracker) {\n this.inactivityTracker.startTracking();\n }\n this._isTracking = true;\n this.notify();\n }\n\n stopTracking(): void {\n if (this.inactivityTracker) {\n this.inactivityTracker.stopTracking();\n }\n this._isTracking = false;\n this.notify();\n }\n\n async handleIdleLogout(): Promise<void> {\n // Hide warning\n this._showInactivityWarning = false;\n this._inactivityTimeRemaining = 0;\n \n // Stop tracking\n this.stopTracking();\n \n // Sign out via Supabase\n try {\n if (this.supabaseClient) {\n await this.supabaseClient.auth.signOut();\n }\n } catch (error: any) {\n console.error('[InactivityService] Error during idle logout:', error);\n }\n \n // Call app callback for navigation/redirect\n this.onIdleLogout?.('inactivity');\n this.notify();\n }\n\n handleStaySignedIn(): void {\n this._showInactivityWarning = false;\n this._inactivityTimeRemaining = 0;\n this.resetActivity();\n this.notify();\n }\n\n async handleSignOutNow(): Promise<void> {\n this._showInactivityWarning = false;\n this._inactivityTimeRemaining = 0;\n this.stopTracking();\n \n // Sign out via Supabase\n try {\n if (this.supabaseClient) {\n await this.supabaseClient.auth.signOut();\n }\n } catch (error: any) {\n console.error('[InactivityService] Error during manual sign out:', error);\n }\n \n // Call app callback for navigation/redirect\n this.onIdleLogout?.('inactivity');\n this.notify();\n }\n\n // Lifecycle methods\n async initialize(): Promise<void> {\n await super.initialize();\n await this.setupInactivityTracker();\n }\n\n cleanup(): void {\n if (this.inactivityTracker) {\n this.inactivityTracker.cleanup?.();\n this.inactivityTracker = null;\n }\n this._isTracking = false;\n this._isIdle = false;\n this._showWarning = false;\n this._showInactivityWarning = false;\n this._timeRemaining = 0;\n this._inactivityTimeRemaining = 0;\n super.cleanup();\n }\n\n protected async doInitialize(): Promise<void> {\n // Production safety check for inactivity feature\n if (typeof window !== 'undefined') {\n const isProduction = import.meta.env.MODE === 'production';\n \n if (isProduction) {\n console.warn('[InactivityService] Inactivity feature enabled in production');\n }\n }\n }\n\n protected doCleanup(): void {\n // Cleanup any resources\n }\n\n private async setupInactivityTracker(): Promise<void> {\n if (typeof window === 'undefined') return;\n\n // Check if inactivity is enabled\n this.isInactivityEnabled = this.user && this.session;\n\n if (!this.isInactivityEnabled) {\n return;\n }\n\n try {\n // Dynamically import the inactivity tracker hook\n const { useInactivityTracker } = await import('../hooks/useInactivityTracker');\n \n // Create a mock implementation since we can't use hooks in services\n // In a real implementation, you'd need to create a non-hook version\n this.inactivityTracker = {\n isIdle: false,\n timeRemaining: 0,\n showWarning: false,\n isTracking: false,\n resetActivity: () => {\n this._isIdle = false;\n this._timeRemaining = 0;\n this._showWarning = false;\n this.notify();\n },\n startTracking: () => {\n this._isTracking = true;\n this.notify();\n },\n stopTracking: () => {\n this._isTracking = false;\n this.notify();\n },\n cleanup: () => {\n this._isTracking = false;\n this._isIdle = false;\n this._showWarning = false;\n this._timeRemaining = 0;\n }\n };\n\n // Set up event handlers\n this.setupEventHandlers();\n } catch (error) {\n console.error('[InactivityService] Failed to setup inactivity tracker:', error);\n }\n }\n\n private setupEventHandlers(): void {\n if (typeof window === 'undefined') return;\n\n let idleTimer: NodeJS.Timeout | null = null;\n let warningTimer: NodeJS.Timeout | null = null;\n let lastActivity = Date.now();\n\n const resetTimers = () => {\n lastActivity = Date.now();\n \n if (idleTimer) {\n clearTimeout(idleTimer);\n idleTimer = null;\n }\n \n if (warningTimer) {\n clearTimeout(warningTimer);\n warningTimer = null;\n }\n\n this._showInactivityWarning = false;\n this._inactivityTimeRemaining = 0;\n this._isIdle = false;\n this._showWarning = false;\n this.notify();\n };\n\n const startIdleTimer = () => {\n if (idleTimer) {\n clearTimeout(idleTimer);\n }\n\n idleTimer = setTimeout(() => {\n this._isIdle = true;\n this._showWarning = true;\n this.notify();\n \n // Start warning timer\n warningTimer = setTimeout(() => {\n this.handleIdleLogout();\n }, this.warnBeforeMs);\n }, this.idleTimeoutMs - this.warnBeforeMs);\n };\n\n const startWarningTimer = () => {\n if (warningTimer) {\n clearTimeout(warningTimer);\n }\n\n warningTimer = setTimeout(() => {\n this.handleIdleLogout();\n }, this.warnBeforeMs);\n };\n\n // Activity detection\n const activityEvents = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart', 'click'];\n \n const handleActivity = () => {\n resetTimers();\n startIdleTimer();\n };\n\n // Add event listeners\n activityEvents.forEach(event => {\n document.addEventListener(event, handleActivity, true);\n });\n\n // Start initial timer\n startIdleTimer();\n\n // Store cleanup function\n this.inactivityTracker.cleanup = () => {\n if (idleTimer) {\n clearTimeout(idleTimer);\n idleTimer = null;\n }\n \n if (warningTimer) {\n clearTimeout(warningTimer);\n warningTimer = null;\n }\n\n activityEvents.forEach(event => {\n document.removeEventListener(event, handleActivity, true);\n });\n\n this._isTracking = false;\n this._isIdle = false;\n this._showWarning = false;\n this._timeRemaining = 0;\n this._showInactivityWarning = false;\n this._inactivityTimeRemaining = 0;\n };\n\n this._isTracking = true;\n this.notify();\n }\n}","/**\n * @file Inactivity Service Provider\n * @package @jmruthers/pace-core\n * @module Providers/Services\n * @since 0.1.0\n *\n * React provider for InactivityService.\n * Provides inactivity service instance to React components.\n */\n\nimport React, { createContext, useContext, useMemo, useEffect, useRef } from 'react';\nimport { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';\nimport { InactivityService } from '../../services/InactivityService';\n\n// Context type\nexport interface InactivityServiceContextType {\n inactivityService: InactivityService;\n}\n\nexport const InactivityServiceContext = createContext<InactivityServiceContextType | null>(null);\n\nexport interface InactivityServiceProviderProps {\n children: React.ReactNode;\n supabaseClient: SupabaseClient;\n user: User | null;\n session: Session | null;\n idleTimeoutMs?: number;\n warnBeforeMs?: number;\n onIdleLogout: (reason: 'inactivity') => void;\n}\n\nexport function InactivityServiceProvider({ \n children, \n supabaseClient, \n user, \n session, \n idleTimeoutMs = 30 * 60 * 1000,\n warnBeforeMs = 60 * 1000,\n onIdleLogout\n}: InactivityServiceProviderProps) {\n // Create service instance once with useRef to avoid recreation on dependency changes\n const inactivityServiceRef = useRef<InactivityService | null>(null);\n \n if (!inactivityServiceRef.current) {\n inactivityServiceRef.current = new InactivityService(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout);\n }\n \n const inactivityService = inactivityServiceRef.current;\n\n // Update service dependencies and initialize when dependencies change\n useEffect(() => {\n inactivityService.updateDependencies(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout);\n \n // Re-initialize service when dependencies change\n let isMounted = true;\n \n inactivityService.initialize().catch(error => {\n if (isMounted) {\n console.error('[InactivityServiceProvider] Failed to initialize inactivity service:', error);\n }\n });\n\n return () => {\n isMounted = false;\n };\n }, [inactivityService, supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout]);\n\n const contextValue = useMemo(() => ({\n inactivityService\n }), [inactivityService]);\n\n return (\n <InactivityServiceContext.Provider value={contextValue}>\n {children}\n </InactivityServiceContext.Provider>\n );\n}\n\nexport const useInactivityService = (): InactivityService => {\n const context = useContext(InactivityServiceContext);\n \n if (!context) {\n throw new Error('useInactivityService must be used within InactivityServiceProvider');\n }\n \n return context.inactivityService;\n};","/**\n * @file Auth Service Hook\n * @package @jmruthers/pace-core\n * @module Hooks/Services\n * @since 0.1.0\n *\n * React hook for AuthService.\n * Provides authentication service with reactive state updates.\n */\n\nimport { useContext, useReducer, useEffect } from 'react';\nimport { AuthServiceContext } from '../../providers/services/AuthServiceProvider';\nimport { AuthService } from '../../services/AuthService';\n\nexport function useAuthService(): AuthService {\n const context = useContext(AuthServiceContext);\n \n if (!context) {\n throw new Error('useAuthService must be used within AuthServiceProvider');\n }\n \n // Subscribe to service state changes\n const [, forceUpdate] = useReducer(x => x + 1, 0);\n \n useEffect(() => {\n return context.authService.subscribe(() => forceUpdate());\n }, [context.authService]);\n \n return context.authService;\n}","/**\n * @file Organisation Service Hook\n * @package @jmruthers/pace-core\n * @module Hooks/Services\n * @since 0.1.0\n *\n * React hook for OrganisationService.\n * Provides organisation service with reactive state updates.\n */\n\nimport { useContext, useReducer, useEffect } from 'react';\nimport { OrganisationServiceContext } from '../../providers/services/OrganisationServiceProvider';\nimport { OrganisationService } from '../../services/OrganisationService';\n\nexport function useOrganisationService(): OrganisationService {\n const context = useContext(OrganisationServiceContext);\n \n if (!context) {\n throw new Error('useOrganisationService must be used within OrganisationServiceProvider');\n }\n \n // Subscribe to service state changes\n const [, forceUpdate] = useReducer(x => x + 1, 0);\n \n useEffect(() => {\n return context.organisationService.subscribe(() => forceUpdate());\n }, [context.organisationService]);\n \n return context.organisationService;\n}","/**\n * @file Event Service Hook\n * @package @jmruthers/pace-core\n * @module Hooks/Services\n * @since 0.1.0\n *\n * React hook for EventService.\n * Provides event service with reactive state updates.\n */\n\nimport { useContext, useReducer, useEffect } from 'react';\nimport { EventServiceContext } from '../../providers/services/EventServiceProvider';\nimport { EventService } from '../../services/EventService';\n\nexport function useEventService(): EventService {\n const context = useContext(EventServiceContext);\n \n if (!context) {\n throw new Error('useEventService must be used within EventServiceProvider');\n }\n \n // Subscribe to service state changes\n const [, forceUpdate] = useReducer(x => x + 1, 0);\n \n useEffect(() => {\n return context.eventService.subscribe(() => forceUpdate());\n }, [context.eventService]);\n \n return context.eventService;\n}","/**\n * @file Inactivity Service Hook\n * @package @jmruthers/pace-core\n * @module Hooks/Services\n * @since 0.1.0\n *\n * React hook for InactivityService.\n * Provides inactivity service with reactive state updates.\n */\n\nimport { useContext, useReducer, useEffect } from 'react';\nimport { InactivityServiceContext } from '../../providers/services/InactivityServiceProvider';\nimport { InactivityService } from '../../services/InactivityService';\n\nexport function useInactivityService(): InactivityService {\n const context = useContext(InactivityServiceContext);\n \n if (!context) {\n throw new Error('useInactivityService must be used within InactivityServiceProvider');\n }\n \n // Subscribe to service state changes\n const [, forceUpdate] = useReducer(x => x + 1, 0);\n \n useEffect(() => {\n return context.inactivityService.subscribe(() => forceUpdate());\n }, [context.inactivityService]);\n \n return context.inactivityService;\n}","/**\n * @file useSessionRestoration Hook\n * @package @jmruthers/pace-core\n * @module Hooks\n * @since 0.1.0\n *\n * Provides reactive session restoration state from the AuthService.\n * Handles timeout detection to prevent infinite loading loops when\n * Supabase session hydration from localStorage takes too long.\n */\n\nimport { useContext, useMemo, useEffect, useState } from 'react';\nimport { AuthServiceContext } from '../providers/services/AuthServiceProvider';\nimport type { SessionRestorationState } from '../types/auth';\n\nconst SESSION_RESTORATION_TIMEOUT_MS = 5000;\n\nexport interface UseSessionRestorationResult extends SessionRestorationState {\n /** Indicates whether the restoration process exceeded the timeout window */\n hasTimedOut: boolean;\n /** Timeout duration in milliseconds */\n timeoutMs: number;\n}\n\nexport function useSessionRestoration(): UseSessionRestorationResult {\n const context = useContext(AuthServiceContext);\n\n if (!context) {\n throw new Error('useSessionRestoration must be used within AuthServiceProvider');\n }\n\n const { sessionRestoration } = context;\n const [hasTimedOut, setHasTimedOut] = useState(false);\n\n useEffect(() => {\n let timeoutHandle: ReturnType<typeof setTimeout> | null = null;\n\n if (sessionRestoration.isRestoring && !sessionRestoration.restorationComplete && !sessionRestoration.restorationError) {\n setHasTimedOut(false);\n timeoutHandle = setTimeout(() => {\n console.warn('[useSessionRestoration] Session restoration timed out');\n setHasTimedOut(true);\n }, SESSION_RESTORATION_TIMEOUT_MS);\n } else {\n setHasTimedOut(false);\n }\n\n return () => {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n };\n }, [\n sessionRestoration.isRestoring,\n sessionRestoration.restorationComplete,\n sessionRestoration.restorationError\n ]);\n\n return useMemo(() => ({\n ...sessionRestoration,\n hasTimedOut,\n timeoutMs: SESSION_RESTORATION_TIMEOUT_MS,\n }), [sessionRestoration, hasTimedOut]);\n}\n","/**\n * @file Unified Auth Provider\n * @package @jmruthers/pace-core\n * @module Providers/Services\n * @since 0.1.0\n *\n * Unified authentication provider for authentication, organisations, events, and inactivity tracking.\n * Note: RBAC functionality is available via useRBAC() hook from '@jmruthers/pace-core/rbac'\n */\n\nimport React, { createContext, useContext, useMemo, useCallback, useRef } from 'react';\nimport { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';\nimport { AuthServiceProvider } from './AuthServiceProvider';\nimport { OrganisationServiceProvider } from './OrganisationServiceProvider';\nimport { EventServiceProvider } from './EventServiceProvider';\nimport { InactivityServiceProvider } from './InactivityServiceProvider';\nimport { useAuthService } from '../../hooks/services/useAuthService';\nimport { useOrganisationService } from '../../hooks/services/useOrganisationService';\nimport { useEventService } from '../../hooks/services/useEventService';\nimport { useInactivityService } from '../../hooks/services/useInactivityService';\nimport { useSessionRestoration } from '../../hooks/useSessionRestoration';\nimport type { Organisation, OrganisationMembership } from '../../types/organisation';\nimport type { Event } from '../../types/unified';\nimport type { AuthError } from '@supabase/supabase-js';\nimport type { SessionRestorationState } from '../../types/auth';\n\n// Re-export UserEventAccess type\nexport interface UserEventAccess {\n event_id: string;\n event_name: string;\n event_description?: string | null;\n start_date: string;\n end_date: string;\n event_status: string;\n app_id: string;\n access_level: string;\n granted_at: string;\n organisation_id: string;\n}\n\n// Combined context type - focuses on auth, organisations, events, and inactivity\nexport interface UnifiedAuthContextType {\n // Auth state\n user: User | null;\n session: Session | null;\n isAuthenticated: boolean;\n authLoading: boolean;\n authError: AuthError | null;\n error: AuthError | null; // Alias for authError for backward compatibility\n supabase: SupabaseClient | null;\n \n // Auth methods\n signIn: (email: string, password?: string) => Promise<{ error: AuthError | null }>;\n signUp: (email: string, password: string) => Promise<{ error: AuthError | null }>;\n signOut: () => Promise<{ error: AuthError | null }>;\n resetPassword: (email: string) => Promise<{ error: AuthError | null }>;\n updatePassword: (password: string) => Promise<{ error: AuthError | null }>;\n refreshSession: () => Promise<{ error: AuthError | null }>;\n\n // Organisation state\n selectedOrganisation: Organisation | null;\n organisations: Organisation[];\n userMemberships: OrganisationMembership[];\n organisationLoading: boolean;\n organisationError: Error | null;\n hasValidOrganisationContext: boolean;\n isContextReady: boolean;\n \n // Organisation methods\n switchOrganisation: (orgId: string) => Promise<void>;\n getUserRole: (orgId?: string) => string;\n validateOrganisationAccess: (orgId: string) => boolean;\n refreshOrganisations: () => Promise<void>;\n ensureOrganisationContext: () => Organisation;\n isOrganisationSecure: () => boolean;\n getPrimaryOrganisation: () => Organisation | null;\n\n // Event state\n events: Event[];\n selectedEvent: Event | null;\n eventLoading: boolean;\n eventError: Error | null;\n \n // Event methods\n setSelectedEvent: (event: Event | null) => void;\n refreshEvents: () => Promise<void>;\n\n // Inactivity state\n showInactivityWarning: boolean;\n inactivityTimeRemaining: number;\n isIdle: boolean;\n timeRemaining: number;\n showWarning: boolean;\n isTracking: boolean;\n \n // Inactivity methods\n resetActivity: () => void;\n startTracking: () => void;\n stopTracking: () => void;\n handleIdleLogout: () => Promise<void>;\n handleStaySignedIn: () => void;\n handleSignOutNow: () => Promise<void>;\n\n // Additional unified properties\n appName: string;\n appConfig: { requires_event: boolean } | null;\n isLoading: boolean;\n hasErrors: boolean;\n sessionRestoration: SessionRestorationState;\n sessionRestorationTimedOut: boolean;\n sessionRestorationTimeoutMs: number;\n}\n\nconst UnifiedAuthContext = createContext<UnifiedAuthContextType | undefined>(undefined);\n\nexport const useUnifiedAuth = () => {\n const context = useContext(UnifiedAuthContext);\n if (!context) {\n // Provide a helpful console error in addition to throwing for testability and DX\n console.error('useUnifiedAuth must be used within a UnifiedAuthProvider');\n throw new Error('useUnifiedAuth must be used within a UnifiedAuthProvider');\n }\n return context;\n};\n\nexport interface UnifiedAuthProviderProps {\n children: React.ReactNode;\n supabaseClient: SupabaseClient;\n appName: string;\n persistState?: boolean;\n enablePersistence?: boolean;\n requireOrganisationContext?: boolean;\n \n // App configuration\n appConfig?: { requires_event: boolean } | null;\n \n // Inactivity auto-logout configuration - MANDATORY for security\n idleTimeoutMs: number; // REQUIRED: Inactivity timeout in milliseconds\n warnBeforeMs: number; // REQUIRED: Warning time before logout in milliseconds\n onIdleLogout: (reason: 'inactivity') => void; // REQUIRED: App handles redirect/navigation\n renderInactivityWarning?: (args: {\n timeRemaining: number;\n onStaySignedIn: () => void;\n onSignOutNow: () => void;\n }) => React.ReactNode; // Optional custom warning UI\n dangerouslyDisableInactivity?: boolean; // Dev-only; must not disable in production\n}\n\n// Internal component that combines all contexts\nfunction UnifiedAuthContextProvider({ \n children, \n appName,\n appConfig = { requires_event: true }, // Default to requiring events\n ...props \n}: UnifiedAuthProviderProps) {\n const authService = useAuthService();\n const organisationService = useOrganisationService();\n const inactivityService = useInactivityService();\n const sessionRestorationState = useSessionRestoration();\n const {\n hasTimedOut: sessionRestorationTimedOut,\n timeoutMs: sessionRestorationTimeoutMs,\n isRestoring,\n restorationComplete,\n restorationError,\n } = sessionRestorationState;\n const sessionRestoration: SessionRestorationState = useMemo(() => ({\n isRestoring,\n restorationComplete,\n restorationError,\n }), [isRestoring, restorationComplete, restorationError]);\n\n // Try to get event service, but provide fallback if not available\n let eventService;\n try {\n eventService = useEventService();\n } catch (error) {\n // EventService not available - provide fallback implementation\n eventService = {\n getEvents: () => [],\n getSelectedEvent: () => null,\n isLoading: () => false,\n getError: () => null,\n setSelectedEvent: () => {},\n refreshEvents: async () => {}\n };\n }\n\n // Get current auth state - these will trigger re-renders when services change\n const currentUser = authService.getUser();\n const currentSession = authService.getSession();\n const isAuth = !!(currentUser && currentSession);\n\n // Get loading states - these will trigger re-renders when services change\n const authLoading = authService.isLoading();\n const orgLoading = organisationService.isLoading();\n const eventLoading = eventService.isLoading();\n const restorationLoading = sessionRestoration.isRestoring && !sessionRestorationTimedOut && !sessionRestoration.restorationError;\n const totalLoading = restorationLoading || authLoading || orgLoading || eventLoading;\n \n // Extract all primitive values from services to use in dependencies\n const authError = authService.getError();\n const supabase = authService.getSupabaseClient();\n const selectedOrganisation = organisationService.getSelectedOrganisation();\n const organisations = organisationService.getOrganisations();\n const userMemberships = organisationService.getUserMemberships();\n const organisationError = organisationService.getError();\n const hasValidOrganisationContext = organisationService.hasValidOrganisationContext();\n const isContextReady = organisationService.isContextReady();\n const events = eventService.getEvents();\n const selectedEvent = eventService.getSelectedEvent();\n const eventError = eventService.getError();\n const showInactivityWarning = inactivityService.getShowInactivityWarning();\n const inactivityTimeRemaining = inactivityService.getInactivityTimeRemaining();\n const isIdle = inactivityService.isIdle();\n const timeRemaining = inactivityService.getTimeRemaining();\n const showWarning = inactivityService.isWarningShown();\n const isTracking = inactivityService.isTracking();\n const hasErrors = !!(authError || organisationError || eventError || sessionRestoration.restorationError);\n\n // Create stable references for all methods using useCallback\n const signIn = useCallback((email: string, password?: string) => authService.signIn(email, password), [authService]);\n const signUp = useCallback((email: string, password: string) => authService.signUp(email, password), [authService]);\n const signOut = useCallback(() => authService.signOut(), [authService]);\n const resetPassword = useCallback((email: string) => authService.resetPassword(email), [authService]);\n const updatePassword = useCallback((password: string) => authService.updatePassword(password), [authService]);\n const refreshSession = useCallback(() => authService.refreshSession(), [authService]);\n \n const switchOrganisation = useCallback((orgId: string) => organisationService.switchOrganisation(orgId), [organisationService]);\n const getUserRole = useCallback((orgId?: string) => organisationService.getUserRole(orgId), [organisationService]);\n const validateOrganisationAccess = useCallback((orgId: string) => organisationService.validateOrganisationAccess(orgId), [organisationService]);\n const refreshOrganisations = useCallback(() => organisationService.refreshOrganisations(), [organisationService]);\n const ensureOrganisationContext = useCallback(() => organisationService.ensureOrganisationContext(), [organisationService]);\n const isOrganisationSecure = useCallback(() => organisationService.isOrganisationSecure(), [organisationService]);\n const getPrimaryOrganisation = useCallback(() => organisationService.getPrimaryOrganisation(), [organisationService]);\n \n const setSelectedEvent = useCallback((event: Event | null) => eventService.setSelectedEvent(event), [eventService]);\n const refreshEvents = useCallback(() => eventService.refreshEvents(), [eventService]);\n \n const resetActivity = useCallback(() => inactivityService.resetActivity(), [inactivityService]);\n const startTracking = useCallback(() => inactivityService.startTracking(), [inactivityService]);\n const stopTracking = useCallback(() => inactivityService.stopTracking(), [inactivityService]);\n const handleIdleLogout = useCallback(() => inactivityService.handleIdleLogout(), [inactivityService]);\n const handleStaySignedIn = useCallback(() => inactivityService.handleStaySignedIn(), [inactivityService]);\n const handleSignOutNow = useCallback(() => inactivityService.handleSignOutNow(), [inactivityService]);\n\n // Use ref to track previous state for conditional logging (dev only)\n const prevStateRef = useRef<{\n isAuthenticated: boolean;\n userEmail: string | undefined;\n totalLoading: boolean;\n } | null>(null);\n \n // Only log when state actually changes (dev mode detection)\n const isDev = import.meta.env.DEV || import.meta.env.MODE === 'development';\n if (isDev) {\n const currentState = {\n isAuthenticated: isAuth,\n userEmail: currentUser?.email,\n totalLoading,\n };\n \n const prevState = prevStateRef.current;\n if (!prevState || \n prevState.isAuthenticated !== currentState.isAuthenticated ||\n prevState.userEmail !== currentState.userEmail ||\n prevState.totalLoading !== currentState.totalLoading) {\n console.log('[UnifiedAuthContext] Auth state changed:', {\n isAuthenticated: isAuth,\n user: currentUser?.email,\n session: currentSession ? 'exists' : 'null',\n totalLoading,\n authLoading,\n orgLoading,\n eventLoading,\n orgContextReady: isContextReady,\n sessionRestoration,\n sessionRestorationTimedOut,\n });\n prevStateRef.current = currentState;\n }\n }\n \n // Memoized combined context value - only depends on primitive values\n const contextValue = useMemo<UnifiedAuthContextType>(() => {\n return {\n // Auth state\n user: currentUser,\n session: currentSession,\n isAuthenticated: isAuth,\n authLoading: authLoading,\n authError: authError,\n error: authError, // Alias for backward compatibility\n supabase: supabase,\n \n // Auth methods\n signIn,\n signUp,\n signOut,\n resetPassword,\n updatePassword,\n refreshSession,\n\n // Organisation state\n selectedOrganisation: selectedOrganisation,\n organisations: organisations,\n userMemberships: userMemberships,\n organisationLoading: orgLoading,\n organisationError: organisationError,\n hasValidOrganisationContext: hasValidOrganisationContext,\n isContextReady: isContextReady,\n \n // Organisation methods\n switchOrganisation,\n getUserRole,\n validateOrganisationAccess,\n refreshOrganisations,\n ensureOrganisationContext,\n isOrganisationSecure,\n getPrimaryOrganisation,\n\n // Event state\n events: events,\n selectedEvent: selectedEvent,\n eventLoading: eventLoading,\n eventError: eventError,\n \n // Event methods\n setSelectedEvent,\n refreshEvents,\n\n // Inactivity state\n showInactivityWarning: showInactivityWarning,\n inactivityTimeRemaining: inactivityTimeRemaining,\n isIdle: isIdle,\n timeRemaining: timeRemaining,\n showWarning: showWarning,\n isTracking: isTracking,\n \n // Inactivity methods\n resetActivity,\n startTracking,\n stopTracking,\n handleIdleLogout,\n handleStaySignedIn,\n handleSignOutNow,\n\n // Additional unified properties\n appName,\n appConfig: appConfig,\n isLoading: totalLoading,\n hasErrors: hasErrors,\n sessionRestoration: sessionRestoration,\n sessionRestorationTimedOut,\n sessionRestorationTimeoutMs,\n };\n }, [\n // All primitive values extracted from services\n // Note: Arrays/objects from services are stable references (same reference unless data changes)\n currentUser,\n currentSession,\n isAuth,\n authLoading,\n authError,\n supabase,\n selectedOrganisation,\n organisations,\n userMemberships,\n orgLoading,\n organisationError,\n hasValidOrganisationContext,\n isContextReady,\n events,\n selectedEvent,\n eventLoading,\n eventError,\n showInactivityWarning,\n inactivityTimeRemaining,\n isIdle,\n timeRemaining,\n showWarning,\n isTracking,\n totalLoading,\n hasErrors,\n appName,\n appConfig,\n sessionRestoration,\n sessionRestorationTimedOut,\n sessionRestorationTimeoutMs,\n // Stable function references from useCallback (services are stable, so callbacks are too)\n signIn,\n signUp,\n signOut,\n resetPassword,\n updatePassword,\n refreshSession,\n switchOrganisation,\n getUserRole,\n validateOrganisationAccess,\n refreshOrganisations,\n ensureOrganisationContext,\n isOrganisationSecure,\n getPrimaryOrganisation,\n setSelectedEvent,\n refreshEvents,\n resetActivity,\n startTracking,\n stopTracking,\n handleIdleLogout,\n handleStaySignedIn,\n handleSignOutNow,\n ]);\n\n return (\n <UnifiedAuthContext.Provider value={contextValue}>\n {children}\n </UnifiedAuthContext.Provider>\n );\n}\n\n// Wrapper for EventServiceProvider that reads selectedOrganisation from OrganisationService\nfunction EventServiceProviderWrapper({ \n children, \n supabaseClient,\n user,\n session,\n appName\n}: {\n children: React.ReactNode;\n supabaseClient: SupabaseClient;\n user: User | null;\n session: Session | null;\n appName: string;\n}) {\n const organisationService = useOrganisationService();\n const selectedOrganisation = organisationService.getSelectedOrganisation();\n\n // Always render EventServiceProvider - it handles null user/session gracefully\n // This ensures EventServiceContext is always available for components calling useEvents()\n return (\n <EventServiceProvider\n supabaseClient={supabaseClient}\n user={user}\n session={session}\n appName={appName}\n selectedOrganisation={selectedOrganisation}\n setSelectedEventId={() => {\n // Event selection is now handled at the application level\n }}\n >\n {children}\n </EventServiceProvider>\n );\n}\n\n// Internal component that provides user/session to child providers\nfunction ServiceAwareProviders({ \n children, \n supabaseClient,\n appName,\n appConfig,\n persistState,\n enablePersistence,\n requireOrganisationContext,\n idleTimeoutMs,\n warnBeforeMs,\n onIdleLogout,\n renderInactivityWarning,\n dangerouslyDisableInactivity\n}: UnifiedAuthProviderProps) {\n const authService = useAuthService();\n\n return (\n <OrganisationServiceProvider\n supabaseClient={supabaseClient}\n user={authService.getUser()}\n session={authService.getSession()}\n >\n <EventServiceProviderWrapper\n supabaseClient={supabaseClient}\n user={authService.getUser()}\n session={authService.getSession()}\n appName={appName}\n >\n <InactivityServiceProvider\n supabaseClient={supabaseClient}\n user={authService.getUser()}\n session={authService.getSession()}\n idleTimeoutMs={idleTimeoutMs}\n warnBeforeMs={warnBeforeMs}\n onIdleLogout={onIdleLogout}\n >\n <UnifiedAuthContextProvider\n appName={appName}\n appConfig={appConfig}\n supabaseClient={supabaseClient}\n persistState={persistState}\n enablePersistence={enablePersistence}\n requireOrganisationContext={requireOrganisationContext}\n idleTimeoutMs={idleTimeoutMs}\n warnBeforeMs={warnBeforeMs}\n onIdleLogout={onIdleLogout}\n renderInactivityWarning={renderInactivityWarning}\n dangerouslyDisableInactivity={dangerouslyDisableInactivity}\n >\n {children}\n </UnifiedAuthContextProvider>\n </InactivityServiceProvider>\n </EventServiceProviderWrapper>\n </OrganisationServiceProvider>\n );\n}\n\nexport function UnifiedAuthProvider({\n children,\n supabaseClient,\n appName,\n appConfig = { requires_event: true }, // Default to requiring events\n persistState = true,\n enablePersistence,\n requireOrganisationContext = true,\n idleTimeoutMs = 30 * 60 * 1000, // 30 minutes\n warnBeforeMs = 60 * 1000, // 60 seconds\n onIdleLogout,\n renderInactivityWarning,\n dangerouslyDisableInactivity = false\n}: UnifiedAuthProviderProps) {\n return (\n <AuthServiceProvider supabaseClient={supabaseClient}>\n <ServiceAwareProviders\n supabaseClient={supabaseClient}\n appName={appName}\n appConfig={appConfig}\n persistState={persistState}\n enablePersistence={enablePersistence}\n requireOrganisationContext={requireOrganisationContext}\n idleTimeoutMs={idleTimeoutMs}\n warnBeforeMs={warnBeforeMs}\n onIdleLogout={onIdleLogout}\n renderInactivityWarning={renderInactivityWarning}\n dangerouslyDisableInactivity={dangerouslyDisableInactivity}\n >\n {children}\n </ServiceAwareProviders>\n </AuthServiceProvider>\n );\n}\n"],"mappings":"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","names":["createContext","useContext","useMemo","useEffect","jsx","createContext","useContext","useMemo","useEffect","useRef","jsx","createContext","useContext","useMemo","useEffect","useRef","jsx","useContext","useEffect","useAuthService","useContext","useReducer","useEffect","useOrganisationService","useContext","useReducer","useEffect","useEventService","useContext","useReducer","useEffect","useInactivityService","useContext","useMemo","useEffect","useState","createContext","useContext","useMemo","useRef","jsx","useAuthService","useOrganisationService","useInactivityService","useEventService"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/providers/OrganisationProvider.tsx","../src/components/PublicLayout/PublicErrorBoundary.tsx","../src/components/PublicLayout/PublicPageProvider.tsx","../src/hooks/useAppConfig.ts","../src/utils/storage/config.ts","../src/utils/storage/helpers.ts","../src/hooks/public/usePublicEventLogo.ts"],"sourcesContent":["/**\n * @file Re-export for OrganisationProvider\n * @package @jmruthers/pace-core\n * @module Providers\n * @since 0.1.0\n * \n * Re-exports the service-based OrganisationProvider for backward compatibility.\n */\n\nexport { OrganisationServiceProvider as OrganisationProvider } from './services/OrganisationServiceProvider';\nexport type { OrganisationServiceProviderProps as OrganisationProviderProps } from './services/OrganisationServiceProvider';\n\n// Re-export context and hook\nexport { OrganisationServiceContext, useOrganisationService } from './services/OrganisationServiceProvider';\nexport type { OrganisationServiceContextType } from './services/OrganisationServiceProvider';\n\n// Re-export convenience hook for backward compatibility\nexport { useOrganisations } from '../hooks/useOrganisations';\n\n","/**\n * @file Public Error Boundary Component\n * @package @jmruthers/pace-core\n * @module Components/PublicLayout\n * @since 1.0.0\n *\n * An error boundary component specifically designed for public pages.\n * Provides graceful error handling and recovery for public content.\n *\n * Features:\n * - Graceful error handling\n * - User-friendly error messages\n * - Recovery mechanisms\n * - Accessibility compliant\n * - TypeScript support\n *\n * @example\n * ```tsx\n * import { PublicErrorBoundary } from '@jmruthers/pace-core';\n *\n * function PublicEventPage() {\n * return (\n * <PublicErrorBoundary>\n * <PublicPageContent />\n * </PublicErrorBoundary>\n * );\n * }\n * ```\n *\n * @accessibility\n * - WCAG 2.1 AA compliant\n * - Screen reader friendly error messages\n * - Keyboard accessible recovery actions\n * - High contrast support\n *\n * @dependencies\n * - React 18+ - Component framework\n * - Error boundary patterns\n * - Tailwind CSS - Styling\n */\n\nimport React, { Component, ErrorInfo, ReactNode } from 'react';\n\nexport interface PublicErrorBoundaryProps {\n /** Child components to wrap */\n children: ReactNode;\n /** Custom error fallback component */\n fallback?: React.ComponentType<PublicErrorBoundaryState>;\n /** Custom CSS classes for error display */\n className?: string;\n /** Whether to show error details in development */\n showErrorDetails?: boolean;\n /** Custom error message */\n customErrorMessage?: string;\n /** Custom recovery action */\n onRecover?: () => void;\n}\n\nexport interface PublicErrorBoundaryState {\n /** Whether an error has occurred */\n hasError: boolean;\n /** The error that occurred */\n error: Error | null;\n /** Error information */\n errorInfo: ErrorInfo | null;\n /** Function to reset the error state */\n resetError: () => void;\n}\n\n/**\n * Error boundary component for public pages\n * \n * This component catches JavaScript errors anywhere in the child component tree,\n * logs those errors, and displays a fallback UI instead of the component tree that crashed.\n * \n * @param props - Error boundary configuration\n * @returns React element with error boundary wrapper\n */\nexport class PublicErrorBoundary extends Component<PublicErrorBoundaryProps, PublicErrorBoundaryState> {\n constructor(props: PublicErrorBoundaryProps) {\n super(props);\n this.state = {\n hasError: false,\n error: null,\n errorInfo: null,\n resetError: this.resetError.bind(this)\n };\n }\n\n static getDerivedStateFromError(error: Error): Partial<PublicErrorBoundaryState> {\n // Update state so the next render will show the fallback UI\n return {\n hasError: true,\n error\n };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n // Log the error to console in development\n if (import.meta.env.MODE === 'development') {\n console.error('PublicErrorBoundary caught an error:', error, errorInfo);\n }\n\n // Update state with error info\n this.setState({\n error,\n errorInfo\n });\n\n // You can also log the error to an error reporting service here\n // Example: logErrorToService(error, errorInfo);\n }\n\n resetError = () => {\n this.setState({\n hasError: false,\n error: null,\n errorInfo: null\n });\n };\n\n render() {\n if (this.state.hasError) {\n // Custom fallback component\n if (this.props.fallback) {\n return <this.props.fallback {...this.state} />;\n }\n\n // Default error UI\n return (\n <div className={`min-h-screen bg-white flex items-center justify-center ${this.props.className || ''}`}>\n <div className=\"max-w-md mx-auto text-center px-4\">\n <div className=\"mb-6\">\n <div className=\"mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-red-100 mb-4\">\n <svg\n className=\"h-6 w-6 text-red-600\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-bold text-gray-900 mb-2\">\n Something went wrong\n </h1>\n <p className=\"text-gray-600 mb-6\">\n {this.props.customErrorMessage || \n 'We encountered an error while loading this page. Please try again.'}\n </p>\n </div>\n\n {/* Error details in development */}\n {this.props.showErrorDetails && this.state.error && (\n <div className=\"mb-6 p-4 bg-red-50 border border-red-200 rounded-md text-left\">\n <h3 className=\"text-sm font-medium text-red-800 mb-2\">\n Error Details (Development Only)\n </h3>\n <pre className=\"text-xs text-red-700 whitespace-pre-wrap\">\n {this.state.error.toString()}\n {this.state.errorInfo?.componentStack}\n </pre>\n </div>\n )}\n\n {/* Recovery actions */}\n <div className=\"space-y-3\">\n <button\n onClick={this.resetError}\n className=\"w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\n >\n Try Again\n </button>\n \n <button\n onClick={() => window.location.reload()}\n className=\"w-full px-4 py-2 bg-gray-600 text-white rounded-md hover:bg-gray-700 transition-colors focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2\"\n >\n Reload Page\n </button>\n\n {this.props.onRecover && (\n <button\n onClick={this.props.onRecover}\n className=\"w-full px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2\"\n >\n Alternative Action\n </button>\n )}\n </div>\n\n {/* Help text */}\n <div className=\"mt-6 text-sm text-gray-500\">\n <p>\n If this problem persists, please contact support or try accessing the page later.\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n\n/**\n * Hook for accessing error boundary state\n * Useful for components that need to know if they're inside an error boundary\n */\nexport function useErrorBoundary() {\n const [error, setError] = React.useState<Error | null>(null);\n\n const resetError = React.useCallback(() => {\n setError(null);\n }, []);\n\n const captureError = React.useCallback((error: Error) => {\n setError(error);\n }, []);\n\n // Throw error synchronously during render so error boundary can catch it\n if (error) {\n throw error;\n }\n\n return { captureError, resetError };\n}\n\n/**\n * Default error fallback component\n */\nexport function DefaultPublicErrorFallback({ \n error, \n resetError \n}: PublicErrorBoundaryState) {\n return (\n <div className=\"min-h-screen bg-white flex items-center justify-center\">\n <div className=\"max-w-md mx-auto text-center px-4\">\n <div className=\"mb-6\">\n <div className=\"mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-red-100 mb-4\">\n <svg\n className=\"h-6 w-6 text-red-600\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z\"\n />\n </svg>\n </div>\n <h1 className=\"text-2xl font-bold text-gray-900 mb-2\">\n Page Error\n </h1>\n <p className=\"text-gray-600 mb-6\">\n We encountered an error while loading this page.\n </p>\n </div>\n\n <button\n onClick={resetError}\n className=\"w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2\"\n >\n Try Again\n </button>\n </div>\n </div>\n );\n}\n","/**\n * @file Public Page Provider\n * @package @jmruthers/pace-core\n * @module Components/PublicLayout\n * @since 1.0.0\n *\n * A completely isolated provider for public pages that doesn't trigger\n * any authentication context. This ensures public pages work independently\n * of the main application's authentication system.\n *\n * Features:\n * - No authentication required\n * - No organisation context\n * - No event context\n * - Completely isolated from main app context\n * - Environment variable access for public data\n * - Error boundary integration\n *\n * @example\n * ```tsx\n * import { PublicPageProvider } from '@jmruthers/pace-core';\n * \n * function PublicApp() {\n * return (\n * <PublicPageProvider>\n * <Routes>\n * <Route path=\"/events/:eventCode/recipe-grid-report\" element={<PublicRecipePage />} />\n * </Routes>\n * </PublicPageProvider>\n * );\n * }\n * ```\n */\n\nimport React, { createContext, useContext, ReactNode, useMemo } from 'react';\nimport { createClient } from '@supabase/supabase-js';\nimport type { Database } from '../../types/database';\nimport { PublicErrorBoundary } from './PublicErrorBoundary';\n\ninterface PublicPageContextType {\n isPublicPage: true;\n supabase: ReturnType<typeof createClient<Database>> | null;\n environment: {\n supabaseUrl: string | null;\n supabaseKey: string | null;\n };\n}\n\nexport const PublicPageContext = createContext<PublicPageContextType | undefined>(undefined);\n\nexport interface PublicPageProviderProps {\n children: ReactNode;\n}\n\n/**\n * Provider for public pages that completely isolates them from authentication context\n * \n * This provider:\n * - Does not initialize any authentication providers\n * - Provides environment variables for public data access\n * - Includes error boundary for graceful error handling\n * - Is completely separate from the main app context\n */\nexport function PublicPageProvider({ children }: PublicPageProviderProps) {\n // Get environment variables for public data access\n // Handle both Vite (import.meta.env) and Node.js (process.env) environments\n const getEnvVar = (key: string): string | undefined => {\n // Check Vite environment first (browser)\n if (typeof import.meta !== 'undefined' && (import.meta as any).env) {\n return (import.meta as any).env[key];\n }\n // Check Node.js environment (server-side)\n if (typeof import.meta !== 'undefined' && import.meta.env) {\n return import.meta.env[key];\n }\n return undefined;\n };\n\n const supabaseUrl = getEnvVar('VITE_SUPABASE_URL') || \n getEnvVar('NEXT_PUBLIC_SUPABASE_URL') || \n null;\n \n const supabaseKey = getEnvVar('VITE_SUPABASE_ANON_KEY') || \n getEnvVar('NEXT_PUBLIC_SUPABASE_ANON_KEY') || \n null;\n\n // Create Supabase client if environment variables are available\n const supabase = useMemo(() => {\n if (!supabaseUrl || !supabaseKey) {\n console.warn('[PublicPageProvider] Missing Supabase environment variables. Please ensure VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY are set in your environment.');\n return null;\n }\n return createClient<Database>(supabaseUrl, supabaseKey);\n }, [supabaseUrl, supabaseKey]);\n\n const contextValue: PublicPageContextType = {\n isPublicPage: true,\n supabase,\n environment: {\n supabaseUrl,\n supabaseKey\n }\n };\n\n return (\n <PublicPageContext.Provider value={contextValue}>\n <PublicErrorBoundary>\n {children}\n </PublicErrorBoundary>\n </PublicPageContext.Provider>\n );\n}\n\n/**\n * Hook to access public page context\n * \n * @returns Public page context with environment variables\n */\nexport function usePublicPageContext(): PublicPageContextType {\n const context = useContext(PublicPageContext);\n \n if (!context) {\n throw new Error('usePublicPageContext must be used within a PublicPageProvider');\n }\n \n return context;\n}\n\n/**\n * Hook to check if we're in a public page context\n * \n * @returns True if we're in a public page context\n */\nexport function useIsPublicPage(): boolean {\n const context = useContext(PublicPageContext);\n return context !== undefined;\n}\n","/**\n * @file useAppConfig Hook\n * @package @jmruthers/pace-core\n * @module Hooks/useAppConfig\n * @since 0.4.0\n *\n * Hook for accessing app configuration like direct access support and event requirements.\n * This is a convenience hook that extracts app config from the UnifiedAuthProvider.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { supportsDirectAccess, requiresEvent, isLoading } = useAppConfig();\n * \n * if (isLoading) return <div>Loading...</div>;\n * \n * return (\n * <div>\n * {supportsDirectAccess && (\n * <div>This app supports direct access!</div>\n * )}\n * {requiresEvent && (\n * <EventSelector />\n * )}\n * </div>\n * );\n * }\n * ```\n */\n\nimport { useMemo } from 'react';\nimport { useUnifiedAuth } from '../providers/UnifiedAuthProvider';\nimport { useIsPublicPage } from '../components/PublicLayout/PublicPageProvider';\n\nexport interface UseAppConfigReturn {\n supportsDirectAccess: boolean;\n requiresEvent: boolean;\n isLoading: boolean;\n appName: string;\n}\n\n/**\n * Hook to access app configuration\n * Works in both authenticated and public contexts\n * @returns App configuration and loading state\n */\nexport function useAppConfig(): UseAppConfigReturn {\n // Check if we're in a public page context first\n const isPublicPage = useIsPublicPage();\n \n if (isPublicPage) {\n // For public pages, try to get app name from environment variables\n const getAppName = (): string => {\n // Check Vite environment first (browser)\n if (typeof import.meta !== 'undefined' && (import.meta as any).env) {\n return (import.meta as any).env.VITE_APP_NAME || \n (import.meta as any).env.NEXT_PUBLIC_APP_NAME || \n 'PACE';\n }\n // Check Node.js environment (server-side)\n if (typeof import.meta !== 'undefined' && import.meta.env) {\n return import.meta.env.VITE_APP_NAME || \n import.meta.env.NEXT_PUBLIC_APP_NAME || \n 'PACE';\n }\n return 'PACE';\n };\n \n return useMemo(() => ({\n supportsDirectAccess: false, // Public pages don't support direct access\n requiresEvent: true, // Public pages always require an event\n isLoading: false,\n appName: getAppName()\n }), []);\n }\n \n // For authenticated pages, use UnifiedAuthProvider\n try {\n const { appConfig, appName } = useUnifiedAuth();\n return useMemo(() => ({\n supportsDirectAccess: !(appConfig?.requires_event ?? true),\n requiresEvent: appConfig?.requires_event ?? true,\n isLoading: appConfig === null,\n appName\n }), [appConfig?.requires_event, appName]);\n } catch (error) {\n // Fallback if UnifiedAuthProvider is not available\n return useMemo(() => ({\n supportsDirectAccess: false,\n requiresEvent: true,\n isLoading: false,\n appName: 'PACE'\n }), []);\n }\n} ","/**\n * Storage configuration for pace-core\n */\n\nimport { FileSizeLimits, StorageConfig } from './types';\n\n/**\n * File size limits by MIME type (in bytes)\n */\nexport const FILE_SIZE_LIMITS: FileSizeLimits = {\n // Images\n 'image/jpeg': 5 * 1024 * 1024, // 5MB\n 'image/png': 5 * 1024 * 1024, // 5MB\n 'image/gif': 10 * 1024 * 1024, // 10MB (for animations)\n 'image/webp': 5 * 1024 * 1024, // 5MB\n 'image/svg+xml': 1 * 1024 * 1024, // 1MB (vector graphics)\n \n // Documents\n 'application/pdf': 50 * 1024 * 1024, // 50MB\n 'application/msword': 25 * 1024 * 1024, // 25MB\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 25 * 1024 * 1024, // 25MB\n 'application/vnd.ms-excel': 25 * 1024 * 1024, // 25MB\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 25 * 1024 * 1024, // 25MB\n \n // Archives\n 'application/zip': 100 * 1024 * 1024, // 100MB\n 'application/x-rar-compressed': 100 * 1024 * 1024, // 100MB\n \n // Text files\n 'text/plain': 1 * 1024 * 1024, // 1MB\n 'text/csv': 10 * 1024 * 1024, // 10MB\n 'application/json': 10 * 1024 * 1024, // 10MB\n};\n\n/**\n * Default file size limit for unknown MIME types\n */\nexport const DEFAULT_FILE_SIZE_LIMIT = 10 * 1024 * 1024; // 10MB\n\n/**\n * App-specific path mappings for file organization\n * Maps app names to their primary category in the organization-first structure\n */\nexport const APP_PATH_MAPPING: Record<string, string> = {\n 'PACE': 'event_logos',\n 'TRAC': 'trac_accommodation', // Default category for TRAC files\n 'MEDI': 'documents',\n 'CAKE': 'documents'\n};\n\n/**\n * Storage configuration\n */\nexport const STORAGE_CONFIG: StorageConfig = {\n bucketName: 'files',\n fileSizeLimits: FILE_SIZE_LIMITS,\n defaultFileSizeLimit: DEFAULT_FILE_SIZE_LIMIT,\n};\n\n/**\n * Get the file size limit for a given MIME type\n */\nexport function getFileSizeLimit(mimeType: string): number {\n return STORAGE_CONFIG.fileSizeLimits[mimeType] || STORAGE_CONFIG.defaultFileSizeLimit;\n}\n\n/**\n * Get the bucket name based on whether the file is public or private\n * @param isPublic - Whether the file should be publicly accessible\n * @returns The bucket name: 'public-files' for public files, 'files' for private files\n */\nexport function getBucketName(isPublic: boolean): 'files' | 'public-files' {\n return isPublic ? 'public-files' : 'files';\n}\n\n/**\n * Validate file size against limits\n */\nexport function validateFileSize(file: File): { isValid: boolean; error?: string } {\n const limit = getFileSizeLimit(file.type);\n \n if (file.size > limit) {\n const limitMB = Math.round(limit / (1024 * 1024));\n const fileMB = Math.round(file.size / (1024 * 1024));\n return {\n isValid: false,\n error: `File size (${fileMB}MB) exceeds limit (${limitMB}MB) for ${file.type}`\n };\n }\n \n return { isValid: true };\n}\n\n/**\n * Get human-readable file size\n */\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 Bytes';\n if (bytes < 0) return `${bytes} Bytes`; // Handle negative numbers\n \n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n \n // Ensure we don't exceed the available size units\n const sizeIndex = Math.min(Math.max(i, 0), sizes.length - 1);\n \n return parseFloat((bytes / Math.pow(k, sizeIndex)).toFixed(2)) + ' ' + sizes[sizeIndex];\n}\n","/**\n * Storage helper functions for pace-core\n */\n\nimport { SupabaseClient } from '@supabase/supabase-js';\nimport { \n StorageUploadOptions, \n StorageUploadResult, \n StorageFileMetadata,\n StorageUrlOptions,\n StorageListOptions,\n StorageListResult,\n StorageFileInfo\n} from './types';\nimport { validateFileSize, STORAGE_CONFIG, getBucketName } from './config';\n\n/**\n * Generate a file path based on organization-first structure\n */\nexport function generateFilePath(options: StorageUploadOptions, fileName: string): string {\n const { orgId, isPublic = false, customPath } = options;\n \n \n // Validate required orgId\n if (!orgId) {\n throw new Error('orgId is required for file path generation');\n }\n \n if (isPublic) {\n // Public files go to {orgId}/{category}/filename\n if (customPath) {\n return `${orgId}/${customPath}/${fileName}`;\n }\n return `${orgId}/public/${fileName}`;\n }\n \n // Organization-first structure: {orgId}/{category}/filename\n if (customPath) {\n return `${orgId}/${customPath}/${fileName}`;\n }\n \n // Use customPath if available, otherwise default to files\n const pathCategory = customPath || 'files';\n return `${orgId}/${pathCategory}/${fileName}`;\n}\n\n/**\n * Generate a unique filename with timestamp and UUID\n */\nexport function generateUniqueFileName(originalName: string): string {\n const timestamp = Date.now();\n const uuid = crypto.randomUUID();\n const extension = originalName.split('.').pop() || '';\n const baseName = originalName.replace(/\\.[^/.]+$/, '');\n \n // If there's no extension, don't add one\n if (!extension || extension === originalName) {\n return `${timestamp}-${uuid}-${baseName}`;\n }\n \n return `${timestamp}-${uuid}-${baseName}.${extension}`;\n}\n\n/**\n * Extract file metadata from a File object\n */\nexport async function extractFileMetadata(\n file: File, \n options: StorageUploadOptions,\n uploadedBy: string\n): Promise<StorageFileMetadata> {\n const metadata: StorageFileMetadata = {\n mimeType: file.type,\n size: file.size,\n orgId: options.orgId,\n appName: options.appName || 'pace-core',\n uploadedBy,\n uploadedAt: new Date().toISOString(),\n tags: options.tags || [],\n isPublic: options.isPublic || false,\n customMetadata: options.metadata || {}\n };\n\n // Extract image dimensions if it's an image\n if (file.type.startsWith('image/')) {\n try {\n const dimensions = await getImageDimensions(file);\n metadata.width = dimensions.width;\n metadata.height = dimensions.height;\n } catch (error) {\n console.warn('Could not extract image dimensions:', error);\n }\n }\n\n // Generate file hash if possible\n try {\n metadata.hash = await generateFileHash(file);\n } catch (error) {\n console.warn('Could not generate file hash:', error);\n }\n\n return metadata;\n}\n\n/**\n * Get image dimensions from a File object\n */\nasync function getImageDimensions(file: File): Promise<{ width: number; height: number }> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n const url = URL.createObjectURL(file);\n \n img.onload = () => {\n URL.revokeObjectURL(url);\n resolve({ width: img.width, height: img.height });\n };\n \n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error('Could not load image'));\n };\n \n img.src = url;\n });\n}\n\n/**\n * Generate a hash for a file\n */\nasync function generateFileHash(file: File): Promise<string> {\n const buffer = await file.arrayBuffer();\n const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n return `sha256:${hashHex}`;\n}\n\n/**\n * Upload a file to Supabase storage with app segregation\n */\nexport async function uploadFile(\n supabase: SupabaseClient,\n file: File,\n options: StorageUploadOptions\n): Promise<StorageUploadResult> {\n try {\n // Validate file size\n const sizeValidation = validateFileSize(file);\n if (!sizeValidation.isValid) {\n return {\n success: false,\n error: sizeValidation.error\n };\n }\n\n // Generate unique filename and path\n const uniqueFileName = generateUniqueFileName(file.name);\n const filePath = generateFilePath(options, uniqueFileName);\n\n // Extract metadata\n const metadata = await extractFileMetadata(file, options, 'current-user'); // TODO: Get actual user ID\n\n // Select bucket based on isPublic flag\n const bucketName = getBucketName(options.isPublic || false);\n\n // Upload file to Supabase\n const { data, error } = await supabase.storage\n .from(bucketName)\n .upload(filePath, file, {\n cacheControl: '3600',\n upsert: false,\n contentType: file.type\n });\n\n if (error) {\n return {\n success: false,\n error: `Upload failed: ${error.message}`\n };\n }\n\n // Generate public URL if file is public\n let publicUrl: string | undefined;\n if (options.isPublic) {\n const { data: urlData } = supabase.storage\n .from(bucketName)\n .getPublicUrl(filePath);\n publicUrl = urlData.publicUrl;\n }\n\n return {\n success: true,\n path: filePath,\n publicUrl,\n metadata\n };\n\n } catch (error) {\n return {\n success: false,\n error: `Upload failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n };\n }\n}\n\n/**\n * Get a public URL for a file\n * @param supabase - Supabase client instance\n * @param path - File path within the bucket\n * @param isPublic - Whether the file is in the public-files bucket (default: true)\n * @returns Public URL for the file\n */\nexport function getPublicUrl(\n supabase: SupabaseClient,\n path: string,\n isPublic: boolean = true\n): string {\n if (!supabase) {\n throw new Error('Supabase client is required to generate a public URL');\n }\n\n if (!path || typeof path !== 'string') {\n throw new Error('A valid storage path is required to generate a public URL');\n }\n\n // If the path is already an absolute URL, return it directly\n if (/^https?:\\/\\//i.test(path)) {\n return path;\n }\n\n // Normalise path by trimming whitespace and leading slashes\n let normalisedPath = path.trim().replace(/^\\/+/, '');\n\n if (!normalisedPath) {\n throw new Error('Storage path cannot be empty after normalisation');\n }\n\n const { bucketNameFromPath, storagePath } = resolveBucketHint(normalisedPath);\n\n const bucketName = bucketNameFromPath || getBucketName(isPublic);\n\n const { data } = supabase.storage\n .from(bucketName)\n .getPublicUrl(storagePath);\n\n return data.publicUrl;\n}\n\nfunction resolveBucketHint(pathWithPotentialBucket: string): { bucketNameFromPath: string | null; storagePath: string } {\n const BUCKET_NAME_PATTERN = /^[a-z0-9][a-z0-9-_\\.]{1,62}$/i;\n const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n const KNOWN_BUCKET_NAMES = new Set(['files', 'public-files']);\n\n const trimmedPath = pathWithPotentialBucket.trim();\n\n if (!trimmedPath) {\n throw new Error('Storage path cannot be empty after normalisation');\n }\n\n // Support \"bucket::path\" notation to remove ambiguity with colon usage in file names.\n const doubleColonIndex = trimmedPath.indexOf('::');\n if (doubleColonIndex > 0) {\n const potentialBucket = trimmedPath.slice(0, doubleColonIndex).trim();\n const remainingPath = trimmedPath.slice(doubleColonIndex + 2).replace(/^\\/+/, '');\n\n if (potentialBucket && remainingPath && BUCKET_NAME_PATTERN.test(potentialBucket)) {\n return {\n bucketNameFromPath: potentialBucket,\n storagePath: remainingPath\n };\n }\n }\n\n // Support \"bucket/path\" hints, provided the first segment looks like a bucket name and not a directory prefix.\n const firstSlashIndex = trimmedPath.indexOf('/');\n if (firstSlashIndex > 0) {\n const potentialBucket = trimmedPath.slice(0, firstSlashIndex).trim();\n const remainingPath = trimmedPath.slice(firstSlashIndex + 1).replace(/^\\/+/, '');\n\n if (\n potentialBucket &&\n remainingPath &&\n BUCKET_NAME_PATTERN.test(potentialBucket) &&\n !UUID_PATTERN.test(potentialBucket) &&\n (KNOWN_BUCKET_NAMES.has(potentialBucket) || !potentialBucket.includes('-')) &&\n !/^\\d+$/.test(potentialBucket)\n ) {\n return {\n bucketNameFromPath: potentialBucket,\n storagePath: remainingPath\n };\n }\n }\n\n return {\n bucketNameFromPath: null,\n storagePath: trimmedPath\n };\n}\n\n/**\n * Get a signed URL for a protected file\n * Private files are always in the 'files' bucket, so this always uses 'files' bucket\n * @param supabase - Supabase client instance\n * @param path - File path within the bucket\n * @param options - URL options including expiry time\n * @returns Signed URL with expiration timestamp, or null if failed\n */\nexport async function getSignedUrl(\n supabase: SupabaseClient,\n path: string,\n options: StorageUrlOptions\n): Promise<{ url: string; expiresAt: string } | null> {\n try {\n // Signed URLs are only for private files, which are always in the 'files' bucket\n const bucketName = getBucketName(false);\n \n const { data, error } = await supabase.storage\n .from(bucketName)\n .createSignedUrl(path, options.expiresIn || 3600);\n\n if (error) {\n console.error('Failed to create signed URL:', error);\n return null;\n }\n\n return {\n url: data.signedUrl,\n expiresAt: new Date(Date.now() + (options.expiresIn || 3600) * 1000).toISOString()\n };\n } catch (error) {\n console.error('Failed to create signed URL:', error);\n return null;\n }\n}\n\n/**\n * Delete a file from storage\n * @param supabase - Supabase client instance\n * @param path - File path within the bucket\n * @param isPublic - Whether the file is in the public-files bucket (default: false)\n * @returns Success status and optional error message\n */\nexport async function deleteFile(\n supabase: SupabaseClient,\n path: string,\n isPublic: boolean = false\n): Promise<{ success: boolean; error?: string }> {\n try {\n const bucketName = getBucketName(isPublic);\n \n const { error } = await supabase.storage\n .from(bucketName)\n .remove([path]);\n\n if (error) {\n return {\n success: false,\n error: `Delete failed: ${error.message}`\n };\n }\n\n return { success: true };\n } catch (error) {\n return {\n success: false,\n error: `Delete failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n };\n }\n}\n\n/**\n * List files in an organization scope\n * @param supabase - Supabase client instance\n * @param options - List options including bucket selection via isPublic\n * @returns List of files with metadata\n */\nexport async function listFiles(\n supabase: SupabaseClient,\n options: StorageListOptions & { isPublic?: boolean }\n): Promise<StorageListResult> {\n try {\n // Select bucket based on isPublic flag (default to private files bucket)\n const bucketName = getBucketName(options.isPublic || false);\n \n // Organization-first structure: {orgId}/{category}/\n const pathPrefix = `${options.orgId}/`;\n const searchPath = options.pathPrefix ? `${pathPrefix}${options.pathPrefix}` : pathPrefix;\n\n const { data, error } = await supabase.storage\n .from(bucketName)\n .list(searchPath, {\n limit: options.limit || 100,\n offset: options.offset || 0,\n sortBy: { column: 'created_at', order: 'desc' }\n });\n\n if (error) {\n console.error('Failed to list files:', error);\n return { files: [], totalCount: 0, hasMore: false };\n }\n\n const files: StorageFileInfo[] = (data || []).map(item => ({\n name: item.name,\n path: `${searchPath}${item.name}`,\n size: item.metadata?.size || 0,\n mimeType: item.metadata?.mimetype || 'application/octet-stream',\n lastModified: item.updated_at || item.created_at || new Date().toISOString(),\n metadata: {\n mimeType: item.metadata?.mimetype || 'application/octet-stream',\n size: item.metadata?.size || 0,\n orgId: options.orgId,\n appName: options.appName,\n uploadedBy: 'unknown',\n uploadedAt: item.created_at || new Date().toISOString(),\n isPublic: options.isPublic || false\n }\n }));\n\n return {\n files,\n totalCount: files.length,\n hasMore: files.length >= (options.limit || 100)\n };\n } catch (error) {\n console.error('Failed to list files:', error);\n return { files: [], totalCount: 0, hasMore: false };\n }\n}\n\n/**\n * Download a file from storage\n * @param supabase - Supabase client instance\n * @param path - File path within the bucket\n * @param isPublic - Whether the file is in the public-files bucket (default: false)\n * @returns File blob with metadata, or null if failed\n */\nexport async function downloadFile(\n supabase: SupabaseClient,\n path: string,\n isPublic: boolean = false\n): Promise<{ blob: Blob; metadata: { name: string; size: number; type: string } } | null> {\n try {\n const bucketName = getBucketName(isPublic);\n \n const { data, error } = await supabase.storage\n .from(bucketName)\n .download(path);\n\n if (error) {\n console.error('Failed to download file:', error);\n return null;\n }\n\n if (!data) {\n return null;\n }\n\n // Extract file name from path\n const fileName = path.split('/').pop() || 'download';\n \n // Get file metadata\n const { data: fileInfo } = await supabase.storage\n .from(bucketName)\n .list(path.split('/').slice(0, -1).join('/'), {\n search: fileName\n });\n\n const metadata = fileInfo?.[0]?.metadata || {};\n \n return {\n blob: data,\n metadata: {\n name: fileName,\n size: metadata.size || data.size,\n type: metadata.mimetype || 'application/octet-stream'\n }\n };\n } catch (error) {\n console.error('Failed to download file:', error);\n return null;\n }\n}\n\n/**\n * Move a file to archived location (soft delete)\n * @param supabase - Supabase client instance\n * @param path - File path within the bucket\n * @param options - Archive options including bucket selection via isPublic\n */\nexport async function archiveFile(\n supabase: SupabaseClient,\n path: string,\n options: { appName: string; orgId: string; isPublic?: boolean }\n): Promise<{ success: boolean; error?: string }> {\n try {\n const bucketName = getBucketName(options.isPublic || false);\n \n // Generate archived path for organization-first structure\n const archivedPath = path.replace(`${options.orgId}/`, `archived/${options.orgId}/`);\n \n // Copy file to archived location\n const { error: copyError } = await supabase.storage\n .from(bucketName)\n .copy(path, archivedPath);\n\n if (copyError) {\n return {\n success: false,\n error: `Archive failed: ${copyError.message}`\n };\n }\n\n // Delete original file\n const deleteResult = await deleteFile(supabase, path, options.isPublic || false);\n if (!deleteResult.success) {\n return deleteResult;\n }\n\n return { success: true };\n } catch (error) {\n return {\n success: false,\n error: `Archive failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n };\n }\n}\n","/**\n * @file Public Event Logo Hook\n * @package @jmruthers/pace-core\n * @module Hooks/Public\n * @since 1.0.0\n *\n * A React hook for accessing public event logo URLs without authentication.\n * Provides logo URLs with fallback handling for public pages.\n *\n * Features:\n * - No authentication required\n * - Automatic fallback to event initials\n * - Caching for performance\n * - Error handling and loading states\n * - TypeScript support\n * - Image validation\n *\n * @example\n * ```tsx\n * import { usePublicEventLogo } from '@jmruthers/pace-core';\n *\n * function EventHeader() {\n * const { logoUrl, fallbackText, isLoading, error } = usePublicEventLogo(\n * eventId, \n * eventName, \n * organisationId\n * );\n *\n * if (isLoading) return <div>Loading logo...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n *\n * return (\n * <div>\n * {logoUrl ? (\n * <img src={logoUrl} alt={`${eventName} logo`} />\n * ) : (\n * <div className=\"logo-fallback\">{fallbackText}</div>\n * )}\n * </div>\n * );\n * }\n * ```\n *\n * @accessibility\n * - No direct accessibility concerns (hook)\n * - Enables accessible logo display with proper alt text\n * - Supports screen reader friendly fallbacks\n *\n * @security\n * - Only returns public-safe logo URLs\n * - Validates image existence before returning URL\n * - No sensitive information exposed\n * - Rate limiting applied at storage level\n *\n * @performance\n * - Built-in caching with TTL\n * - Image validation and optimization\n * - Minimal re-renders with stable references\n * - Lazy loading support\n *\n * @dependencies\n * - React 18+ - Hooks and effects\n * - @supabase/supabase-js - Storage integration\n * - Event types - Type definitions\n */\n\nimport { useState, useEffect, useCallback, useMemo } from 'react';\nimport type { SupabaseClient } from '@supabase/supabase-js';\nimport type { Database } from '../../types/database';\nimport { getPublicUrl } from '../../utils/storage/helpers';\nimport { FileCategory } from '../../types/file-reference';\n\n// Simple in-memory cache for public data\nconst publicDataCache = new Map<string, { data: any; timestamp: number; ttl: number }>();\n\nexport interface UsePublicEventLogoReturn {\n /** The logo URL if available, null if not found or error */\n logoUrl: string | null;\n /** Fallback text (event initials) if no logo is available */\n fallbackText: string;\n /** Whether the logo is currently loading */\n isLoading: boolean;\n /** Any error that occurred during loading */\n error: Error | null;\n /** Function to manually refetch the logo */\n refetch: () => Promise<void>;\n}\n\nexport interface UsePublicEventLogoOptions {\n /** Cache TTL in milliseconds (default: 30 minutes) */\n cacheTtl?: number;\n /** Whether to enable caching (default: true) */\n enableCache?: boolean;\n /** Whether to validate image existence (default: true) */\n validateImage?: boolean;\n /** Custom fallback text generator */\n generateFallbackText?: (eventName: string) => string;\n /** Supabase client instance (required) */\n supabase: SupabaseClient<Database>;\n}\n\n/**\n * Generate fallback text from event name (first letter of each word)\n */\nfunction defaultGenerateFallbackText(eventName: string): string {\n if (!eventName) return 'EV';\n \n return eventName\n .split(' ')\n .map(word => word.charAt(0).toUpperCase())\n .join('')\n .substring(0, 3); // Max 3 characters\n}\n\n/**\n * Hook for accessing public event logo URLs\n * \n * This hook provides access to event logo URLs without requiring\n * authentication. It includes fallback handling and image validation.\n * \n * @param eventId - The event ID to fetch logo for\n * @param eventName - The event name for fallback text generation\n * @param organisationId - The organisation ID for storage path\n * @param options - Configuration options for caching and behavior\n * @returns Object containing logo URL, fallback text, loading state, error, and refetch function\n */\nexport function usePublicEventLogo(\n eventId: string | undefined,\n eventName: string | undefined,\n organisationId: string | undefined,\n options: UsePublicEventLogoOptions\n): UsePublicEventLogoReturn {\n const {\n cacheTtl = 30 * 60 * 1000, // 30 minutes\n enableCache = true,\n validateImage = true,\n generateFallbackText = defaultGenerateFallbackText,\n supabase\n } = options;\n\n const [logoUrl, setLogoUrl] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Generate fallback text\n const fallbackText = useMemo(() => {\n return eventName ? generateFallbackText(eventName) : 'EV';\n }, [eventName, generateFallbackText]);\n\n const fetchLogo = useCallback(async (): Promise<void> => {\n if (!eventId || !organisationId || !supabase) {\n setLogoUrl(null);\n setIsLoading(false);\n return;\n }\n\n // Validate UUID format for organisationId to prevent database errors\n const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n if (!uuidRegex.test(organisationId)) {\n console.warn('[usePublicEventLogo] Invalid organisationId format (not a valid UUID):', organisationId);\n // Don't return early - let the database handle the validation\n // This allows for more graceful error handling\n }\n\n // Check cache first\n const cacheKey = `public_logo_${eventId}_${organisationId}`;\n if (enableCache) {\n const cached = publicDataCache.get(cacheKey);\n if (cached && Date.now() - cached.timestamp < cached.ttl) {\n setLogoUrl(cached.data);\n setIsLoading(false);\n setError(null);\n return;\n }\n }\n\n try {\n setIsLoading(true);\n setError(null);\n\n // Get event logo from file_references using new RPC function\n const { data, error: rpcError } = await (supabase as any)\n .rpc('data_file_reference_by_category_list', {\n p_table_name: 'event',\n p_record_id: eventId,\n p_category: FileCategory.EVENT_LOGOS,\n p_organisation_id: organisationId\n });\n\n if (rpcError) {\n throw new Error(rpcError.message || 'Failed to fetch logo');\n }\n\n if (!data || data.length === 0 || !data[0]?.file_path) {\n setLogoUrl(null);\n return;\n }\n\n // Get the file path from the RPC response\n const logoPath = data[0].file_path;\n const isPublic = data[0].is_public ?? true; // Event logos should be public\n\n // Generate public URL using bucket-aware helper (public-files bucket for public files)\n const logoUrl = getPublicUrl(supabase, logoPath, isPublic);\n\n // Validate image existence if requested\n if (validateImage) {\n try {\n const response = await fetch(logoUrl, { method: 'HEAD' });\n if (!response.ok) {\n console.warn('[usePublicEventLogo] Logo URL not accessible:', logoUrl);\n setLogoUrl(null);\n return;\n }\n } catch (fetchError) {\n console.warn('[usePublicEventLogo] Error validating logo URL:', fetchError);\n setLogoUrl(null);\n return;\n }\n }\n\n setLogoUrl(logoUrl);\n\n // Cache the result\n if (enableCache) {\n publicDataCache.set(cacheKey, {\n data: logoUrl,\n timestamp: Date.now(),\n ttl: cacheTtl\n });\n }\n\n } catch (err) {\n console.error('[usePublicEventLogo] Error fetching logo:', err);\n const error = err instanceof Error ? err : new Error('Unknown error occurred');\n setError(error);\n setLogoUrl(null);\n } finally {\n setIsLoading(false);\n }\n }, [eventId, organisationId, supabase, cacheTtl, enableCache, validateImage]);\n\n // Fetch logo when parameters change\n useEffect(() => {\n if (eventId && organisationId) {\n fetchLogo();\n } else {\n setLogoUrl(null);\n setIsLoading(false);\n setError(null);\n }\n }, [fetchLogo, eventId, organisationId]);\n\n const refetch = useCallback(async (): Promise<void> => {\n if (!eventId || !organisationId) return;\n \n // Clear cache for this logo\n if (enableCache) {\n const cacheKey = `public_logo_${eventId}_${organisationId}`;\n publicDataCache.delete(cacheKey);\n }\n await fetchLogo();\n }, [fetchLogo, eventId, organisationId, enableCache]);\n\n return {\n logoUrl,\n fallbackText,\n isLoading,\n error,\n refetch\n };\n}\n\n/**\n * Clear all cached public logo data\n * Useful for testing or when you need to force refresh all data\n */\nexport function clearPublicLogoCache(): void {\n for (const [key] of publicDataCache) {\n if (key.startsWith('public_logo_')) {\n publicDataCache.delete(key);\n }\n }\n}\n\n/**\n * Get cache statistics for debugging\n */\nexport function getPublicLogoCacheStats(): { size: number; keys: string[] } {\n const keys = Array.from(publicDataCache.keys()).filter(key => key.startsWith('public_logo_'));\n return {\n size: keys.length,\n keys\n };\n}\n"],"mappings":"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","names":["error","jsx","useMemo","useMemo","useMemo","useMemo","logoUrl","error"]}
|