@jmruthers/pace-core 0.5.184 → 0.5.186
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/CHANGELOG.md +38 -0
- package/README.md +60 -1
- package/core-usage-manifest.json +312 -0
- package/dist/{DataTable-QAB34V6K.js → DataTable-IX2NBUTP.js} +6 -6
- package/dist/{DataTable-Bz8ffqyA.d.ts → DataTable-Z9NLVJh0.d.ts} +1 -1
- package/dist/{index-Bl--n7-T.d.ts → PublicPageProvider-DIzEzwKl.d.ts} +23 -10
- package/dist/{UnifiedAuthProvider-7F6T4B6K.js → UnifiedAuthProvider-A4BCQRJY.js} +4 -2
- package/dist/{UnifiedAuthProvider-F86d7dSi.d.ts → UnifiedAuthProvider-BG0AL5eE.d.ts} +2 -1
- package/dist/{api-ROMBCNKU.js → api-BMFCXVQX.js} +2 -2
- package/dist/{chunk-RA3JUFMW.js → chunk-445GEP27.js} +154 -4
- package/dist/{chunk-RA3JUFMW.js.map → chunk-445GEP27.js.map} +1 -1
- package/dist/{chunk-W22JP75J.js → chunk-DAGICKHT.js} +9 -7
- package/dist/chunk-DAGICKHT.js.map +1 -0
- package/dist/{chunk-FUEYYMX5.js → chunk-FXFJRTKI.js} +24 -3
- package/dist/chunk-FXFJRTKI.js.map +1 -0
- package/dist/{chunk-CSOFYHAG.js → chunk-GRIQLQ52.js} +374 -60
- package/dist/chunk-GRIQLQ52.js.map +1 -0
- package/dist/{chunk-NQPMQGS2.js → chunk-HDCUMOOI.js} +497 -399
- package/dist/chunk-HDCUMOOI.js.map +1 -0
- package/dist/chunk-HESYZWZW.js +388 -0
- package/dist/chunk-HESYZWZW.js.map +1 -0
- package/dist/{chunk-QUVSNGIP.js → chunk-HGPQUCBC.js} +34 -9
- package/dist/{chunk-QUVSNGIP.js.map → chunk-HGPQUCBC.js.map} +1 -1
- package/dist/{chunk-PWAHJW4G.js → chunk-OALXJH4Y.js} +86 -33
- package/dist/chunk-OALXJH4Y.js.map +1 -0
- package/dist/{chunk-MI7HBHN3.js → chunk-TC7D3CR3.js} +89 -9
- package/dist/chunk-TC7D3CR3.js.map +1 -0
- package/dist/chunk-THRPYOFK.js +215 -0
- package/dist/chunk-THRPYOFK.js.map +1 -0
- package/dist/{chunk-M7W4CP3M.js → chunk-U6WNSFX5.js} +2 -1
- package/dist/chunk-U6WNSFX5.js.map +1 -0
- package/dist/{chunk-UHNYIBXL.js → chunk-UQWSHFVX.js} +1 -1
- package/dist/chunk-UQWSHFVX.js.map +1 -0
- package/dist/{chunk-QCDXODCA.js → chunk-XAUHJD3L.js} +2 -2
- package/dist/components.d.ts +182 -6
- package/dist/components.js +157 -11
- package/dist/components.js.map +1 -1
- package/dist/{database.generated-CBmg2950.d.ts → database.generated-DI89OQeI.d.ts} +63 -9
- package/dist/eslint-rules/pace-core-compliance.cjs +406 -0
- package/dist/{file-reference-D06mEEWW.d.ts → file-reference-PRTSLxKx.d.ts} +10 -1
- package/dist/hooks.d.ts +52 -15
- package/dist/hooks.js +12 -22
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +12 -12
- package/dist/index.js +82 -18
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +3 -1
- package/dist/rbac/index.d.ts +206 -15
- package/dist/rbac/index.js +28 -6
- package/dist/timezone-_pgH8qrY.d.ts +530 -0
- package/dist/{types-_x1f4QBF.d.ts → types-DUyCRSTj.d.ts} +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.js +1 -1
- package/dist/{usePublicRouteParams-JJczomYq.d.ts → usePublicRouteParams-D71QLlg4.d.ts} +114 -3
- package/dist/utils.d.ts +110 -152
- package/dist/utils.js +128 -138
- package/dist/utils.js.map +1 -1
- package/docs/api/README.md +60 -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/Logger.md +178 -0
- 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/RBACAuditManager.md +2 -2
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +2 -2
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +5 -5
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +54 -0
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CalendarProps.md +18 -2
- 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/ComplianceResult.md +30 -0
- 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/DatabaseComplianceResult.md +85 -0
- package/docs/api/interfaces/DatabaseIssue.md +41 -0
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventAppRoleData.md +6 -6
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- 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 +48 -8
- package/docs/api/interfaces/FileUploadProps.md +46 -13
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/FormFieldProps.md +1 -1
- package/docs/api/interfaces/FormProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +9 -9
- 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/LoggerConfig.md +62 -0
- 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 +36 -23
- 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 +11 -11
- 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/ProgressProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/QuickFix.md +52 -0
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +4 -4
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +7 -7
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +5 -5
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/RuntimeComplianceResult.md +55 -0
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
- package/docs/api/interfaces/SetupIssue.md +41 -0
- 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/TabsContentProps.md +1 -1
- package/docs/api/interfaces/TabsListProps.md +1 -1
- package/docs/api/interfaces/TabsProps.md +1 -1
- package/docs/api/interfaces/TabsTriggerProps.md +1 -1
- package/docs/api/interfaces/TextareaProps.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/UseFormDialogOptions.md +62 -0
- package/docs/api/interfaces/UseFormDialogReturn.md +117 -0
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +2 -2
- 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 +2 -2
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.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 +746 -50
- package/docs/api-reference/components.md +26 -12
- package/docs/api-reference/hooks.md +111 -0
- package/docs/api-reference/rpc-functions.md +1 -1
- package/docs/api-reference/utilities.md +184 -0
- package/docs/getting-started/installation-guide.md +75 -16
- package/docs/getting-started/quick-start.md +61 -11
- package/docs/implementation-guides/authentication.md +88 -12
- package/docs/implementation-guides/file-reference-system.md +26 -3
- package/docs/implementation-guides/file-upload-storage.md +30 -1
- package/docs/rbac/README.md +1 -0
- package/docs/rbac/compliance/compliance-guide.md +544 -0
- package/docs/rbac/getting-started.md +158 -33
- package/docs/standards/pace-core-compliance.md +432 -0
- package/eslint-config-pace-core.cjs +93 -0
- package/package.json +15 -3
- package/scripts/analyze-bundle.js +232 -0
- package/scripts/build-css.js +56 -0
- package/scripts/build-docs-incremental.js +1015 -0
- package/scripts/check-pace-core-compliance.cjs +2353 -0
- package/scripts/check-pace-core-compliance.js +512 -0
- package/scripts/generate-docs.js +157 -0
- package/scripts/setup-build-cache.js +73 -0
- package/scripts/utils/command-runner.js +131 -0
- package/scripts/utils/env.js +33 -0
- package/scripts/utils/index.js +10 -0
- package/scripts/utils/logger.js +88 -0
- package/scripts/utils/path-helpers.js +37 -0
- package/scripts/validate-formats.js +133 -0
- package/scripts/validate-master.js +155 -0
- package/scripts/validate-pre-publish.js +140 -0
- package/scripts/validate-theme.js +142 -0
- package/src/components/Calendar/Calendar.tsx +8 -1
- package/src/components/Card/Card.tsx +47 -8
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +314 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +126 -0
- package/src/components/DatePickerWithTimezone/README.md +135 -0
- package/src/components/DatePickerWithTimezone/index.ts +10 -0
- package/src/components/DateTimeField/DateTimeField.test.tsx +358 -0
- package/src/components/DateTimeField/DateTimeField.tsx +232 -0
- package/src/components/DateTimeField/README.md +148 -0
- package/src/components/DateTimeField/index.ts +10 -0
- package/src/components/FileUpload/FileUpload.test.tsx +2 -0
- package/src/components/FileUpload/FileUpload.tsx +10 -1
- package/src/components/Header/Header.test.tsx +47 -18
- package/src/components/Header/Header.tsx +22 -7
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +29 -20
- package/src/components/PaceAppLayout/README.md +9 -0
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +37 -8
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +146 -5
- package/src/components/index.ts +8 -0
- package/src/eslint-rules/pace-core-compliance.cjs +406 -0
- package/src/eslint-rules/pace-core-compliance.js +640 -0
- package/src/hooks/__tests__/useFormDialog.test.ts +478 -0
- package/src/hooks/index.ts +5 -0
- package/src/hooks/useFileReference.test.ts +2 -0
- package/src/hooks/useFormDialog.ts +147 -0
- package/src/hooks/usePreventTabReload.ts +106 -0
- package/src/hooks/useSecureDataAccess.ts +2 -2
- package/src/index.ts +27 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +6 -5
- package/src/providers/services/UnifiedAuthProvider.tsx +24 -3
- package/src/rbac/__tests__/rbac-role-isolation.test.ts +456 -0
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +3 -0
- package/src/rbac/compliance/database-validator.ts +165 -0
- package/src/rbac/compliance/index.ts +38 -0
- package/src/rbac/compliance/quick-fix-suggestions.ts +209 -0
- package/src/rbac/compliance/runtime-compliance.ts +77 -0
- package/src/rbac/compliance/setup-validator.ts +131 -0
- package/src/rbac/components/PagePermissionGuard.tsx +8 -64
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +35 -21
- package/src/rbac/docs/event-based-apps.md +285 -0
- package/src/rbac/errors.ts +11 -0
- package/src/rbac/hooks/useRoleManagement.ts +292 -12
- package/src/rbac/index.ts +30 -0
- package/src/services/OrganisationService.ts +4 -0
- package/src/styles/core.css +5 -5
- package/src/types/database.generated.ts +63 -9
- package/src/types/file-reference.ts +9 -0
- package/src/utils/__tests__/timezone.test.ts +345 -0
- package/src/utils/file-reference/__tests__/file-reference.test.ts +60 -4
- package/src/utils/file-reference/index.ts +13 -2
- package/src/utils/formatting/formatDateTimeTimezone.test.ts +167 -0
- package/src/utils/formatting/formatting.ts +179 -0
- package/src/utils/index.ts +27 -1
- package/src/utils/location/index.ts +16 -0
- package/src/utils/location/location.test.ts +286 -0
- package/src/utils/location/location.ts +175 -0
- package/src/utils/security/secureDataAccess.ts +1 -1
- package/src/utils/storage/helpers.ts +68 -0
- package/src/utils/timezone/index.ts +17 -0
- package/src/utils/timezone/timezone.test.ts +349 -0
- package/src/utils/timezone/timezone.ts +281 -0
- package/dist/chunk-CSOFYHAG.js.map +0 -1
- package/dist/chunk-FUEYYMX5.js.map +0 -1
- package/dist/chunk-HKIT6O7W.js +0 -198
- package/dist/chunk-HKIT6O7W.js.map +0 -1
- package/dist/chunk-KUEN3HFB.js +0 -94
- package/dist/chunk-KUEN3HFB.js.map +0 -1
- package/dist/chunk-M7W4CP3M.js.map +0 -1
- package/dist/chunk-MI7HBHN3.js.map +0 -1
- package/dist/chunk-NQPMQGS2.js.map +0 -1
- package/dist/chunk-PWAHJW4G.js.map +0 -1
- package/dist/chunk-UHNYIBXL.js.map +0 -1
- package/dist/chunk-W22JP75J.js.map +0 -1
- package/dist/formatting-5wETwiGF.d.ts +0 -162
- /package/dist/{DataTable-QAB34V6K.js.map → DataTable-IX2NBUTP.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-7F6T4B6K.js.map → UnifiedAuthProvider-A4BCQRJY.js.map} +0 -0
- /package/dist/{api-ROMBCNKU.js.map → api-BMFCXVQX.js.map} +0 -0
- /package/dist/{chunk-QCDXODCA.js.map → chunk-XAUHJD3L.js.map} +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useOrganisations
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XAUHJD3L.js";
|
|
4
4
|
import {
|
|
5
5
|
EventServiceContext,
|
|
6
6
|
useUnifiedAuth
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-FXFJRTKI.js";
|
|
8
8
|
import {
|
|
9
9
|
setOrganisationContext
|
|
10
10
|
} from "./chunk-VBXEHIUJ.js";
|
|
@@ -70,8 +70,9 @@ function useSecureDataAccess() {
|
|
|
70
70
|
"medi_profile_versions",
|
|
71
71
|
"pace_consent",
|
|
72
72
|
"pace_contact",
|
|
73
|
-
"
|
|
74
|
-
"
|
|
73
|
+
"pace_identification",
|
|
74
|
+
"pace_identification_type",
|
|
75
|
+
"pace_qualification",
|
|
75
76
|
"form_responses",
|
|
76
77
|
"form_response_values",
|
|
77
78
|
"forms",
|
|
@@ -207,8 +208,9 @@ function useSecureDataAccess() {
|
|
|
207
208
|
"medi_profile_versions",
|
|
208
209
|
"pace_consent",
|
|
209
210
|
"pace_contact",
|
|
210
|
-
"
|
|
211
|
-
"
|
|
211
|
+
"pace_identification",
|
|
212
|
+
"pace_identification_type",
|
|
213
|
+
"pace_qualification",
|
|
212
214
|
"form_responses",
|
|
213
215
|
"form_response_values",
|
|
214
216
|
"forms",
|
|
@@ -386,4 +388,4 @@ function useSecureDataAccess() {
|
|
|
386
388
|
export {
|
|
387
389
|
useSecureDataAccess
|
|
388
390
|
};
|
|
389
|
-
//# sourceMappingURL=chunk-
|
|
391
|
+
//# sourceMappingURL=chunk-DAGICKHT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/useSecureDataAccess.ts"],"sourcesContent":["/**\n * @file useSecureDataAccess Hook\n * @package @jmruthers/pace-core\n * @module Hooks/useSecureDataAccess\n * @since 0.4.0\n *\n * Hook for secure database operations with mandatory organisation context.\n * Ensures all data access is properly scoped to the user's current organisation.\n *\n * @example\n * ```tsx\n * function DataComponent() {\n * const { secureQuery, secureInsert, secureUpdate, secureDelete } = useSecureDataAccess();\n * \n * const loadData = async () => {\n * try {\n * // Automatically includes organisation_id filter\n * const events = await secureQuery('event', '*', { is_visible: true });\n * console.log('Organisation events:', events);\n * } catch (error) {\n * console.error('Failed to load data:', error);\n * }\n * };\n * \n * const createEvent = async (eventData) => {\n * try {\n * // Automatically sets organisation_id\n * const newEvent = await secureInsert('event', eventData);\n * console.log('Created event:', newEvent);\n * } catch (error) {\n * console.error('Failed to create event:', error);\n * }\n * };\n * \n * return (\n * <div>\n * <button onClick={loadData}>Load Data</button>\n * <button onClick={() => createEvent({ event_name: 'New Event' })}>\n * Create Event\n * </button>\n * </div>\n * );\n * }\n * ```\n *\n * @security\n * - All queries automatically include organisation_id filter\n * - Validates organisation context before any operation\n * - Prevents data leaks between organisations\n * - Error handling for security violations\n * - Type-safe database operations\n */\n\nimport { useCallback, useState, useContext } from 'react';\nimport { useUnifiedAuth } from '../providers';\nimport { useOrganisations } from './useOrganisations';\nimport { EventServiceContext } from '../providers/services/EventServiceProvider';\nimport { setOrganisationContext } from '../utils/context/organisationContext';\nimport { logger } from '../utils/core/logger';\nimport type { Permission } from '../rbac/types';\nimport type { OrganisationSecurityError } from '../types/organisation';\n\nexport interface SecureDataAccessReturn {\n /** Execute a secure query with organisation filtering */\n secureQuery: <T = any>(\n table: string,\n columns: string,\n filters?: Record<string, any>,\n options?: {\n orderBy?: string;\n ascending?: boolean;\n limit?: number;\n offset?: number;\n }\n ) => Promise<T[]>;\n \n /** Execute a secure insert with organisation context */\n secureInsert: <T = any>(\n table: string,\n data: Record<string, any>\n ) => Promise<T>;\n \n /** Execute a secure update with organisation filtering */\n secureUpdate: <T = any>(\n table: string,\n data: Record<string, any>,\n filters: Record<string, any>\n ) => Promise<T[]>;\n \n /** Execute a secure delete with organisation filtering */\n secureDelete: (\n table: string,\n filters: Record<string, any>\n ) => Promise<void>;\n \n /** Execute a secure RPC call with organisation context */\n secureRpc: <T = any>(\n functionName: string,\n params?: Record<string, any>\n ) => Promise<T>;\n \n /** Get current organisation ID */\n getCurrentOrganisationId: () => string;\n \n /** Validate organisation context */\n validateContext: () => void;\n \n // NEW: Phase 1 - Enhanced Security Features\n /** Check if data access is allowed for a table and operation */\n isDataAccessAllowed: (table: string, operation: string) => boolean;\n \n /** Get all data access permissions for current user */\n getDataAccessPermissions: () => Record<string, string[]>;\n \n /** Check if strict mode is enabled */\n isStrictMode: boolean;\n \n /** Check if audit logging is enabled */\n isAuditLogEnabled: boolean;\n \n /** Get data access history */\n getDataAccessHistory: () => DataAccessRecord[];\n \n /** Clear data access history */\n clearDataAccessHistory: () => void;\n \n /** Validate data access attempt */\n validateDataAccess: (table: string, operation: string) => boolean;\n}\n\nexport interface DataAccessRecord {\n table: string;\n operation: string;\n userId: string;\n organisationId: string;\n allowed: boolean;\n timestamp: string;\n query?: string;\n filters?: Record<string, any>;\n}\n\n/**\n * Hook for secure data access with automatic organisation filtering\n * \n * All database operations automatically include organisation context:\n * - Queries filter by organisation_id\n * - Inserts include organisation_id\n * - Updates/deletes are scoped to organisation\n * - RPC calls include organisation_id parameter\n */\nexport function useSecureDataAccess(): SecureDataAccessReturn {\n const { supabase, user, session } = useUnifiedAuth();\n const { ensureOrganisationContext } = useOrganisations();\n \n // Get selected event for event-scoped RPC calls\n // Use useContext directly to safely check if EventServiceProvider is available\n const eventServiceContext = useContext(EventServiceContext);\n const selectedEvent = eventServiceContext?.eventService?.getSelectedEvent() || null;\n\n const validateContext = useCallback((): void => {\n if (!supabase) {\n throw new Error('No Supabase client available') as OrganisationSecurityError;\n }\n if (!user || !session) {\n throw new Error('User must be authenticated with valid session') as OrganisationSecurityError;\n }\n \n try {\n ensureOrganisationContext();\n } catch (error) {\n throw new Error('Organisation context is required for data access') as OrganisationSecurityError;\n }\n }, [supabase, user, session, ensureOrganisationContext]);\n\n const getCurrentOrganisationId = useCallback((): string => {\n validateContext();\n const currentOrg = ensureOrganisationContext();\n return currentOrg.id;\n }, [validateContext, ensureOrganisationContext]);\n\n // Set organisation context in database session\n const setOrganisationContextInSession = useCallback(async (organisationId: string): Promise<void> => {\n if (!supabase) {\n throw new Error('No Supabase client available') as OrganisationSecurityError;\n }\n\n await setOrganisationContext(supabase, organisationId);\n }, [supabase]);\n\n const secureQuery = useCallback(async <T = any>(\n table: string,\n columns: string,\n filters: Record<string, any> = {},\n options: {\n orderBy?: string;\n ascending?: boolean;\n limit?: number;\n offset?: number;\n } = {}\n ): Promise<T[]> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Build query with organisation filter\n let query = supabase!\n .from(table)\n .select(columns);\n\n // Add organisation filter only if table has organisation_id column\n const tablesWithOrganisation = [\n 'event', 'organisation_settings',\n 'rbac_event_app_roles', 'rbac_organisation_roles',\n // SECURITY: Phase 2 additions - complete organisation table mapping\n 'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',\n // SECURITY: Emergency additions for Phase 1 fixes\n 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member',\n // SECURITY: Phase 3A additions - medical and personal data\n 'medi_profile', 'medi_condition', 'medi_diet', 'medi_action_plan', 'medi_profile_versions',\n 'pace_consent', 'pace_contact', 'pace_identification', 'pace_identification_type', 'pace_qualification',\n 'form_responses', 'form_response_values', 'forms',\n // SECURITY: Phase 3B additions - remaining critical tables\n 'invoice', 'line_item', 'credit_balance', 'payment_method',\n 'form_contexts', 'form_field_config', 'form_fields',\n 'cake_delivery', 'cake_diettype', 'cake_diner', 'cake_dish', 'cake_item', \n 'cake_logistics', 'cake_mealplan', 'cake_package', 'cake_recipe', 'cake_supplier', \n 'cake_supply', 'cake_unit', 'event_app_access', 'base_application', 'base_questions'\n ];\n \n if (tablesWithOrganisation.includes(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n\n // Apply additional filters\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n // Handle qualified column names (e.g., 'users.role')\n const columnName = key.includes('.') ? key.split('.').pop()! : key;\n query = query.eq(columnName, value);\n }\n });\n\n // Apply options\n if (options.orderBy) {\n // Only use the column name, not a qualified name\n const orderByColumn = options.orderBy.split('.').pop();\n if (orderByColumn) {\n query = query.order(orderByColumn, { ascending: options.ascending ?? true });\n }\n }\n \n if (options.limit) {\n query = query.limit(options.limit);\n }\n \n if (options.offset) {\n query = query.range(options.offset, options.offset + (options.limit || 100) - 1);\n }\n\n const { data, error } = await query;\n \n if (error) {\n logger.error('useSecureDataAccess', 'Query failed', { table, columns, filters, error });\n // NEW: Phase 1 - Record failed data access attempt\n recordDataAccess(table, 'read', false, `SELECT ${columns} FROM ${table}`, filters);\n throw error;\n }\n\n // NEW: Phase 1 - Record successful data access attempt\n recordDataAccess(table, 'read', true, `SELECT ${columns} FROM ${table}`, filters);\n\n return (data as T[]) || [];\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase]);\n\n const secureInsert = useCallback(async <T = any>(\n table: string,\n data: Record<string, any>\n ): Promise<T> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Ensure organisation_id is set\n const secureData = {\n ...data,\n organisation_id: organisationId\n };\n\n const { data: insertData, error } = await supabase!\n .from(table)\n .insert(secureData)\n .select()\n .single();\n\n if (error) {\n logger.error('useSecureDataAccess', 'Insert failed', { table, data: secureData, error });\n throw error;\n }\n\n return insertData as T;\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase]);\n\n const secureUpdate = useCallback(async <T = any>(\n table: string,\n data: Record<string, any>,\n filters: Record<string, any>\n ): Promise<T[]> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Filter out organisation_id from data to prevent manipulation\n const { organisation_id, ...secureData } = data;\n \n // Build update query with organisation filter\n let query = supabase!\n .from(table)\n .update(secureData);\n\n // Add organisation filter only if table has organisation_id column\n const tablesWithOrganisation = [\n 'event', 'organisation_settings',\n 'rbac_event_app_roles', 'rbac_organisation_roles',\n // SECURITY: Phase 2 additions - complete organisation table mapping\n 'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',\n // SECURITY: Emergency additions for Phase 1 fixes\n 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member'\n ];\n \n if (tablesWithOrganisation.includes(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n\n // Apply filters\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n query = query.eq(key, value);\n }\n });\n\n const { data: updateData, error } = await query.select();\n\n if (error) {\n logger.error('useSecureDataAccess', 'Update failed', { table, data: secureData, filters, error });\n throw error;\n }\n\n return (updateData as T[]) || [];\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase]);\n\n const secureDelete = useCallback(async (\n table: string,\n filters: Record<string, any>\n ): Promise<void> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Build delete query with organisation filter\n let query = supabase!\n .from(table)\n .delete();\n\n // Add organisation filter only if table has organisation_id column\n const tablesWithOrganisation = [\n 'event', 'organisation_settings',\n 'rbac_event_app_roles', 'rbac_organisation_roles',\n // SECURITY: Phase 2 additions - complete organisation table mapping\n 'organisation_audit_log', 'organisation_invitations', 'organisation_app_access',\n // SECURITY: Emergency additions for Phase 1 fixes\n 'cake_meal', 'cake_mealtype', 'pace_person', 'pace_member',\n // SECURITY: Phase 3A additions - medical and personal data\n 'medi_profile', 'medi_condition', 'medi_diet', 'medi_action_plan', 'medi_profile_versions',\n 'pace_consent', 'pace_contact', 'pace_identification', 'pace_identification_type', 'pace_qualification',\n 'form_responses', 'form_response_values', 'forms',\n // SECURITY: Phase 3B additions - remaining critical tables\n 'invoice', 'line_item', 'credit_balance', 'payment_method',\n 'form_contexts', 'form_field_config', 'form_fields',\n 'cake_delivery', 'cake_diettype', 'cake_diner', 'cake_dish', 'cake_item', \n 'cake_logistics', 'cake_mealplan', 'cake_package', 'cake_recipe', 'cake_supplier', \n 'cake_supply', 'cake_unit', 'event_app_access', 'base_application', 'base_questions'\n ];\n \n if (tablesWithOrganisation.includes(table)) {\n query = query.eq('organisation_id', organisationId);\n }\n\n // Apply filters\n Object.entries(filters).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n query = query.eq(key, value);\n }\n });\n\n const { error } = await query;\n\n if (error) {\n logger.error('useSecureDataAccess', 'Delete failed', { table, filters, error });\n throw error;\n }\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase]);\n\n const secureRpc = useCallback(async <T = any>(\n functionName: string,\n params: Record<string, any> = {}\n ): Promise<T> => {\n validateContext();\n const organisationId = getCurrentOrganisationId();\n\n // Set organisation context in database session\n await setOrganisationContextInSession(organisationId);\n\n // Include organisation_id in RPC parameters\n // Some functions use p_organisation_id instead of organisation_id (to avoid conflicts with RETURNS TABLE columns)\n const functionsWithPOrganisationId = [\n 'data_cake_diners_list',\n 'data_cake_mealplans_list'\n ];\n \n const paramName = functionsWithPOrganisationId.includes(functionName) \n ? 'p_organisation_id' \n : 'organisation_id';\n \n // Functions that need p_event_id for event-app role permission checks\n // Note: Even org-scoped functions (like items, packages, suppliers) need event_id\n // for permission checks when users have event-app roles\n const functionsNeedingEventId = [\n 'data_cake_items_list',\n 'data_cake_packages_list',\n 'data_cake_suppliers_list',\n 'data_cake_diettypes_list',\n 'data_cake_mealtypes_list',\n 'data_cake_diners_list',\n 'data_cake_mealplans_list',\n 'data_cake_dishes_list',\n 'data_cake_recipes_list',\n 'data_cake_meals_list',\n 'data_cake_units_list',\n 'data_cake_orders_list',\n 'app_cake_item_create',\n 'app_cake_item_update',\n 'app_cake_package_create',\n 'app_cake_package_update',\n 'app_cake_supplier_create',\n 'app_cake_supplier_update',\n 'app_cake_supplier_delete',\n 'app_cake_meal_create',\n 'app_cake_meal_update',\n 'app_cake_meal_delete',\n 'app_cake_unit_create',\n 'app_cake_unit_update',\n 'app_cake_unit_delete',\n 'app_cake_delivery_upsert'\n ];\n \n // Build secureParams with correct parameter order\n // For functions that require p_event_id as first parameter, ensure it's first\n const secureParams: Record<string, any> = {};\n \n // Functions where p_event_id is the FIRST required parameter (no default)\n const functionsWithEventIdFirst = [\n 'data_cake_meals_list',\n 'data_cake_units_list'\n ];\n \n // Add p_user_id explicitly for functions that need it (even though it has a default)\n // This ensures parameter matching works correctly\n if (user?.id) {\n secureParams.p_user_id = user.id;\n }\n \n // Add organisation_id parameter\n secureParams[paramName] = organisationId;\n \n // Add p_event_id if function needs it and event is selected\n // CRITICAL: This must be added AFTER organisation_id but BEFORE caller params\n // to ensure it's not overwritten. For data_cake_items_list, p_event_id is the 3rd param.\n if (functionsNeedingEventId.includes(functionName) && selectedEvent?.event_id) {\n secureParams.p_event_id = selectedEvent.event_id;\n }\n \n // Add any other params passed by caller (limit, offset, etc.)\n // NOTE: This will NOT overwrite p_event_id if caller passes it, but we want to ensure\n // our value takes precedence if event is selected\n Object.assign(secureParams, params);\n \n // Ensure p_event_id is set if needed (after Object.assign, so it overrides caller params)\n if (functionsNeedingEventId.includes(functionName) && selectedEvent?.event_id) {\n secureParams.p_event_id = selectedEvent.event_id;\n }\n\n const { data, error } = await supabase!.rpc(functionName, secureParams);\n\n if (error) {\n logger.error('useSecureDataAccess', 'RPC failed', { functionName, params: secureParams, error });\n throw error;\n }\n\n return data as T;\n }, [validateContext, getCurrentOrganisationId, setOrganisationContextInSession, supabase, selectedEvent?.event_id, user?.id]);\n\n // NEW: Phase 1 - Enhanced Security Features\n const [dataAccessHistory, setDataAccessHistory] = useState<DataAccessRecord[]>([]);\n const [isStrictMode] = useState(true); // Always enabled in Phase 1\n const [isAuditLogEnabled] = useState(true); // Always enabled in Phase 1\n\n // Check if data access is allowed for a table and operation\n const isDataAccessAllowed = useCallback((table: string, operation: string): boolean => {\n if (!user?.id) return false;\n \n // Use the existing RBAC system to check data access permissions\n // This is a synchronous check for the context - actual permission checking\n // happens in the secure data operations using the RBAC engine\n const permission = `${operation}:data.${table}` as Permission;\n \n // For now, we'll return true and let the secure data operations\n // handle the actual permission checking asynchronously\n // This context is mainly for tracking and audit purposes\n return true;\n }, [user?.id]);\n\n // Get all data access permissions for current user\n const getDataAccessPermissions = useCallback((): Record<string, string[]> => {\n if (!user?.id) return {};\n \n // For now, return empty object - this will be enhanced with actual permission checking\n // when we integrate with the existing RBAC system\n return {};\n }, [user?.id]);\n\n // Get data access history\n const getDataAccessHistory = useCallback((): DataAccessRecord[] => {\n return [...dataAccessHistory];\n }, [dataAccessHistory]);\n\n // Clear data access history\n const clearDataAccessHistory = useCallback(() => {\n setDataAccessHistory([]);\n }, []);\n\n // Validate data access attempt\n const validateDataAccess = useCallback((table: string, operation: string): boolean => {\n if (!user?.id) return false;\n \n // Validate organisation context\n try {\n validateContext();\n } catch (error) {\n logger.error('useSecureDataAccess', 'Organisation context validation failed', { table, operation, error });\n return false;\n }\n \n return isDataAccessAllowed(table, operation);\n }, [user?.id, validateContext, isDataAccessAllowed]);\n\n // Record data access attempt\n const recordDataAccess = useCallback((\n table: string,\n operation: string,\n allowed: boolean,\n query?: string,\n filters?: Record<string, any>\n ) => {\n if (!isAuditLogEnabled || !user?.id) return;\n \n const record: DataAccessRecord = {\n table,\n operation,\n userId: user.id,\n organisationId: getCurrentOrganisationId(),\n allowed,\n timestamp: new Date().toISOString(),\n query,\n filters\n };\n \n setDataAccessHistory(prev => {\n const newHistory = [record, ...prev];\n return newHistory.slice(0, 1000); // Keep last 1000 records\n });\n \n if (isStrictMode && !allowed) {\n logger.error('useSecureDataAccess', 'STRICT MODE VIOLATION: User attempted data access without permission', {\n table,\n operation,\n userId: user.id,\n organisationId: getCurrentOrganisationId(),\n timestamp: new Date().toISOString()\n });\n }\n }, [isAuditLogEnabled, isStrictMode, user?.id, getCurrentOrganisationId]);\n\n return {\n secureQuery,\n secureInsert,\n secureUpdate,\n secureDelete,\n secureRpc,\n getCurrentOrganisationId,\n validateContext,\n // NEW: Phase 1 - Enhanced Security Features\n isDataAccessAllowed,\n getDataAccessPermissions,\n isStrictMode,\n isAuditLogEnabled,\n getDataAccessHistory,\n clearDataAccessHistory,\n validateDataAccess\n };\n} "],"mappings":";;;;;;;;;;;;;;;AAqDA,SAAS,aAAa,UAAU,kBAAkB;AAiG3C,SAAS,sBAA8C;AAC5D,QAAM,EAAE,UAAU,MAAM,QAAQ,IAAI,eAAe;AACnD,QAAM,EAAE,0BAA0B,IAAI,iBAAiB;AAIvD,QAAM,sBAAsB,WAAW,mBAAmB;AAC1D,QAAM,gBAAgB,qBAAqB,cAAc,iBAAiB,KAAK;AAE/E,QAAM,kBAAkB,YAAY,MAAY;AAC9C,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AACA,QAAI,CAAC,QAAQ,CAAC,SAAS;AACrB,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AAEA,QAAI;AACF,gCAA0B;AAAA,IAC5B,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,kDAAkD;AAAA,IACpE;AAAA,EACF,GAAG,CAAC,UAAU,MAAM,SAAS,yBAAyB,CAAC;AAEvD,QAAM,2BAA2B,YAAY,MAAc;AACzD,oBAAgB;AAChB,UAAM,aAAa,0BAA0B;AAC7C,WAAO,WAAW;AAAA,EACpB,GAAG,CAAC,iBAAiB,yBAAyB,CAAC;AAG/C,QAAM,kCAAkC,YAAY,OAAO,mBAA0C;AACnG,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAEA,UAAM,uBAAuB,UAAU,cAAc;AAAA,EACvD,GAAG,CAAC,QAAQ,CAAC;AAEb,QAAM,cAAc,YAAY,OAC9B,OACA,SACA,UAA+B,CAAC,GAChC,UAKI,CAAC,MACY;AACjB,oBAAgB;AAChB,UAAM,iBAAiB,yBAAyB;AAGhD,UAAM,gCAAgC,cAAc;AAGpD,QAAI,QAAQ,SACT,KAAK,KAAK,EACV,OAAO,OAAO;AAGjB,UAAM,yBAAyB;AAAA,MAC7B;AAAA,MAAU;AAAA,MACV;AAAA,MAAwB;AAAA;AAAA,MAExB;AAAA,MAA0B;AAAA,MAA4B;AAAA;AAAA,MAEtD;AAAA,MAAa;AAAA,MAAiB;AAAA,MAAe;AAAA;AAAA,MAE7C;AAAA,MAAgB;AAAA,MAAkB;AAAA,MAAa;AAAA,MAAoB;AAAA,MACnE;AAAA,MAAgB;AAAA,MAAgB;AAAA,MAAuB;AAAA,MAA4B;AAAA,MACnF;AAAA,MAAkB;AAAA,MAAwB;AAAA;AAAA,MAE1C;AAAA,MAAW;AAAA,MAAa;AAAA,MAAkB;AAAA,MAC1C;AAAA,MAAiB;AAAA,MAAqB;AAAA,MACtC;AAAA,MAAiB;AAAA,MAAiB;AAAA,MAAc;AAAA,MAAa;AAAA,MAC7D;AAAA,MAAkB;AAAA,MAAiB;AAAA,MAAgB;AAAA,MAAe;AAAA,MAClE;AAAA,MAAe;AAAA,MAAa;AAAA,MAAoB;AAAA,MAAoB;AAAA,IACtE;AAEA,QAAI,uBAAuB,SAAS,KAAK,GAAG;AAC1C,cAAQ,MAAM,GAAG,mBAAmB,cAAc;AAAA,IACpD;AAGA,WAAO,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAChD,UAAI,UAAU,UAAa,UAAU,MAAM;AAEzC,cAAM,aAAa,IAAI,SAAS,GAAG,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI,IAAK;AAC/D,gBAAQ,MAAM,GAAG,YAAY,KAAK;AAAA,MACpC;AAAA,IACF,CAAC;AAGD,QAAI,QAAQ,SAAS;AAEnB,YAAM,gBAAgB,QAAQ,QAAQ,MAAM,GAAG,EAAE,IAAI;AACrD,UAAI,eAAe;AACjB,gBAAQ,MAAM,MAAM,eAAe,EAAE,WAAW,QAAQ,aAAa,KAAK,CAAC;AAAA,MAC7E;AAAA,IACF;AAEA,QAAI,QAAQ,OAAO;AACjB,cAAQ,MAAM,MAAM,QAAQ,KAAK;AAAA,IACnC;AAEA,QAAI,QAAQ,QAAQ;AAClB,cAAQ,MAAM,MAAM,QAAQ,QAAQ,QAAQ,UAAU,QAAQ,SAAS,OAAO,CAAC;AAAA,IACjF;AAEA,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM;AAE9B,QAAI,OAAO;AACT,aAAO,MAAM,uBAAuB,gBAAgB,EAAE,OAAO,SAAS,SAAS,MAAM,CAAC;AAEtF,uBAAiB,OAAO,QAAQ,OAAO,UAAU,OAAO,SAAS,KAAK,IAAI,OAAO;AACjF,YAAM;AAAA,IACR;AAGA,qBAAiB,OAAO,QAAQ,MAAM,UAAU,OAAO,SAAS,KAAK,IAAI,OAAO;AAEhF,WAAQ,QAAgB,CAAC;AAAA,EAC3B,GAAG,CAAC,iBAAiB,0BAA0B,iCAAiC,QAAQ,CAAC;AAEzF,QAAM,eAAe,YAAY,OAC/B,OACA,SACe;AACf,oBAAgB;AAChB,UAAM,iBAAiB,yBAAyB;AAGhD,UAAM,gCAAgC,cAAc;AAGpD,UAAM,aAAa;AAAA,MACjB,GAAG;AAAA,MACH,iBAAiB;AAAA,IACnB;AAEA,UAAM,EAAE,MAAM,YAAY,MAAM,IAAI,MAAM,SACvC,KAAK,KAAK,EACV,OAAO,UAAU,EACjB,OAAO,EACP,OAAO;AAEV,QAAI,OAAO;AACT,aAAO,MAAM,uBAAuB,iBAAiB,EAAE,OAAO,MAAM,YAAY,MAAM,CAAC;AACvF,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,iBAAiB,0BAA0B,iCAAiC,QAAQ,CAAC;AAEzF,QAAM,eAAe,YAAY,OAC/B,OACA,MACA,YACiB;AACjB,oBAAgB;AAChB,UAAM,iBAAiB,yBAAyB;AAGhD,UAAM,gCAAgC,cAAc;AAGpD,UAAM,EAAE,iBAAiB,GAAG,WAAW,IAAI;AAG3C,QAAI,QAAQ,SACT,KAAK,KAAK,EACV,OAAO,UAAU;AAGpB,UAAM,yBAAyB;AAAA,MAC7B;AAAA,MAAU;AAAA,MACV;AAAA,MAAwB;AAAA;AAAA,MAExB;AAAA,MAA0B;AAAA,MAA4B;AAAA;AAAA,MAEtD;AAAA,MAAa;AAAA,MAAiB;AAAA,MAAe;AAAA,IAC/C;AAEA,QAAI,uBAAuB,SAAS,KAAK,GAAG;AAC1C,cAAQ,MAAM,GAAG,mBAAmB,cAAc;AAAA,IACpD;AAGA,WAAO,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAChD,UAAI,UAAU,UAAa,UAAU,MAAM;AACzC,gBAAQ,MAAM,GAAG,KAAK,KAAK;AAAA,MAC7B;AAAA,IACF,CAAC;AAED,UAAM,EAAE,MAAM,YAAY,MAAM,IAAI,MAAM,MAAM,OAAO;AAEvD,QAAI,OAAO;AACT,aAAO,MAAM,uBAAuB,iBAAiB,EAAE,OAAO,MAAM,YAAY,SAAS,MAAM,CAAC;AAChG,YAAM;AAAA,IACR;AAEA,WAAQ,cAAsB,CAAC;AAAA,EACjC,GAAG,CAAC,iBAAiB,0BAA0B,iCAAiC,QAAQ,CAAC;AAEzF,QAAM,eAAe,YAAY,OAC/B,OACA,YACkB;AAClB,oBAAgB;AAChB,UAAM,iBAAiB,yBAAyB;AAGhD,UAAM,gCAAgC,cAAc;AAGpD,QAAI,QAAQ,SACT,KAAK,KAAK,EACV,OAAO;AAGV,UAAM,yBAAyB;AAAA,MAC7B;AAAA,MAAU;AAAA,MACV;AAAA,MAAwB;AAAA;AAAA,MAExB;AAAA,MAA0B;AAAA,MAA4B;AAAA;AAAA,MAEtD;AAAA,MAAa;AAAA,MAAiB;AAAA,MAAe;AAAA;AAAA,MAE7C;AAAA,MAAgB;AAAA,MAAkB;AAAA,MAAa;AAAA,MAAoB;AAAA,MACnE;AAAA,MAAgB;AAAA,MAAgB;AAAA,MAAuB;AAAA,MAA4B;AAAA,MACnF;AAAA,MAAkB;AAAA,MAAwB;AAAA;AAAA,MAE1C;AAAA,MAAW;AAAA,MAAa;AAAA,MAAkB;AAAA,MAC1C;AAAA,MAAiB;AAAA,MAAqB;AAAA,MACtC;AAAA,MAAiB;AAAA,MAAiB;AAAA,MAAc;AAAA,MAAa;AAAA,MAC7D;AAAA,MAAkB;AAAA,MAAiB;AAAA,MAAgB;AAAA,MAAe;AAAA,MAClE;AAAA,MAAe;AAAA,MAAa;AAAA,MAAoB;AAAA,MAAoB;AAAA,IACtE;AAEA,QAAI,uBAAuB,SAAS,KAAK,GAAG;AAC1C,cAAQ,MAAM,GAAG,mBAAmB,cAAc;AAAA,IACpD;AAGA,WAAO,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAChD,UAAI,UAAU,UAAa,UAAU,MAAM;AACzC,gBAAQ,MAAM,GAAG,KAAK,KAAK;AAAA,MAC7B;AAAA,IACF,CAAC;AAED,UAAM,EAAE,MAAM,IAAI,MAAM;AAExB,QAAI,OAAO;AACT,aAAO,MAAM,uBAAuB,iBAAiB,EAAE,OAAO,SAAS,MAAM,CAAC;AAC9E,YAAM;AAAA,IACR;AAAA,EACF,GAAG,CAAC,iBAAiB,0BAA0B,iCAAiC,QAAQ,CAAC;AAEzF,QAAM,YAAY,YAAY,OAC5B,cACA,SAA8B,CAAC,MAChB;AACf,oBAAgB;AAChB,UAAM,iBAAiB,yBAAyB;AAGhD,UAAM,gCAAgC,cAAc;AAIpD,UAAM,+BAA+B;AAAA,MACnC;AAAA,MACA;AAAA,IACF;AAEA,UAAM,YAAY,6BAA6B,SAAS,YAAY,IAChE,sBACA;AAKJ,UAAM,0BAA0B;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAIA,UAAM,eAAoC,CAAC;AAG3C,UAAM,4BAA4B;AAAA,MAChC;AAAA,MACA;AAAA,IACF;AAIA,QAAI,MAAM,IAAI;AACZ,mBAAa,YAAY,KAAK;AAAA,IAChC;AAGA,iBAAa,SAAS,IAAI;AAK1B,QAAI,wBAAwB,SAAS,YAAY,KAAK,eAAe,UAAU;AAC7E,mBAAa,aAAa,cAAc;AAAA,IAC1C;AAKA,WAAO,OAAO,cAAc,MAAM;AAGlC,QAAI,wBAAwB,SAAS,YAAY,KAAK,eAAe,UAAU;AAC7E,mBAAa,aAAa,cAAc;AAAA,IAC1C;AAEA,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,SAAU,IAAI,cAAc,YAAY;AAEtE,QAAI,OAAO;AACT,aAAO,MAAM,uBAAuB,cAAc,EAAE,cAAc,QAAQ,cAAc,MAAM,CAAC;AAC/F,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,iBAAiB,0BAA0B,iCAAiC,UAAU,eAAe,UAAU,MAAM,EAAE,CAAC;AAG5H,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAA6B,CAAC,CAAC;AACjF,QAAM,CAAC,YAAY,IAAI,SAAS,IAAI;AACpC,QAAM,CAAC,iBAAiB,IAAI,SAAS,IAAI;AAGzC,QAAM,sBAAsB,YAAY,CAAC,OAAe,cAA+B;AACrF,QAAI,CAAC,MAAM,GAAI,QAAO;AAKtB,UAAM,aAAa,GAAG,SAAS,SAAS,KAAK;AAK7C,WAAO;AAAA,EACT,GAAG,CAAC,MAAM,EAAE,CAAC;AAGb,QAAM,2BAA2B,YAAY,MAAgC;AAC3E,QAAI,CAAC,MAAM,GAAI,QAAO,CAAC;AAIvB,WAAO,CAAC;AAAA,EACV,GAAG,CAAC,MAAM,EAAE,CAAC;AAGb,QAAM,uBAAuB,YAAY,MAA0B;AACjE,WAAO,CAAC,GAAG,iBAAiB;AAAA,EAC9B,GAAG,CAAC,iBAAiB,CAAC;AAGtB,QAAM,yBAAyB,YAAY,MAAM;AAC/C,yBAAqB,CAAC,CAAC;AAAA,EACzB,GAAG,CAAC,CAAC;AAGL,QAAM,qBAAqB,YAAY,CAAC,OAAe,cAA+B;AACpF,QAAI,CAAC,MAAM,GAAI,QAAO;AAGtB,QAAI;AACF,sBAAgB;AAAA,IAClB,SAAS,OAAO;AACd,aAAO,MAAM,uBAAuB,0CAA0C,EAAE,OAAO,WAAW,MAAM,CAAC;AACzG,aAAO;AAAA,IACT;AAEA,WAAO,oBAAoB,OAAO,SAAS;AAAA,EAC7C,GAAG,CAAC,MAAM,IAAI,iBAAiB,mBAAmB,CAAC;AAGnD,QAAM,mBAAmB,YAAY,CACnC,OACA,WACA,SACA,OACA,YACG;AACH,QAAI,CAAC,qBAAqB,CAAC,MAAM,GAAI;AAErC,UAAM,SAA2B;AAAA,MAC/B;AAAA,MACA;AAAA,MACA,QAAQ,KAAK;AAAA,MACb,gBAAgB,yBAAyB;AAAA,MACzC;AAAA,MACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC;AAAA,MACA;AAAA,IACF;AAEA,yBAAqB,UAAQ;AAC3B,YAAM,aAAa,CAAC,QAAQ,GAAG,IAAI;AACnC,aAAO,WAAW,MAAM,GAAG,GAAI;AAAA,IACjC,CAAC;AAED,QAAI,gBAAgB,CAAC,SAAS;AAC5B,aAAO,MAAM,uBAAuB,wEAAwE;AAAA,QAC1G;AAAA,QACA;AAAA,QACA,QAAQ,KAAK;AAAA,QACb,gBAAgB,yBAAyB;AAAA,QACzC,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,mBAAmB,cAAc,MAAM,IAAI,wBAAwB,CAAC;AAExE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "./chunk-PWLANIRT.js";
|
|
13
13
|
|
|
14
14
|
// src/providers/services/UnifiedAuthProvider.tsx
|
|
15
|
-
import { createContext as createContext5, useContext as useContext6, useMemo as useMemo6, useCallback, useRef as useRef4, useEffect as useEffect10, useState as useState3 } from "react";
|
|
15
|
+
import { createContext as createContext5, useContext as useContext6, useMemo as useMemo6, useCallback, useRef as useRef4, useEffect as useEffect10, useState as useState3, useReducer as useReducer5 } from "react";
|
|
16
16
|
|
|
17
17
|
// src/providers/services/AuthServiceProvider.tsx
|
|
18
18
|
import { createContext, useMemo, useEffect, useState } from "react";
|
|
@@ -969,6 +969,7 @@ var OrganisationService = class extends BaseService {
|
|
|
969
969
|
this._userMemberships = memberships;
|
|
970
970
|
this._roleMapState = roleMap;
|
|
971
971
|
let initialOrg = null;
|
|
972
|
+
let selectionMethod = "first";
|
|
972
973
|
try {
|
|
973
974
|
const persistedOrgString = localStorage.getItem("pace-core-selected-organisation");
|
|
974
975
|
if (persistedOrgString) {
|
|
@@ -977,6 +978,7 @@ var OrganisationService = class extends BaseService {
|
|
|
977
978
|
const validPersistedOrg = activeOrgs.find((org) => org.id === persistedOrg.id);
|
|
978
979
|
if (validPersistedOrg) {
|
|
979
980
|
initialOrg = validPersistedOrg;
|
|
981
|
+
selectionMethod = "persisted";
|
|
980
982
|
} else {
|
|
981
983
|
logger.warn("OrganisationService", "Persisted organisation not found in active orgs, clearing cache");
|
|
982
984
|
localStorage.removeItem("pace-core-selected-organisation");
|
|
@@ -996,11 +998,13 @@ var OrganisationService = class extends BaseService {
|
|
|
996
998
|
const foundOrg = organisations.find((org) => org.id === adminMembership.organisation_id);
|
|
997
999
|
if (foundOrg) {
|
|
998
1000
|
initialOrg = foundOrg;
|
|
1001
|
+
selectionMethod = "admin";
|
|
999
1002
|
}
|
|
1000
1003
|
}
|
|
1001
1004
|
}
|
|
1002
1005
|
if (!initialOrg) {
|
|
1003
1006
|
initialOrg = activeOrgs[0];
|
|
1007
|
+
selectionMethod = "first";
|
|
1004
1008
|
}
|
|
1005
1009
|
if (!initialOrg) {
|
|
1006
1010
|
throw new Error("No valid organisation found for user");
|
|
@@ -1919,7 +1923,10 @@ function UnifiedAuthContextProvider({
|
|
|
1919
1923
|
setSelectedEvent: () => {
|
|
1920
1924
|
},
|
|
1921
1925
|
refreshEvents: async () => {
|
|
1926
|
+
},
|
|
1927
|
+
subscribe: () => () => {
|
|
1922
1928
|
}
|
|
1929
|
+
// No-op subscribe/unsubscribe for fallback
|
|
1923
1930
|
};
|
|
1924
1931
|
}
|
|
1925
1932
|
const currentUser = authService.getUser();
|
|
@@ -1933,7 +1940,7 @@ function UnifiedAuthContextProvider({
|
|
|
1933
1940
|
isResolvingAppIdRef.current = true;
|
|
1934
1941
|
const userId = currentUser.id;
|
|
1935
1942
|
const appNameValue = appName;
|
|
1936
|
-
import("./api-
|
|
1943
|
+
import("./api-BMFCXVQX.js").then(async ({ resolveAppContext, setupRBAC }) => {
|
|
1937
1944
|
try {
|
|
1938
1945
|
setupRBAC(supabase);
|
|
1939
1946
|
const result = await resolveAppContext({
|
|
@@ -1965,6 +1972,19 @@ function UnifiedAuthContextProvider({
|
|
|
1965
1972
|
setAppId(void 0);
|
|
1966
1973
|
}
|
|
1967
1974
|
}, [isAuth, currentUser?.id, supabase, appName, appId]);
|
|
1975
|
+
const [, forceUpdate] = useReducer5((x) => x + 1, 0);
|
|
1976
|
+
useEffect10(() => {
|
|
1977
|
+
const unsubscribeAuth = authService.subscribe(() => forceUpdate());
|
|
1978
|
+
const unsubscribeOrg = organisationService.subscribe(() => forceUpdate());
|
|
1979
|
+
const unsubscribeEvent = eventService.subscribe(() => forceUpdate());
|
|
1980
|
+
const unsubscribeInactivity = inactivityService.subscribe(() => forceUpdate());
|
|
1981
|
+
return () => {
|
|
1982
|
+
unsubscribeAuth();
|
|
1983
|
+
unsubscribeOrg();
|
|
1984
|
+
unsubscribeEvent();
|
|
1985
|
+
unsubscribeInactivity();
|
|
1986
|
+
};
|
|
1987
|
+
}, [authService, organisationService, eventService, inactivityService]);
|
|
1968
1988
|
const authLoading = authService.isLoading();
|
|
1969
1989
|
const orgLoading = organisationService.isLoading();
|
|
1970
1990
|
const eventLoading = eventService.isLoading();
|
|
@@ -2290,7 +2310,8 @@ export {
|
|
|
2290
2310
|
useEventService,
|
|
2291
2311
|
useInactivityService,
|
|
2292
2312
|
useSessionRestoration,
|
|
2313
|
+
UnifiedAuthContext,
|
|
2293
2314
|
useUnifiedAuth,
|
|
2294
2315
|
UnifiedAuthProvider
|
|
2295
2316
|
};
|
|
2296
|
-
//# sourceMappingURL=chunk-
|
|
2317
|
+
//# sourceMappingURL=chunk-FXFJRTKI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/providers/services/UnifiedAuthProvider.tsx","../src/providers/services/AuthServiceProvider.tsx","../src/services/AuthService.ts","../src/services/base/BaseService.ts","../src/providers/services/OrganisationServiceProvider.tsx","../src/services/OrganisationService.ts","../src/providers/services/EventServiceProvider.tsx","../src/services/EventService.ts","../src/providers/services/InactivityServiceProvider.tsx","../src/services/InactivityService.ts","../src/hooks/services/useAuthService.ts","../src/hooks/services/useOrganisationService.ts","../src/hooks/services/useEventService.ts","../src/hooks/services/useInactivityService.ts","../src/hooks/useSessionRestoration.ts"],"sourcesContent":["/**\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, useEffect, useState, useReducer } 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/event';\nimport type { AuthError } from '@supabase/supabase-js';\nimport type { SessionRestorationState } from '../../types/auth';\nimport { logger } from '../../utils/core/logger';\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 supabase: SupabaseClient | null;\n \n // App context (resolved immediately on login)\n appName: string;\n appId: string | undefined; // Resolved from appName when user logs in\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 appConfig: { requires_event: boolean } | null;\n isLoading: boolean;\n hasErrors: boolean;\n sessionRestoration: SessionRestorationState;\n sessionRestorationTimedOut: boolean;\n sessionRestorationTimeoutMs: number;\n}\n\nexport const UnifiedAuthContext = createContext<UnifiedAuthContextType | undefined>(undefined);\n\nexport const useUnifiedAuth = () => {\n const context = useContext(UnifiedAuthContext);\n if (!context) {\n // Provide a helpful error log in addition to throwing for testability and DX\n logger.error('useUnifiedAuth', '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 // Include subscribe method to match BaseService interface\n eventService = {\n getEvents: () => [],\n getSelectedEvent: () => null,\n isLoading: () => false,\n getError: () => null,\n setSelectedEvent: () => {},\n refreshEvents: async () => {},\n subscribe: () => () => {} // No-op subscribe/unsubscribe for fallback\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 supabase client early so we can use it in useEffect\n const supabase = authService.getSupabaseClient();\n \n // Resolve appId immediately when user logs in (don't wait for organisation/event)\n // This makes appId available early for navigation menu filtering\n const [appId, setAppId] = useState<string | undefined>(undefined);\n const isResolvingAppIdRef = useRef(false);\n \n useEffect(() => {\n // Resolve appId as soon as we have user + supabase + appName\n // Don't wait for organisation or event - appId resolution only needs user + appName\n if (\n isAuth &&\n currentUser?.id &&\n supabase &&\n appName &&\n !appId &&\n !isResolvingAppIdRef.current\n ) {\n isResolvingAppIdRef.current = true;\n const userId = currentUser.id;\n const appNameValue = appName;\n \n // Resolve appId immediately\n import('../../rbac/api').then(async ({ resolveAppContext, setupRBAC }) => {\n try {\n // Ensure RBAC is initialized (idempotent - safe to call multiple times)\n setupRBAC(supabase);\n \n const result = await resolveAppContext({\n userId,\n appName: appNameValue\n });\n \n if (result?.appId) {\n setAppId(result.appId);\n logger.debug('UnifiedAuthProvider', 'appId resolved on login', {\n appId: result.appId,\n appName: appNameValue\n });\n }\n } catch (error) {\n logger.error('UnifiedAuthProvider', 'Failed to resolve appId on login', {\n error: error instanceof Error ? error.message : String(error),\n appName: appNameValue,\n userId\n });\n } finally {\n isResolvingAppIdRef.current = false;\n }\n }).catch((importError) => {\n logger.error('UnifiedAuthProvider', 'Failed to import RBAC API', importError);\n isResolvingAppIdRef.current = false;\n });\n }\n \n // Clear appId when user logs out\n if (!isAuth) {\n setAppId(undefined);\n }\n }, [isAuth, currentUser?.id, supabase, appName, appId]);\n\n // Subscribe to service state changes to trigger re-renders\n // Use useReducer to force updates when services notify\n const [, forceUpdate] = useReducer(x => x + 1, 0);\n \n useEffect(() => {\n // Subscribe to all service changes\n const unsubscribeAuth = authService.subscribe(() => forceUpdate());\n const unsubscribeOrg = organisationService.subscribe(() => forceUpdate());\n const unsubscribeEvent = eventService.subscribe(() => forceUpdate());\n const unsubscribeInactivity = inactivityService.subscribe(() => forceUpdate());\n \n return () => {\n unsubscribeAuth();\n unsubscribeOrg();\n unsubscribeEvent();\n unsubscribeInactivity();\n };\n }, [authService, organisationService, eventService, inactivityService]);\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 // supabase is already declared above (line 198)\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 // State change detected, notify subscribers\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 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 appId, // Resolved immediately on login\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 appId,\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 // Warn if supabaseClient reference changes (indicates multiple client instances)\n const clientRef = useRef(supabaseClient);\n useEffect(() => {\n if (clientRef.current !== supabaseClient) {\n logger.warn('UnifiedAuthProvider', 'Supabase client reference changed - this may indicate multiple client instances are being created', {\n previousClient: clientRef.current,\n newClient: supabaseClient,\n note: 'Ensure you create the Supabase client once and reuse it. Creating multiple clients can cause performance issues and the \"Multiple GoTrueClient instances\" warning.'\n });\n clientRef.current = supabaseClient;\n }\n }, [supabaseClient]);\n\n return (\n <AuthServiceProvider supabaseClient={supabaseClient} appName={appName}>\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","/**\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, useMemo, useEffect, useState } from 'react';\nimport { type SupabaseClient } from '@supabase/supabase-js';\nimport { AuthService } from '../../services/AuthService';\nimport type { SessionRestorationState } from '../../types/auth';\nimport { logger } from '../../utils/core/logger';\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 appName?: string;\n}\n\nexport function AuthServiceProvider({ children, supabaseClient, appName }: AuthServiceProviderProps) {\n // Create service instance with useMemo to prevent recreation on every render\n const authService = useMemo(\n () => new AuthService(supabaseClient, appName),\n [supabaseClient, appName]\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\n return () => {\n unsubscribe();\n };\n }, [authService]);\n\n // Initialize service on mount\n useEffect(() => {\n authService.initialize().catch(error => {\n logger.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 * @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, type AuthChangeEvent, type Session as SupabaseSession } from '@supabase/supabase-js';\nimport type { SessionRestorationState } from '../types/auth';\nimport { BaseService } from './base/BaseService';\nimport { IAuthService, AuthResult } from './interfaces/IAuthService';\nimport { logger } from '../utils/core/logger';\n\ntype AuthStateSubscription = {\n data: {\n subscription: {\n unsubscribe: () => void;\n };\n };\n};\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: { unsubscribe: () => void } | null = 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 private appName: string | undefined = undefined;\n private errorHandler: ((event: ErrorEvent) => void) | null = null;\n private unhandledRejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;\n\n constructor(supabaseClient: SupabaseClient, appName?: string) {\n super();\n this.supabaseClient = supabaseClient;\n this.appName = appName;\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) {\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 this.notify();\n\n this.restorationTimeoutId = setTimeout(() => {\n logger.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 logger.warn('AuthService', 'Session restoration finished with error:', error);\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 const subscription = this.supabaseClient.auth.onAuthStateChange(\n (event: AuthChangeEvent, session: SupabaseSession | null) => {\n try {\n // Handle different auth events\n if (event === 'SIGNED_OUT') {\n this.session = null;\n this.user = null;\n this.authError = null;\n \n // Automatic session tracking (non-blocking)\n if (session?.user) {\n this.trackSession('logout', session).catch(err => {\n logger.warn('AuthService', 'Failed to track logout session:', err);\n });\n }\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 \n // Automatic session tracking for login (non-blocking)\n // Only track on SIGNED_IN, not TOKEN_REFRESHED (to avoid duplicate login records)\n if (event === 'SIGNED_IN' && session?.user) {\n this.trackSession('login', session).catch(err => {\n logger.warn('AuthService', 'Failed to track login session:', err);\n });\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 // Reset restoration state if valid session arrives after earlier failure\n // This clears stale errors when session eventually succeeds\n const hasTimeoutError = this.sessionRestorationState.restorationError?.name === 'SessionRestorationTimeoutError';\n if (this.sessionRestorationState.isRestoring || \n this.sessionRestorationState.restorationError ||\n (hasTimeoutError && session)) {\n this.finishSessionRestoration();\n return;\n }\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 logger.warn('AuthService', 'Error in auth state change handler:', error);\n this.authLoading = false;\n this.notify();\n }\n }\n );\n this.authStateSubscription = subscription.data.subscription;\n } catch (error) {\n logger.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 logger.error('AuthService', 'Unable to restore session:', error);\n this.finishSessionRestoration(error);\n return;\n }\n\n this.startSessionRestoration();\n\n try {\n let currentSession: Session | null = null;\n let sessionError: AuthError | null = null;\n\n try {\n const { data, error } = await this.supabaseClient.auth.getSession();\n currentSession = data?.session ?? null;\n sessionError = error ?? null;\n } catch (error) {\n // Handle cases where getSession might not exist (mocked/test clients)\n currentSession = null;\n sessionError = null;\n }\n\n if (sessionError) {\n // Record error but continue to attempt getUser to satisfy edge cases\n this.authError = sessionError;\n \n // Attempt getUser as fallback when getSession fails\n try {\n const { data, error } = await this.supabaseClient.auth.getUser();\n const currentUser = data?.user ?? null;\n const userError = 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 } catch (getUserError) {\n // If getUser also fails, we've already recorded the sessionError\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 // 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 logger.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 /**\n * Automatically track user session using rbac_session_track\n * This method is called automatically on SIGNED_IN and SIGNED_OUT events.\n * It's non-blocking and failures are logged as warnings.\n */\n private async trackSession(\n sessionType: 'login' | 'logout',\n session: Session | null\n ): Promise<void> {\n if (!this.supabaseClient || !session?.user) {\n return;\n }\n\n try {\n // Resolve app_id from appName if available\n let appId: string | undefined = undefined;\n if (this.appName) {\n const { data, error } = await this.supabaseClient\n .from('rbac_apps')\n .select('id')\n .eq('name', this.appName)\n .eq('is_active', true)\n .single();\n \n if (!error && data) {\n appId = data.id;\n }\n }\n\n // Get IP address and user agent from browser (if available)\n const ipAddress = undefined; // Browser doesn't expose IP directly, could use API\n const userAgent = typeof navigator !== 'undefined' ? navigator.userAgent : undefined;\n \n // Get device fingerprint from localStorage if available\n // Note: Device fingerprinting should be done by consuming app and passed via custom header\n // For now, we'll skip it to avoid dependencies\n const deviceFingerprint = undefined;\n\n // Call rbac_session_track RPC function\n // This automatically inserts into rbac_user_sessions AND rbac_user_login_history (for login)\n // Note: Using type assertion for RPC call as Supabase doesn't provide full typing for custom RPC functions\n const { error } = await (this.supabaseClient as unknown as { rpc: (name: string, params: Record<string, unknown>) => Promise<{ error: Error | null }> }).rpc('rbac_session_track', {\n p_user_id: session.user.id,\n p_session_type: sessionType,\n p_event_id: null, // Event ID should come from context, not auth service\n p_app_id: appId,\n p_ip_address: ipAddress,\n p_user_agent: userAgent,\n p_device_fingerprint: deviceFingerprint,\n });\n\n if (error) {\n logger.warn('AuthService', `Failed to track ${sessionType} session:`, error);\n }\n } catch (error) {\n // Log error but don't throw (non-blocking)\n logger.warn('AuthService', `Error tracking ${sessionType} session:`, error);\n }\n }\n\n private setupErrorHandlers(): void {\n if (typeof window === 'undefined') return;\n\n this.errorHandler = (event: ErrorEvent) => {\n if (event.error?.message?.includes('AuthSessionMissingError') || \n event.error?.message?.includes('Auth session missing')) {\n logger.warn('AuthService', 'Suppressing AuthSessionMissingError during logout');\n event.preventDefault();\n return false;\n }\n };\n\n this.unhandledRejectionHandler = (event: PromiseRejectionEvent) => {\n if (event.reason?.message?.includes('AuthSessionMissingError') ||\n event.reason?.message?.includes('Auth session missing')) {\n logger.warn('AuthService', 'Suppressing unhandled AuthSessionMissingError');\n event.preventDefault();\n return false;\n }\n };\n\n window.addEventListener('error', this.errorHandler);\n window.addEventListener('unhandledrejection', this.unhandledRejectionHandler);\n }\n\n private removeErrorHandlers(): void {\n if (typeof window === 'undefined') return;\n\n if (this.errorHandler) {\n window.removeEventListener('error', this.errorHandler);\n this.errorHandler = null;\n }\n\n if (this.unhandledRejectionHandler) {\n window.removeEventListener('unhandledrejection', this.unhandledRejectionHandler);\n this.unhandledRejectionHandler = null;\n }\n }\n}","/**\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\nimport { logger } from '../../utils/core/logger';\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 logger.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 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, useMemo, useEffect, useRef } from 'react';\nimport { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';\nimport { OrganisationService } from '../../services/OrganisationService';\nimport { logger } from '../../utils/core/logger';\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()\n .catch(error => {\n if (isMounted) {\n logger.error('OrganisationServiceProvider', 'Failed to initialize organisation service:', error);\n }\n });\n\n return () => {\n isMounted = false;\n };\n }, [organisationService, user, session]);\n\n // Cleanup service on unmount only\n useEffect(() => {\n return () => {\n organisationService.cleanup();\n };\n }, [organisationService]);\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 * @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/context/organisationContext';\nimport { logger } from '../utils/core/logger';\nimport { assertUserId, assertOrganisationId } from '../types/core';\n\n// Type for RPC response from data_user_organisation_roles_get\ninterface OrganisationRoleRpcResponse {\n user_id: string;\n organisation_id: string;\n role: 'org_admin' | 'leader' | 'member' | 'supporter';\n status: 'active' | 'inactive' | 'suspended';\n [key: string]: unknown;\n}\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.resetInitialization();\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) => \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'] as const;\n \n for (const role of rolePriority) {\n const membership = this._userMemberships.find((m) => m.role === role);\n if (membership) {\n return this._organisations.find((org) => 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 logger.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 // 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 // Database organisation context set successfully\n this._isContextReady = true;\n this.notify();\n } catch (error) {\n logger.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 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 // 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 // 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 // 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 // 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 { data: OrganisationRoleRpcResponse[] | null; error: Error | null };\n \n // Filter to only actual members (org_admin, leader, member) - exclude supporters\n // Map to branded types when filtering\n memberships = result.data?.filter((role) => \n ['org_admin', 'leader', 'member'].includes(role.role)\n ).map((m) => ({\n ...m,\n user_id: assertUserId(m.user_id),\n organisation_id: assertOrganisationId(m.organisation_id),\n })) || [];\n membershipError = result.error;\n } catch (queryError) {\n membershipError = queryError instanceof Error ? queryError : new Error(String(queryError));\n }\n\n if (membershipError) {\n logger.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 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 logger.error(\"OrganisationService\", \"Fallback query also failed:\", fallbackError);\n throw membershipError; // Throw original error\n }\n \n // Map to branded types\n memberships = fallbackData?.map((m) => ({\n ...m,\n user_id: assertUserId(m.user_id),\n organisation_id: assertOrganisationId(m.organisation_id),\n })) || [];\n membershipError = null;\n } catch (fallbackErr) {\n logger.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) => m.organisation_id)\n .filter((id: string) => {\n // Better validation to prevent empty string UUID errors\n if (!id || typeof id !== 'string') {\n logger.warn(\"OrganisationService\", \"Invalid organisation ID (not string):\", id);\n return false;\n }\n const trimmedId = id.trim();\n if (trimmedId === '') {\n logger.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 logger.warn(\"OrganisationService\", \"Invalid UUID format:\", trimmedId);\n }\n return isValidUuid;\n });\n \n if (organisationIds.length === 0) {\n logger.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 logger.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) => {\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 // Memberships already have branded types from earlier mapping\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 let selectionMethod: 'persisted' | 'admin' | 'first' = 'first';\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 selectionMethod = 'persisted';\n } else {\n logger.warn(\"OrganisationService\", \"Persisted organisation not found in active orgs, clearing cache\");\n localStorage.removeItem('pace-core-selected-organisation');\n }\n } else {\n logger.warn(\"OrganisationService\", \"Invalid persisted organisation ID, clearing cache\");\n localStorage.removeItem('pace-core-selected-organisation');\n }\n }\n } catch (storageError) {\n logger.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) => 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 selectionMethod = 'admin';\n }\n }\n }\n \n // 3. Fall back to first organisation\n if (!initialOrg) {\n initialOrg = activeOrgs[0];\n selectionMethod = 'first';\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 logger.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 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, useMemo, useEffect, useRef } from 'react';\nimport { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';\nimport { EventService } from '../../services/EventService';\nimport { logger } from '../../utils/core/logger';\nimport type { Organisation } from '../../types/organisation';\n\n// Context type\nexport interface EventServiceContextType {\n eventService: EventService;\n}\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: Organisation | null;\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 let isMounted = true;\n \n const updateAndInitialize = async () => {\n // Update dependencies (now async to handle user change cleanup)\n await eventService.updateDependencies(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);\n \n if (!isMounted) return;\n \n // Re-initialize service when dependencies change\n await eventService.initialize().catch(error => {\n if (isMounted) {\n logger.error('EventServiceProvider', 'Failed to initialize event service:', error);\n }\n });\n };\n\n updateAndInitialize();\n\n return () => {\n isMounted = false;\n };\n }, [eventService, supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId]);\n\n // Cleanup service on unmount only\n useEffect(() => {\n return () => {\n eventService.cleanup();\n };\n }, [eventService]);\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 * @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/event';\nimport { Organisation } from '../types/organisation';\nimport { assertOrganisationId } from '../types/core';\nimport { logger } from '../utils/core/logger';\nimport { secureStorage } from '../utils/security/secureStorage';\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 // Helper method to get user-scoped storage key\n private getStorageKey(userId: string | null): string {\n if (!userId) {\n // Return a temporary key that won't match any user\n return 'pace-core-selected-event-no-user';\n }\n return `pace-core-selected-event-${userId}`;\n }\n\n // Update dependencies\n async 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 ): Promise<void> {\n const previousOrgId = this.selectedOrganisation?.id;\n const newOrgId = selectedOrganisation?.id;\n const previousUserId = this.user?.id || null;\n const newUserId = user?.id || null;\n \n // If user changed, clear previous user's event selection from storage\n if (previousUserId !== newUserId) {\n if (previousUserId !== null) {\n await this.clearEventSelectionForUser(previousUserId);\n }\n // If user is now null (logout), clear current selection state\n if (newUserId === null) {\n this.selectedEvent = null;\n this.setSelectedEventId?.(null);\n }\n }\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 ONLY when switching between different organisations (not when org first becomes available)\n if (previousOrgId !== null && newOrgId !== null && previousOrgId !== newOrgId) {\n this.events = [];\n this.selectedEvent = null;\n } else if (previousOrgId !== null && newOrgId === null) {\n // Organisation was removed - clear events\n this.events = [];\n this.selectedEvent = null;\n }\n }\n \n this.notify();\n }\n\n // Event state getters\n getEvents(): Event[] {\n // Return a new array reference so React can detect changes\n // This ensures useMemo dependencies work correctly\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 if (this.selectedOrganisation && event.organisation_id !== this.selectedOrganisation.id) {\n logger.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 logger.error('EventService', 'Error during event validation:', error);\n }\n\n this.selectedEvent = event;\n this.setSelectedEventId?.(event.event_id);\n // Persist asynchronously (don't await to avoid blocking)\n this.persistEventSelection(event.event_id).catch(error => {\n logger.warn('EventService', 'Failed to persist event selection:', error);\n });\n // Reset the user cleared flag when selecting an event\n this.userClearedEventRef = false;\n } else {\n this.selectedEvent = null;\n this.setSelectedEventId?.(null);\n // Clear from secure storage (don't await to avoid blocking)\n this.clearEventSelection().catch(error => {\n logger.warn('EventService', 'Failed to clear event selection:', error);\n });\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 }\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 const userId = this.user?.id || null;\n \n // Don't load persisted event if no user is authenticated\n if (!userId) {\n return false;\n }\n \n const storageKey = this.getStorageKey(userId);\n \n // Retrieve from secure storage (will automatically decrypt)\n const persistedEventId = await secureStorage.getItem(storageKey);\n \n if (persistedEventId && events.length > 0) {\n // Validate that event exists in user's accessible events\n const persistedEvent = events.find(event => event.event_id === persistedEventId);\n \n if (persistedEvent) {\n // Use setSelectedEvent() to go through same path as EventSelector\n // This ensures consistent behavior and proper notification\n // Theme will be applied by useEventTheme hook once user navigates away from login\n this.setSelectedEvent(persistedEvent);\n return true;\n } else {\n // Event no longer accessible to user, clear invalid persisted event\n await secureStorage.removeItem(storageKey);\n }\n }\n } catch (error) {\n logger.warn('EventService', 'Failed to load persisted event:', error);\n }\n return false;\n }\n\n /**\n * Restore persisted event after login screen has rendered\n * This should be called explicitly from login page component\n * \n * @returns Promise<boolean> - true if event was successfully restored, false otherwise\n */\n async restorePersistedEvent(): Promise<boolean> {\n if (this.events.length === 0) {\n // Events haven't been fetched yet, wait for them\n return false;\n }\n return await this.loadPersistedEvent(this.events);\n }\n\n async persistEventSelection(eventId: string): Promise<void> {\n try {\n const userId = this.user?.id || null;\n const storageKey = this.getStorageKey(userId);\n \n // Store with encryption using secureStorage\n await secureStorage.setItem(storageKey, eventId, { encrypt: true });\n } catch (error) {\n logger.warn('EventService', 'Failed to persist event selection:', error);\n }\n }\n\n async clearEventSelection(): Promise<void> {\n try {\n const userId = this.user?.id || null;\n const storageKey = this.getStorageKey(userId);\n \n // Clear from secure storage\n await secureStorage.removeItem(storageKey);\n \n // Clear the selected event\n this.selectedEvent = null;\n this.setSelectedEventId?.(null);\n } catch (error) {\n logger.warn('EventService', 'Failed to clear event selection:', error);\n }\n }\n\n /**\n * Clear event selection for a specific user (used when user logs out or changes)\n */\n async clearEventSelectionForUser(userId: string | null): Promise<void> {\n try {\n if (!userId) return;\n \n const storageKey = this.getStorageKey(userId);\n await secureStorage.removeItem(storageKey);\n } catch (error) {\n logger.warn('EventService', 'Failed to clear event selection for user:', error);\n }\n }\n\n autoSelectNextEvent(events: Event[]): void {\n const nextEvent = this.getNextEventByDate(events);\n if (nextEvent) {\n // Use setSelectedEvent() to ensure consistent behavior\n // Theme will be applied by useEventTheme() hook\n this.setSelectedEvent(nextEvent);\n }\n }\n\n // Lifecycle methods\n async initialize(): Promise<void> {\n // Only call super.initialize() which will call doInitialize() and fetchEvents()\n // Don't call fetchEvents() again here to avoid double-fetching\n await super.initialize();\n }\n\n cleanup(): void {\n super.cleanup();\n }\n\n protected async doInitialize(): Promise<void> {\n // Skip if already initialized\n if (this.isInitializedRef) {\n return;\n }\n \n // Skip if already fetching\n if (this.isFetchingRef) {\n return;\n }\n \n // Clean up old storage keys (migration from old key format)\n try {\n sessionStorage.removeItem('pace-core-selected-event');\n localStorage.removeItem('pace-core-selected-event');\n localStorage.removeItem('_sec_pace-core-selected-event');\n } catch (error) {\n logger.warn('EventService', 'Failed to clean up old storage keys:', error);\n }\n \n // Skip if no user or organisation\n if (!this.user || !this.selectedOrganisation) {\n return;\n }\n \n // Initial setup - fetch events on initialization\n await this.fetchEvents(false);\n }\n\n protected doCleanup(): void {\n // Cleanup any resources\n }\n\n private async fetchEvents(skipLoadPersisted: boolean = false): 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 logger.error('EventService', 'RPC error fetching events:', rpcError);\n throw new Error(rpcError.message || 'Failed to fetch events');\n }\n\n if (isMounted) {\n const eventsData = data || [];\n\n // Transform the data to match our Event interface\n // Type for RPC response from data_user_events_get\n interface EventRpcResponse {\n event_id: string;\n event_name: string;\n event_code: string;\n event_date: string | null;\n event_venue: string | null;\n event_participants: number | null;\n event_colours: Record<string, unknown> | null;\n organisation_id: string;\n is_visible: boolean;\n }\n \n const transformedEvents: Event[] = eventsData.map((event: EventRpcResponse) => ({\n id: event.event_id,\n event_id: event.event_id,\n event_name: event.event_name,\n event_code: event.event_code,\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: assertOrganisationId(event.organisation_id),\n is_visible: event.is_visible,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString()\n }));\n\n this.events = transformedEvents;\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 (only if not skipping)\n if (!skipLoadPersisted) {\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 // Use setSelectedEvent() to ensure consistent behavior\n // Theme will be applied by useEventTheme() hook\n this.setSelectedEvent(nextEvent);\n }\n }\n } else {\n // If skipping persisted event load, still do auto-selection for new users\n if (!this.userClearedEventRef) {\n const nextEvent = this.getNextEventByDate(transformedEvents);\n if (nextEvent) {\n this.hasAutoSelectedRef = true;\n // Use setSelectedEvent() to ensure consistent behavior\n // Theme will be applied by useEventTheme() hook\n this.setSelectedEvent(nextEvent);\n }\n }\n }\n }\n } catch (err) {\n logger.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 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 // 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 // Fallback: If no future events found, return the most recent past event\n // This handles cases where users only have access to past events\n const pastEvents = eventsToUse.filter(event => {\n if (!event.event_date) return false;\n const eventDate = new Date(event.event_date);\n const startOfEventDate = new Date(eventDate.getFullYear(), eventDate.getMonth(), eventDate.getDate()).getTime();\n return startOfEventDate < startOfToday;\n });\n\n if (pastEvents.length > 0) {\n // Sort by date (descending) to get the most recent past event\n const sortedPastEvents = pastEvents.sort((a, b) => {\n const dateA = new Date(a.event_date!);\n const dateB = new Date(b.event_date!);\n return dateB.getTime() - dateA.getTime(); // Descending order\n });\n\n return sortedPastEvents[0];\n }\n\n // No events found at all\n return null;\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, useMemo, useEffect, useRef } from 'react';\nimport { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';\nimport { InactivityService } from '../../services/InactivityService';\nimport { logger } from '../../utils/core/logger';\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 logger.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 // Cleanup service on unmount only\n useEffect(() => {\n return () => {\n inactivityService.cleanup();\n };\n }, [inactivityService]);\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 * @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 { type SupabaseClient, type User, type Session } from '@supabase/supabase-js';\nimport { BaseService } from './base/BaseService';\nimport { IInactivityService } from './interfaces/IInactivityService';\nimport { logger } from '../utils/core/logger';\n\ninterface InactivityTracker {\n isIdle: boolean;\n timeRemaining: number;\n showWarning: boolean;\n isTracking: boolean;\n resetActivity: () => void;\n startTracking: () => void;\n stopTracking: () => void;\n cleanup?: () => void;\n}\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: SupabaseClient | null = null;\n private user: User | null = null;\n private session: Session | null = 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: InactivityTracker | null = null;\n private isInactivityEnabled = true;\n private cleanupHandlers: (() => void) | null = null;\n\n constructor(\n supabaseClient: SupabaseClient | null,\n user: User | null,\n session: Session | null,\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: SupabaseClient | null,\n user: User | null,\n session: Session | null,\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) {\n logger.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) {\n logger.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.cleanupHandlers) {\n this.cleanupHandlers();\n this.cleanupHandlers = null;\n }\n if (this.inactivityTracker) {\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 logger.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 // Set up event handlers directly (no need to import hooks - services are pure TypeScript)\n this.setupEventHandlers();\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.cleanupHandlers = () => {\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 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';\nimport { createLogger } from '../utils/core/logger';\n\nconst log = createLogger('useSessionRestoration');\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 log.warn('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"],"mappings":"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","names":["createContext","useContext","useMemo","useRef","useEffect","useState","useReducer","error","createContext","useMemo","useEffect","jsx","createContext","useEffect","useMemo","createContext","useMemo","useEffect","useRef","jsx","createContext","useRef","useEffect","useMemo","createContext","useMemo","useEffect","useRef","jsx","createContext","useRef","useEffect","useMemo","useEffect","useEffect","useContext","useReducer","useEffect","useContext","useReducer","useEffect","useContext","useReducer","useEffect","useContext","useReducer","useEffect","useContext","useReducer","useEffect","useContext","useReducer","useEffect","useContext","useMemo","useEffect","useState","useContext","useState","useEffect","useMemo","jsx","createContext","useContext","useMemo","useState","useRef","useEffect","useReducer"]}
|