@jmruthers/pace-core 0.6.4 → 0.6.6
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 +104 -0
- package/README.md +5 -403
- package/core-usage-manifest.json +93 -0
- package/cursor-rules/00-pace-core-compliance.mdc +128 -26
- package/cursor-rules/01-standards-compliance.mdc +49 -8
- package/cursor-rules/02-project-structure.mdc +6 -0
- package/cursor-rules/03-solid-principles.mdc +2 -0
- package/cursor-rules/04-testing-standards.mdc +2 -0
- package/cursor-rules/05-bug-reports-and-features.mdc +2 -0
- package/cursor-rules/06-code-quality.mdc +2 -0
- package/cursor-rules/07-tech-stack-compliance.mdc +2 -0
- package/cursor-rules/08-markup-quality.mdc +52 -27
- package/cursor-rules/09-rbac-compliance.mdc +462 -0
- package/cursor-rules/10-error-handling-patterns.mdc +179 -0
- package/cursor-rules/11-performance-optimization.mdc +169 -0
- package/cursor-rules/12-ci-cd-integration.mdc +150 -0
- package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
- package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-2N_tqbfq.d.ts} +1 -1
- package/dist/DataTable-LRJL4IRV.js +15 -0
- package/dist/{PublicPageProvider-DEMpysFR.d.ts → PublicPageProvider-BBH6Vqg7.d.ts} +72 -139
- package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
- package/dist/api-Y4MQWOFW.js +4 -0
- package/dist/audit-MYQXYZFU.js +3 -0
- package/dist/{chunk-J36DSWQK.js → chunk-2HGJFNAH.js} +8 -28
- package/dist/{chunk-OEWDTMG7.js → chunk-3O3WHILE.js} +38 -121
- package/dist/{chunk-M43Y4SSO.js → chunk-3QC3KRHK.js} +1 -14
- package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
- package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
- package/dist/chunk-4T7OBVTU.js +62 -0
- package/dist/{chunk-E66EQZE6.js → chunk-6GLLNA6U.js} +3 -9
- package/dist/{chunk-ZSAAAMVR.js → chunk-6QYDGKQY.js} +1 -4
- package/dist/{chunk-NN6WWZ5U.js → chunk-7TYHROIV.js} +579 -563
- package/dist/{chunk-M7MPQISP.js → chunk-A55DK444.js} +9 -16
- package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
- package/dist/{chunk-L4OXEN46.js → chunk-BVP2BCJF.js} +2 -16
- package/dist/chunk-C7NSAPTL.js +1 -0
- package/dist/{chunk-YKRAFF5K.js → chunk-FENMYN2U.js} +73 -149
- package/dist/{chunk-AVMLPIM7.js → chunk-FTCRZOG2.js} +284 -432
- package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
- package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
- package/dist/{chunk-I6DAQMWX.js → chunk-LAZMKTTF.js} +930 -891
- package/dist/{chunk-5EC5MEWX.js → chunk-MAGBIDNS.js} +77 -222
- package/dist/chunk-MBADTM7L.js +64 -0
- package/dist/chunk-OHIK3MIO.js +994 -0
- package/dist/{chunk-6SOIHG6Z.js → chunk-S7DKJPLT.js} +115 -44
- package/dist/{chunk-FMUCXFII.js → chunk-SD6WQY43.js} +1 -5
- package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
- package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
- package/dist/{chunk-FFQEQTNW.js → chunk-UIYSCEV7.js} +134 -45
- package/dist/{chunk-3LPHPB62.js → chunk-ZFYPMX46.js} +271 -87
- package/dist/{chunk-7JPAB3T5.js → chunk-ZS5VO5JB.js} +1989 -1283
- package/dist/components.d.ts +6 -6
- package/dist/components.js +57 -267
- package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
- package/dist/eslint-rules/index.cjs +22 -0
- package/dist/eslint-rules/rules/compliance.cjs +348 -0
- package/dist/eslint-rules/rules/components.cjs +113 -0
- package/dist/eslint-rules/rules/imports.cjs +102 -0
- package/dist/eslint-rules/rules/rbac.cjs +790 -0
- package/dist/eslint-rules/utils/helpers.cjs +42 -0
- package/dist/eslint-rules/utils/manifest-loader.cjs +75 -0
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +62 -270
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +1 -0
- package/dist/index.d.ts +36 -26
- package/dist/index.js +87 -690
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +8 -35
- package/dist/rbac/eslint-rules.d.ts +46 -44
- package/dist/rbac/eslint-rules.js +7 -4
- package/dist/rbac/index.d.ts +124 -594
- package/dist/rbac/index.js +14 -207
- package/dist/styles/index.js +2 -12
- package/dist/theming/runtime.js +3 -19
- package/dist/{timezone-CHhWg6b4.d.ts → timezone-BZe_eUxx.d.ts} +175 -1
- package/dist/{types-CkbwOr4Y.d.ts → types-B-K_5VnO.d.ts} +4 -0
- package/dist/types-t9H8qKRw.d.ts +55 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +7 -94
- package/dist/{usePublicRouteParams-i3qtoBgg.d.ts → usePublicRouteParams-COZ28Mvq.d.ts} +9 -9
- package/dist/utils.d.ts +24 -117
- package/dist/utils.js +54 -392
- package/docs/README.md +16 -6
- package/docs/api/README.md +4 -402
- package/docs/api/modules.md +454 -930
- package/docs/api-reference/components.md +3 -1
- package/docs/api-reference/deprecated.md +31 -6
- package/docs/api-reference/rpc-functions.md +78 -3
- package/docs/best-practices/accessibility.md +6 -3
- package/docs/getting-started/cursor-rules.md +3 -23
- package/docs/getting-started/dependencies.md +650 -0
- package/docs/getting-started/installation-guide.md +20 -7
- package/docs/getting-started/quick-start.md +23 -12
- package/docs/implementation-guides/permission-enforcement.md +4 -0
- package/docs/rbac/MIGRATION_GUIDE.md +819 -0
- package/docs/rbac/RBAC_CONTRACT.md +724 -0
- package/docs/rbac/README.md +12 -3
- package/docs/rbac/edge-functions-guide.md +376 -0
- package/docs/rbac/secure-client-protection.md +0 -34
- package/docs/standards/00-pace-core-compliance.md +967 -0
- package/docs/standards/01-standards-compliance.md +188 -0
- package/docs/standards/02-project-structure.md +985 -0
- package/docs/standards/03-solid-principles.md +39 -0
- package/docs/standards/04-testing-standards.md +36 -0
- package/docs/standards/05-bug-reports-and-features.md +27 -0
- package/docs/standards/{04-code-style-standard.md → 06-code-quality.md} +2 -0
- package/docs/standards/07-tech-stack-compliance.md +30 -0
- package/docs/standards/08-markup-quality.md +345 -0
- package/docs/standards/{07-rbac-and-rls-standard.md → 09-rbac-compliance.md} +149 -54
- package/docs/standards/10-error-handling-patterns.md +401 -0
- package/docs/standards/11-performance-optimization.md +348 -0
- package/docs/standards/12-ci-cd-integration.md +370 -0
- package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +192 -0
- package/docs/standards/README.md +62 -33
- package/docs/troubleshooting/organisation-context-setup.md +42 -19
- package/eslint-config-pace-core.cjs +20 -4
- package/package.json +31 -21
- package/scripts/audit/audit-compliance.cjs +1295 -0
- package/scripts/audit/audit-components.cjs +260 -0
- package/scripts/audit/audit-dependencies.cjs +395 -0
- package/scripts/audit/audit-rbac.cjs +954 -0
- package/scripts/audit/audit-standards.cjs +1268 -0
- package/scripts/audit/index.cjs +1898 -194
- package/scripts/install-cursor-rules.cjs +259 -8
- package/scripts/validate-master.js +1 -1
- package/src/__tests__/fixtures/supabase.ts +1 -1
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +1 -1
- package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +1 -1
- package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +1 -1
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +3 -3
- package/src/__tests__/helpers/component-test-utils.tsx +1 -1
- package/src/__tests__/helpers/supabaseMock.ts +2 -2
- package/src/__tests__/public-recipe-view.test.ts +38 -9
- package/src/components/Button/Button.tsx +5 -1
- package/src/components/ContextSelector/ContextSelector.tsx +42 -39
- package/src/components/DataTable/__tests__/keyboard.test.tsx +15 -2
- package/src/components/DataTable/components/DataTableBody.tsx +55 -31
- package/src/components/DataTable/components/DataTableCore.tsx +186 -13
- package/src/components/DataTable/components/DataTableLayout.tsx +30 -5
- package/src/components/DataTable/components/EditFields.tsx +23 -3
- package/src/components/DataTable/components/EditableRow.tsx +7 -2
- package/src/components/DataTable/components/ImportModal.tsx +4 -6
- package/src/components/DataTable/components/RowComponent.tsx +12 -0
- package/src/components/DataTable/components/ViewRowModal.tsx +4 -4
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +455 -96
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +122 -58
- package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
- package/src/components/DataTable/core/DataTableContext.tsx +1 -1
- package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +51 -47
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +24 -21
- package/src/components/DataTable/hooks/useDataTableState.ts +125 -9
- package/src/components/DataTable/hooks/useTableColumns.ts +40 -2
- package/src/components/DataTable/hooks/useTableHandlers.ts +11 -0
- package/src/components/DataTable/types.ts +5 -0
- package/src/components/DateTimeField/DateTimeField.tsx +20 -20
- package/src/components/DateTimeField/README.md +5 -2
- package/src/components/Dialog/Dialog.test.tsx +361 -318
- package/src/components/Dialog/Dialog.tsx +1154 -323
- package/src/components/Dialog/index.ts +3 -3
- package/src/components/FileDisplay/FileDisplay.test.tsx +45 -2
- package/src/components/FileDisplay/FileDisplay.tsx +28 -22
- package/src/components/Form/Form.test.tsx +9 -10
- package/src/components/Form/Form.tsx +369 -9
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +28 -28
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +40 -54
- package/src/components/LoginForm/LoginForm.tsx +2 -2
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
- package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
- package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +30 -41
- package/src/components/PaceAppLayout/README.md +10 -9
- package/src/components/PaceAppLayout/test-setup.tsx +40 -31
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +61 -0
- package/src/components/PasswordChange/PasswordChangeForm.tsx +20 -13
- package/src/components/PublicLayout/PublicLayout.test.tsx +7 -3
- package/src/components/PublicLayout/PublicPageLayout.tsx +5 -8
- package/src/components/Select/Select.tsx +23 -21
- package/src/components/Select/types.ts +1 -1
- package/src/components/UserMenu/UserMenu.test.tsx +38 -6
- package/src/components/UserMenu/UserMenu.tsx +39 -34
- package/src/components/index.ts +3 -4
- package/src/eslint-rules/index.cjs +22 -0
- package/src/eslint-rules/rules/compliance.cjs +348 -0
- package/src/eslint-rules/rules/components.cjs +113 -0
- package/src/eslint-rules/rules/imports.cjs +102 -0
- package/src/eslint-rules/rules/rbac.cjs +790 -0
- package/src/eslint-rules/utils/helpers.cjs +42 -0
- package/src/eslint-rules/utils/manifest-loader.cjs +75 -0
- package/src/hooks/__tests__/hooks.integration.test.tsx +6 -8
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +149 -67
- package/src/hooks/__tests__/usePublicEvent.test.ts +149 -79
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +158 -109
- package/src/hooks/__tests__/useSessionDraft.test.ts +163 -0
- package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +10 -5
- package/src/hooks/public/usePublicEvent.ts +62 -190
- package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
- package/src/hooks/public/usePublicEventLogo.ts +19 -9
- package/src/hooks/useAppConfig.ts +26 -24
- package/src/hooks/useEventTheme.test.ts +211 -233
- package/src/hooks/useEventTheme.ts +19 -28
- package/src/hooks/useEvents.ts +11 -7
- package/src/hooks/useKeyboardShortcuts.ts +1 -1
- package/src/hooks/useOrganisationPermissions.ts +9 -11
- package/src/hooks/useOrganisations.ts +13 -7
- package/src/hooks/useQueryCache.ts +0 -1
- package/src/hooks/useSessionDraft.ts +380 -0
- package/src/hooks/useSessionRestoration.ts +3 -1
- package/src/icons/index.ts +27 -0
- package/src/index.ts +16 -1
- package/src/providers/OrganisationProvider.tsx +23 -14
- package/src/providers/services/EventServiceProvider.tsx +1 -24
- package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -0
- package/src/rbac/README.md +20 -20
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +7 -457
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +33 -7
- package/src/rbac/adapters.tsx +7 -295
- package/src/rbac/api.test.ts +44 -56
- package/src/rbac/api.ts +10 -17
- package/src/rbac/cache-invalidation.ts +0 -1
- package/src/rbac/compliance/index.ts +10 -0
- package/src/rbac/compliance/pattern-detector.ts +553 -0
- package/src/rbac/compliance/runtime-compliance.ts +22 -0
- package/src/rbac/components/AccessDenied.tsx +150 -0
- package/src/rbac/components/NavigationGuard.tsx +12 -20
- package/src/rbac/components/PagePermissionGuard.tsx +4 -24
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +21 -8
- package/src/rbac/components/index.ts +3 -41
- package/src/rbac/eslint-rules.js +1 -1
- package/src/rbac/hooks/index.ts +0 -3
- package/src/rbac/hooks/permissions/index.ts +0 -3
- package/src/rbac/hooks/permissions/useAccessLevel.ts +4 -8
- package/src/rbac/hooks/usePermissions.ts +0 -3
- package/src/rbac/hooks/useRBAC.test.ts +21 -3
- package/src/rbac/hooks/useRBAC.ts +4 -3
- package/src/rbac/hooks/useResolvedScope.test.ts +57 -47
- package/src/rbac/hooks/useResolvedScope.ts +58 -140
- package/src/rbac/hooks/useResourcePermissions.test.ts +241 -60
- package/src/rbac/hooks/useResourcePermissions.ts +182 -63
- package/src/rbac/hooks/useRoleManagement.test.ts +65 -22
- package/src/rbac/hooks/useRoleManagement.ts +147 -19
- package/src/rbac/hooks/useSecureSupabase.ts +4 -8
- package/src/rbac/index.ts +7 -9
- package/src/rbac/permissions.ts +17 -17
- package/src/rbac/utils/contextValidator.ts +45 -7
- package/src/services/AuthService.ts +132 -23
- package/src/services/EventService.ts +4 -97
- package/src/services/InactivityService.ts +155 -58
- package/src/services/OrganisationService.ts +7 -44
- package/src/services/__tests__/OrganisationService.test.ts +26 -8
- package/src/services/base/BaseService.ts +0 -3
- package/src/styles/core.css +4 -0
- package/src/types/database.generated.ts +4733 -3809
- package/src/utils/__tests__/organisationContext.unit.test.ts +9 -10
- package/src/utils/context/organisationContext.test.ts +13 -28
- package/src/utils/context/organisationContext.ts +21 -52
- package/src/utils/dynamic/dynamicUtils.ts +1 -1
- package/src/utils/file-reference/index.ts +39 -15
- package/src/utils/formatting/formatDateTime.test.ts +3 -2
- package/src/utils/formatting/formatTime.test.ts +3 -2
- package/src/utils/google-places/loadGoogleMapsScript.ts +29 -4
- package/src/utils/index.ts +4 -1
- package/src/utils/persistence/__tests__/keyDerivation.test.ts +135 -0
- package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +123 -0
- package/src/utils/persistence/keyDerivation.ts +304 -0
- package/src/utils/persistence/sensitiveFieldDetection.ts +212 -0
- package/src/utils/security/secureStorage.ts +5 -5
- package/src/utils/storage/helpers.ts +3 -3
- package/src/utils/supabase/createBaseClient.ts +147 -0
- package/src/utils/timezone/timezone.test.ts +1 -2
- package/src/utils/timezone/timezone.ts +1 -1
- package/src/utils/validation/csrf.ts +4 -4
- package/cursor-rules/CHANGELOG.md +0 -119
- package/cursor-rules/README.md +0 -192
- package/dist/DataTable-E7YQZD7D.js +0 -175
- package/dist/DataTable-E7YQZD7D.js.map +0 -1
- package/dist/UnifiedAuthProvider-QPXO24B4.js +0 -18
- package/dist/UnifiedAuthProvider-QPXO24B4.js.map +0 -1
- package/dist/api-6LVZTHDS.js +0 -52
- package/dist/api-6LVZTHDS.js.map +0 -1
- package/dist/audit-V53FV5AG.js +0 -17
- package/dist/audit-V53FV5AG.js.map +0 -1
- package/dist/chunk-36LVWXB2.js +0 -227
- package/dist/chunk-36LVWXB2.js.map +0 -1
- package/dist/chunk-3LPHPB62.js.map +0 -1
- package/dist/chunk-5DRSZLL2.js.map +0 -1
- package/dist/chunk-5EC5MEWX.js.map +0 -1
- package/dist/chunk-63FOKYGO.js.map +0 -1
- package/dist/chunk-6SOIHG6Z.js.map +0 -1
- package/dist/chunk-7JPAB3T5.js.map +0 -1
- package/dist/chunk-ATKZM7RX.js +0 -2053
- package/dist/chunk-ATKZM7RX.js.map +0 -1
- package/dist/chunk-AVMLPIM7.js.map +0 -1
- package/dist/chunk-DGUM43GV.js.map +0 -1
- package/dist/chunk-E66EQZE6.js.map +0 -1
- package/dist/chunk-FFQEQTNW.js.map +0 -1
- package/dist/chunk-FMUCXFII.js.map +0 -1
- package/dist/chunk-G37KK66H.js.map +0 -1
- package/dist/chunk-I6DAQMWX.js.map +0 -1
- package/dist/chunk-J36DSWQK.js.map +0 -1
- package/dist/chunk-KQCRWDSA.js +0 -1
- package/dist/chunk-KQCRWDSA.js.map +0 -1
- package/dist/chunk-L4OXEN46.js.map +0 -1
- package/dist/chunk-LMC26NLJ.js +0 -84
- package/dist/chunk-LMC26NLJ.js.map +0 -1
- package/dist/chunk-M43Y4SSO.js.map +0 -1
- package/dist/chunk-M7MPQISP.js.map +0 -1
- package/dist/chunk-NN6WWZ5U.js.map +0 -1
- package/dist/chunk-OEWDTMG7.js.map +0 -1
- package/dist/chunk-PWLANIRT.js.map +0 -1
- package/dist/chunk-QXHPKYJV.js.map +0 -1
- package/dist/chunk-VBXEHIUJ.js.map +0 -1
- package/dist/chunk-YKRAFF5K.js.map +0 -1
- package/dist/chunk-ZSAAAMVR.js.map +0 -1
- package/dist/components.js.map +0 -1
- package/dist/contextValidator-OOPCLPZW.js +0 -9
- package/dist/contextValidator-OOPCLPZW.js.map +0 -1
- package/dist/eslint-rules/pace-core-compliance.cjs +0 -510
- package/dist/hooks.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/providers.js.map +0 -1
- package/dist/rbac/eslint-rules.js.map +0 -1
- package/dist/rbac/index.js.map +0 -1
- package/dist/styles/index.js.map +0 -1
- package/dist/theming/runtime.js.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils.js.map +0 -1
- package/docs/standards/01-architecture-standard.md +0 -44
- package/docs/standards/02-api-and-rpc-standard.md +0 -39
- package/docs/standards/03-component-standard.md +0 -32
- package/docs/standards/05-security-standard.md +0 -44
- package/docs/standards/06-testing-and-docs-standard.md +0 -29
- package/docs/standards/pace-core-compliance.md +0 -432
- package/scripts/audit/core/checks/accessibility.cjs +0 -197
- package/scripts/audit/core/checks/api-usage.cjs +0 -191
- package/scripts/audit/core/checks/bundle.cjs +0 -142
- package/scripts/audit/core/checks/compliance.cjs +0 -2706
- package/scripts/audit/core/checks/config.cjs +0 -54
- package/scripts/audit/core/checks/coverage.cjs +0 -84
- package/scripts/audit/core/checks/dependencies.cjs +0 -994
- package/scripts/audit/core/checks/documentation.cjs +0 -268
- package/scripts/audit/core/checks/environment.cjs +0 -116
- package/scripts/audit/core/checks/error-handling.cjs +0 -340
- package/scripts/audit/core/checks/forms.cjs +0 -172
- package/scripts/audit/core/checks/heuristics.cjs +0 -68
- package/scripts/audit/core/checks/hooks.cjs +0 -334
- package/scripts/audit/core/checks/imports.cjs +0 -244
- package/scripts/audit/core/checks/performance.cjs +0 -325
- package/scripts/audit/core/checks/routes.cjs +0 -117
- package/scripts/audit/core/checks/state.cjs +0 -130
- package/scripts/audit/core/checks/structure.cjs +0 -65
- package/scripts/audit/core/checks/style.cjs +0 -584
- package/scripts/audit/core/checks/testing.cjs +0 -122
- package/scripts/audit/core/checks/typescript.cjs +0 -61
- package/scripts/audit/core/scanner.cjs +0 -199
- package/scripts/audit/core/utils.cjs +0 -137
- package/scripts/audit/reporters/console.cjs +0 -151
- package/scripts/audit/reporters/json.cjs +0 -54
- package/scripts/audit/reporters/markdown.cjs +0 -124
- package/scripts/audit-consuming-app.cjs +0 -86
- package/src/eslint-rules/pace-core-compliance.cjs +0 -510
- package/src/eslint-rules/pace-core-compliance.js +0 -638
- package/src/rbac/components/EnhancedNavigationMenu.test.tsx +0 -555
- package/src/rbac/components/EnhancedNavigationMenu.tsx +0 -293
- package/src/rbac/components/NavigationProvider.test.tsx +0 -481
- package/src/rbac/components/NavigationProvider.tsx +0 -345
- package/src/rbac/components/PagePermissionProvider.test.tsx +0 -476
- package/src/rbac/components/PagePermissionProvider.tsx +0 -279
- package/src/rbac/components/PermissionEnforcer.tsx +0 -312
- package/src/rbac/components/RoleBasedRouter.tsx +0 -440
- package/src/rbac/components/SecureDataProvider.test.tsx +0 -543
- package/src/rbac/components/SecureDataProvider.tsx +0 -339
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -620
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -726
- package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -661
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +0 -881
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +0 -783
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +0 -645
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -659
- package/src/rbac/hooks/permissions/useCachedPermissions.ts +0 -79
- package/src/rbac/hooks/permissions/useHasAllPermissions.ts +0 -90
- package/src/rbac/hooks/permissions/useHasAnyPermission.ts +0 -90
|
@@ -1,28 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "./chunk-QXHPKYJV.js";
|
|
9
|
-
import {
|
|
10
|
-
secureStorage,
|
|
11
|
-
setOrganisationContext
|
|
12
|
-
} from "./chunk-VBXEHIUJ.js";
|
|
13
|
-
import {
|
|
14
|
-
createLogger,
|
|
15
|
-
logger
|
|
16
|
-
} from "./chunk-PWLANIRT.js";
|
|
17
|
-
|
|
18
|
-
// src/providers/services/UnifiedAuthProvider.tsx
|
|
19
|
-
import { createContext as createContext5, useContext as useContext6, useMemo as useMemo6, useCallback, useRef as useRef9, useEffect as useEffect10, useState as useState3, useReducer as useReducer5 } from "react";
|
|
20
|
-
|
|
21
|
-
// src/providers/services/AuthServiceProvider.tsx
|
|
22
|
-
import { createContext, useMemo, useEffect, useState, useRef } from "react";
|
|
23
|
-
|
|
24
|
-
// src/services/AuthService.ts
|
|
25
|
-
import { AuthError } from "@supabase/supabase-js";
|
|
1
|
+
import { isRBACInitialized, setupRBAC } from './chunk-ZFYPMX46.js';
|
|
2
|
+
import { assertOrganisationId, assertUserId } from './chunk-4SXLQIZO.js';
|
|
3
|
+
import { secureStorage } from './chunk-HF6O3O37.js';
|
|
4
|
+
import { createLogger, logger } from './chunk-TTRFSOKR.js';
|
|
5
|
+
import { createContext, useRef, useEffect, useState, useMemo, useContext, useReducer, useCallback } from 'react';
|
|
6
|
+
import { AuthError } from '@supabase/supabase-js';
|
|
7
|
+
import { jsx } from 'react/jsx-runtime';
|
|
26
8
|
|
|
27
9
|
// src/services/base/BaseService.ts
|
|
28
10
|
var BaseService = class {
|
|
@@ -49,9 +31,6 @@ var BaseService = class {
|
|
|
49
31
|
* This triggers React re-renders
|
|
50
32
|
*/
|
|
51
33
|
notify() {
|
|
52
|
-
const serviceName = this.constructor.name;
|
|
53
|
-
const instanceId = this.instanceId || "unknown";
|
|
54
|
-
logger.debug("BaseService", `[${serviceName} ID:${instanceId}] Notifying ${this.subscribers.length} subscribers`);
|
|
55
34
|
this.subscribers.forEach((callback) => {
|
|
56
35
|
try {
|
|
57
36
|
callback();
|
|
@@ -97,6 +76,7 @@ var BaseService = class {
|
|
|
97
76
|
|
|
98
77
|
// src/services/AuthService.ts
|
|
99
78
|
var _AuthService = class _AuthService extends BaseService {
|
|
79
|
+
// Track previous auth state to detect transitions
|
|
100
80
|
constructor(supabaseClient, appName) {
|
|
101
81
|
super();
|
|
102
82
|
this.user = null;
|
|
@@ -111,26 +91,24 @@ var _AuthService = class _AuthService extends BaseService {
|
|
|
111
91
|
restorationError: null
|
|
112
92
|
};
|
|
113
93
|
this.restorationTimeoutId = null;
|
|
114
|
-
|
|
94
|
+
// Increased timeout to handle hard refresh scenarios where localStorage access
|
|
95
|
+
// and session restoration may take longer, especially with organisation/event context
|
|
96
|
+
this.restorationTimeoutMs = 1e4;
|
|
97
|
+
// 10 seconds (increased from 5)
|
|
115
98
|
this.restorationStartTime = null;
|
|
116
99
|
this.appName = void 0;
|
|
117
100
|
this.errorHandler = null;
|
|
118
101
|
this.unhandledRejectionHandler = null;
|
|
102
|
+
this.wasAuthenticatedRef = false;
|
|
119
103
|
this.instanceId = ++_AuthService.instanceCount;
|
|
120
104
|
this.supabaseClient = supabaseClient;
|
|
121
105
|
this.appName = appName;
|
|
122
|
-
logger.debug("AuthService", `Instance created [ID:${this.instanceId}]`, { appName });
|
|
123
106
|
}
|
|
124
107
|
getInstanceId() {
|
|
125
108
|
return this.instanceId;
|
|
126
109
|
}
|
|
127
110
|
// Auth state getters
|
|
128
111
|
getUser() {
|
|
129
|
-
if (this.user) {
|
|
130
|
-
logger.debug("AuthService", `getUser() [ID:${this.instanceId}] returning user: ${this.user.id}`);
|
|
131
|
-
} else {
|
|
132
|
-
logger.debug("AuthService", `getUser() [ID:${this.instanceId}] returning null`);
|
|
133
|
-
}
|
|
134
112
|
return this.user;
|
|
135
113
|
}
|
|
136
114
|
getSession() {
|
|
@@ -172,6 +150,10 @@ var _AuthService = class _AuthService extends BaseService {
|
|
|
172
150
|
this.authError = null;
|
|
173
151
|
this.user = data.user;
|
|
174
152
|
this.session = data.session;
|
|
153
|
+
if (!this.wasAuthenticatedRef && data.user) {
|
|
154
|
+
this.clearPersistenceOnLogin(null, true);
|
|
155
|
+
this.wasAuthenticatedRef = true;
|
|
156
|
+
}
|
|
175
157
|
}
|
|
176
158
|
this.notify();
|
|
177
159
|
return { user: data.user, session: data.session, error };
|
|
@@ -204,6 +186,10 @@ var _AuthService = class _AuthService extends BaseService {
|
|
|
204
186
|
this.authError = null;
|
|
205
187
|
this.user = data.user;
|
|
206
188
|
this.session = data.session;
|
|
189
|
+
if (!this.wasAuthenticatedRef && data.user) {
|
|
190
|
+
this.clearPersistenceOnLogin(null, true);
|
|
191
|
+
this.wasAuthenticatedRef = true;
|
|
192
|
+
}
|
|
207
193
|
}
|
|
208
194
|
this.notify();
|
|
209
195
|
return { user: data.user, session: data.session, error };
|
|
@@ -225,6 +211,11 @@ var _AuthService = class _AuthService extends BaseService {
|
|
|
225
211
|
}
|
|
226
212
|
try {
|
|
227
213
|
const { error } = await this.supabaseClient.auth.signOut();
|
|
214
|
+
try {
|
|
215
|
+
sessionStorage.clear();
|
|
216
|
+
} catch (storageError) {
|
|
217
|
+
logger.warn("AuthService", "Failed to clear sessionStorage", { error: storageError });
|
|
218
|
+
}
|
|
228
219
|
if (error) {
|
|
229
220
|
this.authError = error;
|
|
230
221
|
} else {
|
|
@@ -235,6 +226,11 @@ var _AuthService = class _AuthService extends BaseService {
|
|
|
235
226
|
this.notify();
|
|
236
227
|
return { user: null, session: null, error };
|
|
237
228
|
} catch (error) {
|
|
229
|
+
try {
|
|
230
|
+
sessionStorage.clear();
|
|
231
|
+
} catch (storageError) {
|
|
232
|
+
logger.warn("AuthService", "Failed to clear sessionStorage", { error: storageError });
|
|
233
|
+
}
|
|
238
234
|
const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
|
|
239
235
|
this.authError = authError;
|
|
240
236
|
this.user = null;
|
|
@@ -381,7 +377,7 @@ var _AuthService = class _AuthService extends BaseService {
|
|
|
381
377
|
}
|
|
382
378
|
this.clearRestorationTimeout();
|
|
383
379
|
const completedAt = Date.now();
|
|
384
|
-
|
|
380
|
+
this.restorationStartTime ? completedAt - this.restorationStartTime : null;
|
|
385
381
|
this.restorationStartTime = null;
|
|
386
382
|
const restorationComplete = !error;
|
|
387
383
|
this.sessionRestorationState = {
|
|
@@ -401,6 +397,43 @@ var _AuthService = class _AuthService extends BaseService {
|
|
|
401
397
|
this.restorationTimeoutId = null;
|
|
402
398
|
}
|
|
403
399
|
}
|
|
400
|
+
/**
|
|
401
|
+
* Clear pace-core persistence entries from sessionStorage
|
|
402
|
+
* This includes dialog, form, and datatable persistence
|
|
403
|
+
*
|
|
404
|
+
* @param userId - Optional user ID to clear only that user's persistence.
|
|
405
|
+
* If not provided, clears all pace-core persistence (for user changes).
|
|
406
|
+
* @param clearUnscoped - If true, also clears old unscoped keys (without :user: prefix)
|
|
407
|
+
*/
|
|
408
|
+
clearPersistenceOnLogin(userId, clearUnscoped = true) {
|
|
409
|
+
if (typeof window === "undefined" || !window.sessionStorage) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
try {
|
|
413
|
+
const keysToRemove = [];
|
|
414
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
|
415
|
+
const key = sessionStorage.key(i);
|
|
416
|
+
if (key && (key.startsWith("pace-core:draft:") || key.startsWith("pace-core:dialog:"))) {
|
|
417
|
+
if (userId && !key.includes(`:user:${userId}`)) {
|
|
418
|
+
if (clearUnscoped && !key.includes(":user:")) {
|
|
419
|
+
keysToRemove.push(key);
|
|
420
|
+
}
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
keysToRemove.push(key);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
keysToRemove.forEach((key) => {
|
|
427
|
+
try {
|
|
428
|
+
sessionStorage.removeItem(key);
|
|
429
|
+
} catch (error) {
|
|
430
|
+
logger.warn("AuthService", `Failed to remove persistence key: ${key}`, error);
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
} catch (error) {
|
|
434
|
+
logger.warn("AuthService", `Failed to clear persistence [ID:${this.instanceId}]:`, error);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
404
437
|
async setupAuthStateListener() {
|
|
405
438
|
if (!this.supabaseClient) {
|
|
406
439
|
this.authLoading = false;
|
|
@@ -411,15 +444,16 @@ var _AuthService = class _AuthService extends BaseService {
|
|
|
411
444
|
const subscription = this.supabaseClient.auth.onAuthStateChange(
|
|
412
445
|
(event, session) => {
|
|
413
446
|
try {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
447
|
+
const wasAuthenticated = this.wasAuthenticatedRef;
|
|
448
|
+
const isNowAuthenticated = !!session?.user;
|
|
449
|
+
const previousUserId = this.user?.id || null;
|
|
450
|
+
const newUserId = session?.user?.id || null;
|
|
451
|
+
const userChanged = previousUserId !== null && newUserId !== null && previousUserId !== newUserId;
|
|
419
452
|
if (event === "SIGNED_OUT") {
|
|
420
453
|
this.session = null;
|
|
421
454
|
this.user = null;
|
|
422
455
|
this.authError = null;
|
|
456
|
+
this.wasAuthenticatedRef = false;
|
|
423
457
|
if (session?.user) {
|
|
424
458
|
this.trackSession("logout", session).catch((err) => {
|
|
425
459
|
logger.warn("AuthService", `Failed to track logout session [ID:${this.instanceId}]:`, err);
|
|
@@ -431,6 +465,12 @@ var _AuthService = class _AuthService extends BaseService {
|
|
|
431
465
|
if (session?.user) {
|
|
432
466
|
this.authError = null;
|
|
433
467
|
}
|
|
468
|
+
if (!wasAuthenticated && isNowAuthenticated && event === "SIGNED_IN") {
|
|
469
|
+
this.clearPersistenceOnLogin(null, true);
|
|
470
|
+
} else if (userChanged && previousUserId) {
|
|
471
|
+
this.clearPersistenceOnLogin(previousUserId, true);
|
|
472
|
+
}
|
|
473
|
+
this.wasAuthenticatedRef = isNowAuthenticated;
|
|
434
474
|
if (event === "SIGNED_IN" && session?.user) {
|
|
435
475
|
this.trackSession("login", session).catch((err) => {
|
|
436
476
|
logger.warn("AuthService", `Failed to track login session [ID:${this.instanceId}]:`, err);
|
|
@@ -438,32 +478,33 @@ var _AuthService = class _AuthService extends BaseService {
|
|
|
438
478
|
}
|
|
439
479
|
} else if (event === "INITIAL_SESSION") {
|
|
440
480
|
if (session) {
|
|
481
|
+
const previousUserId2 = this.user?.id || null;
|
|
482
|
+
const newUserId2 = session.user?.id || null;
|
|
483
|
+
const userChanged2 = previousUserId2 !== null && newUserId2 !== null && previousUserId2 !== newUserId2;
|
|
441
484
|
this.session = session;
|
|
442
485
|
this.user = session.user ?? null;
|
|
443
486
|
this.authError = null;
|
|
487
|
+
if (userChanged2 && previousUserId2) {
|
|
488
|
+
this.clearPersistenceOnLogin(previousUserId2, true);
|
|
489
|
+
} else if (!wasAuthenticated && !!session.user) {
|
|
490
|
+
this.clearPersistenceOnLogin(null, true);
|
|
491
|
+
}
|
|
492
|
+
this.wasAuthenticatedRef = !!session.user;
|
|
444
493
|
const hasTimeoutError = this.sessionRestorationState.restorationError?.name === "SessionRestorationTimeoutError";
|
|
445
494
|
if (this.sessionRestorationState.isRestoring || this.sessionRestorationState.restorationError || hasTimeoutError && session) {
|
|
446
495
|
this.finishSessionRestoration();
|
|
447
496
|
}
|
|
448
497
|
} else {
|
|
498
|
+
this.wasAuthenticatedRef = false;
|
|
449
499
|
if (this.sessionRestorationState.isRestoring) {
|
|
450
500
|
this.finishSessionRestoration();
|
|
451
501
|
}
|
|
452
502
|
}
|
|
453
503
|
this.authLoading = false;
|
|
454
|
-
logger.debug("AuthService", `State synchronized after INITIAL_SESSION [ID:${this.instanceId}]`, {
|
|
455
|
-
hasUser: !!this.user,
|
|
456
|
-
userId: this.user?.id
|
|
457
|
-
});
|
|
458
504
|
this.notify();
|
|
459
505
|
return;
|
|
460
506
|
}
|
|
461
507
|
this.authLoading = false;
|
|
462
|
-
logger.debug("AuthService", `State synchronized after event [ID:${this.instanceId}]`, {
|
|
463
|
-
event,
|
|
464
|
-
hasUser: !!this.user,
|
|
465
|
-
userId: this.user?.id
|
|
466
|
-
});
|
|
467
508
|
this.notify();
|
|
468
509
|
} catch (error) {
|
|
469
510
|
logger.warn("AuthService", `Error in auth state change handler [ID:${this.instanceId}]:`, error);
|
|
@@ -607,9 +648,6 @@ var _AuthService = class _AuthService extends BaseService {
|
|
|
607
648
|
};
|
|
608
649
|
_AuthService.instanceCount = 0;
|
|
609
650
|
var AuthService = _AuthService;
|
|
610
|
-
|
|
611
|
-
// src/providers/services/AuthServiceProvider.tsx
|
|
612
|
-
import { jsx } from "react/jsx-runtime";
|
|
613
651
|
var AuthServiceContext = createContext(null);
|
|
614
652
|
function AuthServiceProvider({ children, supabaseClient, appName }) {
|
|
615
653
|
const authServiceRef = useRef(null);
|
|
@@ -646,9 +684,6 @@ function AuthServiceProvider({ children, supabaseClient, appName }) {
|
|
|
646
684
|
return /* @__PURE__ */ jsx(AuthServiceContext.Provider, { value: contextValue, children });
|
|
647
685
|
}
|
|
648
686
|
|
|
649
|
-
// src/providers/services/OrganisationServiceProvider.tsx
|
|
650
|
-
import { createContext as createContext2, useMemo as useMemo2, useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
651
|
-
|
|
652
687
|
// src/services/OrganisationService.ts
|
|
653
688
|
var _OrganisationService = class _OrganisationService extends BaseService {
|
|
654
689
|
constructor(supabaseClient, user, session) {
|
|
@@ -676,10 +711,6 @@ var _OrganisationService = class _OrganisationService extends BaseService {
|
|
|
676
711
|
this.supabaseClient = supabaseClient;
|
|
677
712
|
this.user = user;
|
|
678
713
|
this.session = session;
|
|
679
|
-
logger.debug("OrganisationService", `Instance created [ID:${this.instanceId}]`, {
|
|
680
|
-
hasUser: !!user,
|
|
681
|
-
userId: user?.id
|
|
682
|
-
});
|
|
683
714
|
}
|
|
684
715
|
getInstanceId() {
|
|
685
716
|
return this.instanceId;
|
|
@@ -761,12 +792,7 @@ var _OrganisationService = class _OrganisationService extends BaseService {
|
|
|
761
792
|
const needsRetry = this._error !== null && !this.isLoadingRef;
|
|
762
793
|
const isEmpty = newUserId !== null && this._organisations.length === 0 && !this.isLoadingRef;
|
|
763
794
|
if (userChanged || needsRetry || isEmpty) {
|
|
764
|
-
if (userChanged) {
|
|
765
|
-
logger.debug("OrganisationService", `User changed [ID:${this.instanceId}], resetting initialization`, {
|
|
766
|
-
previousUserId,
|
|
767
|
-
newUserId
|
|
768
|
-
});
|
|
769
|
-
} else if (needsRetry) {
|
|
795
|
+
if (userChanged) ; else if (needsRetry) {
|
|
770
796
|
logger.debug("OrganisationService", `Previous error detected [ID:${this.instanceId}], retrying initialization`);
|
|
771
797
|
} else if (isEmpty) {
|
|
772
798
|
logger.debug("OrganisationService", `No organisations found [ID:${this.instanceId}], retrying initialization`);
|
|
@@ -853,7 +879,6 @@ var _OrganisationService = class _OrganisationService extends BaseService {
|
|
|
853
879
|
// Lifecycle methods
|
|
854
880
|
async initialize() {
|
|
855
881
|
if (!this.user) {
|
|
856
|
-
logger.debug("OrganisationService", "Skipping initialization - no user");
|
|
857
882
|
return;
|
|
858
883
|
}
|
|
859
884
|
await super.initialize();
|
|
@@ -882,25 +907,8 @@ var _OrganisationService = class _OrganisationService extends BaseService {
|
|
|
882
907
|
doCleanup() {
|
|
883
908
|
}
|
|
884
909
|
async setDatabaseOrganisationContext(organisation) {
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
this._isContextReady = false;
|
|
888
|
-
this.notify();
|
|
889
|
-
return;
|
|
890
|
-
}
|
|
891
|
-
try {
|
|
892
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
893
|
-
setTimeout(() => reject(new Error("Context setting timeout after 5 seconds")), 5e3);
|
|
894
|
-
});
|
|
895
|
-
const contextPromise = setOrganisationContext(this.supabaseClient, organisation.id);
|
|
896
|
-
await Promise.race([contextPromise, timeoutPromise]);
|
|
897
|
-
this._isContextReady = true;
|
|
898
|
-
this.notify();
|
|
899
|
-
} catch (error) {
|
|
900
|
-
logger.error("OrganisationService", "Failed to set database organisation context:", error);
|
|
901
|
-
this._isContextReady = true;
|
|
902
|
-
this.notify();
|
|
903
|
-
}
|
|
910
|
+
this._isContextReady = true;
|
|
911
|
+
this.notify();
|
|
904
912
|
}
|
|
905
913
|
async loadUserOrganisations() {
|
|
906
914
|
if (!this.user || !this.session || !this.supabaseClient) {
|
|
@@ -937,9 +945,6 @@ var _OrganisationService = class _OrganisationService extends BaseService {
|
|
|
937
945
|
this._isLoading = true;
|
|
938
946
|
this._error = null;
|
|
939
947
|
this.notify();
|
|
940
|
-
logger.debug("OrganisationService", "Loading organisations for user", {
|
|
941
|
-
userId: this.user.id
|
|
942
|
-
});
|
|
943
948
|
try {
|
|
944
949
|
let memberships, membershipError, organisations = [];
|
|
945
950
|
try {
|
|
@@ -998,10 +1003,6 @@ var _OrganisationService = class _OrganisationService extends BaseService {
|
|
|
998
1003
|
}
|
|
999
1004
|
});
|
|
1000
1005
|
organisations = Array.from(organisationsMap.values());
|
|
1001
|
-
logger.debug("OrganisationService", "Query results", {
|
|
1002
|
-
membershipsCount: memberships.length,
|
|
1003
|
-
organisationsCount: organisations.length
|
|
1004
|
-
});
|
|
1005
1006
|
} catch (queryError) {
|
|
1006
1007
|
if (queryError instanceof Error) {
|
|
1007
1008
|
membershipError = queryError;
|
|
@@ -1016,7 +1017,7 @@ var _OrganisationService = class _OrganisationService extends BaseService {
|
|
|
1016
1017
|
let userIsSuperAdmin = false;
|
|
1017
1018
|
if (this.user?.id) {
|
|
1018
1019
|
try {
|
|
1019
|
-
const { isSuperAdmin: checkSuperAdmin, isRBACInitialized: isRBACInitialized2, setupRBAC: setupRBAC2 } = await import(
|
|
1020
|
+
const { isSuperAdmin: checkSuperAdmin, isRBACInitialized: isRBACInitialized2, setupRBAC: setupRBAC2 } = await import('./api-Y4MQWOFW.js');
|
|
1020
1021
|
if (!isRBACInitialized2() && this.supabaseClient) {
|
|
1021
1022
|
setupRBAC2(this.supabaseClient);
|
|
1022
1023
|
}
|
|
@@ -1164,22 +1165,19 @@ var _OrganisationService = class _OrganisationService extends BaseService {
|
|
|
1164
1165
|
};
|
|
1165
1166
|
_OrganisationService.instanceCount = 0;
|
|
1166
1167
|
var OrganisationService = _OrganisationService;
|
|
1167
|
-
|
|
1168
|
-
// src/providers/services/OrganisationServiceProvider.tsx
|
|
1169
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
1170
|
-
var OrganisationServiceContext = createContext2(null);
|
|
1168
|
+
var OrganisationServiceContext = createContext(null);
|
|
1171
1169
|
function OrganisationServiceProvider({
|
|
1172
1170
|
children,
|
|
1173
1171
|
supabaseClient,
|
|
1174
1172
|
user,
|
|
1175
1173
|
session
|
|
1176
1174
|
}) {
|
|
1177
|
-
const organisationServiceRef =
|
|
1175
|
+
const organisationServiceRef = useRef(null);
|
|
1178
1176
|
if (!organisationServiceRef.current) {
|
|
1179
1177
|
organisationServiceRef.current = new OrganisationService(supabaseClient, user, session);
|
|
1180
1178
|
}
|
|
1181
1179
|
const organisationService = organisationServiceRef.current;
|
|
1182
|
-
|
|
1180
|
+
useEffect(() => {
|
|
1183
1181
|
organisationService.updateDependencies(user, session);
|
|
1184
1182
|
let isMounted = true;
|
|
1185
1183
|
organisationService.initialize().catch((error) => {
|
|
@@ -1196,20 +1194,17 @@ function OrganisationServiceProvider({
|
|
|
1196
1194
|
isMounted = false;
|
|
1197
1195
|
};
|
|
1198
1196
|
}, [organisationService, user, session]);
|
|
1199
|
-
|
|
1197
|
+
useEffect(() => {
|
|
1200
1198
|
return () => {
|
|
1201
1199
|
organisationService.cleanup();
|
|
1202
1200
|
};
|
|
1203
1201
|
}, [organisationService]);
|
|
1204
|
-
const contextValue =
|
|
1202
|
+
const contextValue = useMemo(() => ({
|
|
1205
1203
|
organisationService
|
|
1206
1204
|
}), [organisationService]);
|
|
1207
|
-
return /* @__PURE__ */
|
|
1205
|
+
return /* @__PURE__ */ jsx(OrganisationServiceContext.Provider, { value: contextValue, children });
|
|
1208
1206
|
}
|
|
1209
1207
|
|
|
1210
|
-
// src/providers/services/EventServiceProvider.tsx
|
|
1211
|
-
import { createContext as createContext3, useMemo as useMemo3, useEffect as useEffect3, useRef as useRef3 } from "react";
|
|
1212
|
-
|
|
1213
1208
|
// src/services/EventService.ts
|
|
1214
1209
|
var _EventService = class _EventService extends BaseService {
|
|
1215
1210
|
constructor(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId) {
|
|
@@ -1241,11 +1236,6 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1241
1236
|
this.appName = appName;
|
|
1242
1237
|
this.selectedOrganisation = selectedOrganisation;
|
|
1243
1238
|
this.setSelectedEventId = setSelectedEventId;
|
|
1244
|
-
logger.debug("EventService", `Instance created [ID:${this.instanceId}]`, {
|
|
1245
|
-
appName,
|
|
1246
|
-
hasUser: !!user,
|
|
1247
|
-
userId: user?.id
|
|
1248
|
-
});
|
|
1249
1239
|
}
|
|
1250
1240
|
getInstanceId() {
|
|
1251
1241
|
return this.instanceId;
|
|
@@ -1263,7 +1253,7 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1263
1253
|
const newOrgId = selectedOrganisation?.id;
|
|
1264
1254
|
const previousUserId = this.user?.id || null;
|
|
1265
1255
|
const newUserId = user?.id || null;
|
|
1266
|
-
|
|
1256
|
+
this.appName;
|
|
1267
1257
|
if (previousUserId !== newUserId) {
|
|
1268
1258
|
if (previousUserId !== null) {
|
|
1269
1259
|
await this.clearEventSelectionForUser(previousUserId);
|
|
@@ -1277,11 +1267,6 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1277
1267
|
this.isFetchingRef = false;
|
|
1278
1268
|
this.userClearedEventRef = false;
|
|
1279
1269
|
this.hasAutoSelectedRef = false;
|
|
1280
|
-
logger.debug("EventService", `User changed [ID:${this.instanceId}]`, {
|
|
1281
|
-
previousUserId,
|
|
1282
|
-
newUserId,
|
|
1283
|
-
willInitialize: newUserId !== null
|
|
1284
|
-
});
|
|
1285
1270
|
}
|
|
1286
1271
|
this.supabaseClient = supabaseClient;
|
|
1287
1272
|
this.user = user;
|
|
@@ -1291,16 +1276,12 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1291
1276
|
this.setSelectedEventId = setSelectedEventId;
|
|
1292
1277
|
if (user?.id) {
|
|
1293
1278
|
try {
|
|
1294
|
-
const { isRBACInitialized: isRBACInitialized2, isSuperAdmin: checkSuperAdmin, setupRBAC: setupRBAC2 } = await import(
|
|
1279
|
+
const { isRBACInitialized: isRBACInitialized2, isSuperAdmin: checkSuperAdmin, setupRBAC: setupRBAC2 } = await import('./api-Y4MQWOFW.js');
|
|
1295
1280
|
if (!isRBACInitialized2() && this.supabaseClient) {
|
|
1296
1281
|
setupRBAC2(this.supabaseClient);
|
|
1297
1282
|
}
|
|
1298
1283
|
if (isRBACInitialized2()) {
|
|
1299
1284
|
this.isSuperAdmin = await checkSuperAdmin(user.id);
|
|
1300
|
-
logger.debug("EventService", "Super admin status updated in updateDependencies", {
|
|
1301
|
-
userId: user.id,
|
|
1302
|
-
isSuperAdmin: this.isSuperAdmin
|
|
1303
|
-
});
|
|
1304
1285
|
} else {
|
|
1305
1286
|
logger.warn("EventService", "RBAC not initialized in updateDependencies, keeping existing super admin status", {
|
|
1306
1287
|
userId: user.id,
|
|
@@ -1375,13 +1356,8 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1375
1356
|
logger.warn("EventService", "Failed to persist event selection:", error);
|
|
1376
1357
|
});
|
|
1377
1358
|
this.userClearedEventRef = false;
|
|
1378
|
-
logger.debug("EventService", "Event selected", {
|
|
1379
|
-
eventId: event.event_id,
|
|
1380
|
-
eventName: event.event_name,
|
|
1381
|
-
userClearedEventRef: this.userClearedEventRef
|
|
1382
|
-
});
|
|
1383
1359
|
} else {
|
|
1384
|
-
|
|
1360
|
+
this.selectedEvent?.event_id;
|
|
1385
1361
|
this.selectedEvent = null;
|
|
1386
1362
|
this.setSelectedEventId?.(null);
|
|
1387
1363
|
this.clearEventSelection().catch((error) => {
|
|
@@ -1389,11 +1365,6 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1389
1365
|
});
|
|
1390
1366
|
this.hasAutoSelectedRef = false;
|
|
1391
1367
|
this.userClearedEventRef = true;
|
|
1392
|
-
logger.debug("EventService", "Event cleared via setSelectedEvent(null)", {
|
|
1393
|
-
previousEventId,
|
|
1394
|
-
userClearedEventRef: this.userClearedEventRef,
|
|
1395
|
-
stackTrace: new Error().stack
|
|
1396
|
-
});
|
|
1397
1368
|
}
|
|
1398
1369
|
this.notify();
|
|
1399
1370
|
}
|
|
@@ -1483,11 +1454,9 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1483
1454
|
}
|
|
1484
1455
|
async doInitialize() {
|
|
1485
1456
|
if (this.isInitializedRef) {
|
|
1486
|
-
logger.debug("EventService", "Skipping initialization - already initialized");
|
|
1487
1457
|
return;
|
|
1488
1458
|
}
|
|
1489
1459
|
if (this.isFetchingRef) {
|
|
1490
|
-
logger.debug("EventService", "Skipping initialization - already fetching");
|
|
1491
1460
|
return;
|
|
1492
1461
|
}
|
|
1493
1462
|
try {
|
|
@@ -1498,22 +1467,10 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1498
1467
|
logger.warn("EventService", "Failed to clean up old storage keys:", error);
|
|
1499
1468
|
}
|
|
1500
1469
|
if (!this.user) {
|
|
1501
|
-
logger.debug("EventService", "Skipping initialization - no user");
|
|
1502
1470
|
return;
|
|
1503
1471
|
}
|
|
1504
|
-
logger.debug("EventService", "Initializing", {
|
|
1505
|
-
userId: this.user.id,
|
|
1506
|
-
appName: this.appName,
|
|
1507
|
-
hasSelectedOrganisation: !!this.selectedOrganisation,
|
|
1508
|
-
hasSupabaseClient: !!this.supabaseClient,
|
|
1509
|
-
hasSession: !!this.session
|
|
1510
|
-
});
|
|
1511
1472
|
await this.fetchEvents(false);
|
|
1512
1473
|
this.isInitializedRef = true;
|
|
1513
|
-
logger.debug("EventService", "Initialization complete", {
|
|
1514
|
-
eventsCount: this.events.length,
|
|
1515
|
-
hasError: !!this.error
|
|
1516
|
-
});
|
|
1517
1474
|
}
|
|
1518
1475
|
doCleanup() {
|
|
1519
1476
|
}
|
|
@@ -1533,17 +1490,13 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1533
1490
|
let organisationIdForRpc = null;
|
|
1534
1491
|
let userIsSuperAdmin = this.isSuperAdmin;
|
|
1535
1492
|
try {
|
|
1536
|
-
const { isRBACInitialized: isRBACInitialized2, isSuperAdmin: checkSuperAdmin, setupRBAC: setupRBAC2 } = await import(
|
|
1493
|
+
const { isRBACInitialized: isRBACInitialized2, isSuperAdmin: checkSuperAdmin, setupRBAC: setupRBAC2 } = await import('./api-Y4MQWOFW.js');
|
|
1537
1494
|
if (!isRBACInitialized2() && this.supabaseClient) {
|
|
1538
1495
|
setupRBAC2(this.supabaseClient);
|
|
1539
1496
|
}
|
|
1540
1497
|
if (isRBACInitialized2()) {
|
|
1541
1498
|
userIsSuperAdmin = await checkSuperAdmin(this.user.id);
|
|
1542
1499
|
this.isSuperAdmin = userIsSuperAdmin;
|
|
1543
|
-
logger.debug("EventService", "Super admin check completed", {
|
|
1544
|
-
userId: this.user.id,
|
|
1545
|
-
isSuperAdmin: userIsSuperAdmin
|
|
1546
|
-
});
|
|
1547
1500
|
} else {
|
|
1548
1501
|
if (this.isSuperAdmin) {
|
|
1549
1502
|
userIsSuperAdmin = true;
|
|
@@ -1568,10 +1521,6 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1568
1521
|
} else if (this.selectedOrganisation) {
|
|
1569
1522
|
organisationIdForRpc = this.selectedOrganisation.id;
|
|
1570
1523
|
} else {
|
|
1571
|
-
logger.debug("EventService", "No organisation context available, fetching all accessible events", {
|
|
1572
|
-
hasSelectedEvent: !!this.selectedEvent,
|
|
1573
|
-
hasSelectedOrganisation: !!this.selectedOrganisation
|
|
1574
|
-
});
|
|
1575
1524
|
organisationIdForRpc = null;
|
|
1576
1525
|
}
|
|
1577
1526
|
}
|
|
@@ -1597,24 +1546,11 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1597
1546
|
}
|
|
1598
1547
|
}
|
|
1599
1548
|
}
|
|
1600
|
-
logger.debug("EventService", "Fetching events", {
|
|
1601
|
-
userId: this.user.id,
|
|
1602
|
-
organisationIdForRpc,
|
|
1603
|
-
appName: this.appName,
|
|
1604
|
-
hasSelectedEvent: !!this.selectedEvent,
|
|
1605
|
-
hasSelectedOrganisation: !!this.selectedOrganisation,
|
|
1606
|
-
isSuperAdmin: userIsSuperAdmin
|
|
1607
|
-
});
|
|
1608
1549
|
let { data, error: rpcError } = await this.supabaseClient.rpc("data_user_events_get", {
|
|
1609
1550
|
p_user_id: this.user.id,
|
|
1610
1551
|
p_organisation_id: organisationIdForRpc,
|
|
1611
1552
|
p_app_name: this.appName
|
|
1612
1553
|
});
|
|
1613
|
-
logger.debug("EventService", "RPC response", {
|
|
1614
|
-
dataLength: data?.length || 0,
|
|
1615
|
-
hasError: !!rpcError,
|
|
1616
|
-
error: rpcError
|
|
1617
|
-
});
|
|
1618
1554
|
if (rpcError) {
|
|
1619
1555
|
logger.error("EventService", "RPC error fetching events:", rpcError);
|
|
1620
1556
|
throw new Error(rpcError.message || "Failed to fetch events");
|
|
@@ -1657,76 +1593,40 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1657
1593
|
this.selectedEvent = null;
|
|
1658
1594
|
this.setSelectedEventId?.(null);
|
|
1659
1595
|
this.userClearedEventRef = previousUserClearedRef;
|
|
1660
|
-
logger.debug("EventService", "Cleared selected event - no longer in events list", {
|
|
1661
|
-
previousEventId: selectedEventId,
|
|
1662
|
-
eventsCount: transformedEvents.length
|
|
1663
|
-
});
|
|
1664
1596
|
}
|
|
1665
1597
|
}
|
|
1666
1598
|
this.hasAutoSelectedRef = false;
|
|
1667
1599
|
if (!skipLoadPersisted) {
|
|
1668
1600
|
const persistedEventLoaded = await this.loadPersistedEvent(transformedEvents);
|
|
1669
|
-
logger.debug("EventService", "Event selection check", {
|
|
1670
|
-
persistedEventLoaded,
|
|
1671
|
-
userClearedEventRef: this.userClearedEventRef,
|
|
1672
|
-
eventsCount: transformedEvents.length,
|
|
1673
|
-
hasSelectedEvent: !!this.selectedEvent
|
|
1674
|
-
});
|
|
1675
1601
|
if (!persistedEventLoaded && !this.userClearedEventRef) {
|
|
1676
1602
|
const nextEvent = this.getNextEventByDate(transformedEvents);
|
|
1677
|
-
logger.debug("EventService", "Auto-selection attempt", {
|
|
1678
|
-
nextEventFound: !!nextEvent,
|
|
1679
|
-
nextEventId: nextEvent?.event_id,
|
|
1680
|
-
nextEventDate: nextEvent?.event_date
|
|
1681
|
-
});
|
|
1682
1603
|
if (nextEvent) {
|
|
1683
1604
|
this.hasAutoSelectedRef = true;
|
|
1684
1605
|
this.setSelectedEvent(nextEvent);
|
|
1685
|
-
logger.debug("EventService", "Auto-selected next event", {
|
|
1686
|
-
eventId: nextEvent.event_id,
|
|
1687
|
-
eventName: nextEvent.event_name,
|
|
1688
|
-
eventDate: nextEvent.event_date
|
|
1689
|
-
});
|
|
1690
|
-
} else {
|
|
1691
|
-
logger.debug("EventService", "No next event found for auto-selection", {
|
|
1692
|
-
eventsCount: transformedEvents.length,
|
|
1693
|
-
eventsWithDates: transformedEvents.filter((e) => e.event_date).length
|
|
1694
|
-
});
|
|
1695
1606
|
}
|
|
1696
1607
|
} else if (persistedEventLoaded) {
|
|
1697
|
-
logger.debug("EventService", "Skipped auto-selection - persisted event loaded");
|
|
1698
1608
|
} else if (this.userClearedEventRef) {
|
|
1699
|
-
logger.debug("EventService", "Skipped auto-selection - user explicitly cleared event");
|
|
1700
1609
|
}
|
|
1701
1610
|
} else {
|
|
1702
1611
|
if (!this.userClearedEventRef) {
|
|
1703
1612
|
const nextEvent = this.getNextEventByDate(transformedEvents);
|
|
1704
|
-
logger.debug("EventService", "Auto-selection attempt (skip persisted)", {
|
|
1705
|
-
nextEventFound: !!nextEvent,
|
|
1706
|
-
nextEventId: nextEvent?.event_id
|
|
1707
|
-
});
|
|
1708
1613
|
if (nextEvent) {
|
|
1709
1614
|
this.hasAutoSelectedRef = true;
|
|
1710
1615
|
this.setSelectedEvent(nextEvent);
|
|
1711
|
-
logger.debug("EventService", "Auto-selected next event (skip persisted)", {
|
|
1712
|
-
eventId: nextEvent.event_id,
|
|
1713
|
-
eventName: nextEvent.event_name
|
|
1714
|
-
});
|
|
1715
1616
|
}
|
|
1716
1617
|
} else {
|
|
1717
|
-
logger.debug("EventService", "Skipped auto-selection (skip persisted) - user explicitly cleared event");
|
|
1718
1618
|
}
|
|
1719
1619
|
}
|
|
1720
1620
|
}
|
|
1721
1621
|
} catch (err) {
|
|
1722
1622
|
logger.error("EventService", "Error fetching events:", err);
|
|
1723
1623
|
const _error = err instanceof Error ? err : new Error("Unknown error occurred");
|
|
1724
|
-
|
|
1624
|
+
{
|
|
1725
1625
|
this.error = _error;
|
|
1726
1626
|
this.events = [];
|
|
1727
1627
|
}
|
|
1728
1628
|
} finally {
|
|
1729
|
-
|
|
1629
|
+
{
|
|
1730
1630
|
this._isLoading = false;
|
|
1731
1631
|
}
|
|
1732
1632
|
this.isFetchingRef = false;
|
|
@@ -1773,10 +1673,7 @@ var _EventService = class _EventService extends BaseService {
|
|
|
1773
1673
|
};
|
|
1774
1674
|
_EventService.instanceCount = 0;
|
|
1775
1675
|
var EventService = _EventService;
|
|
1776
|
-
|
|
1777
|
-
// src/providers/services/EventServiceProvider.tsx
|
|
1778
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1779
|
-
var EventServiceContext = createContext3(null);
|
|
1676
|
+
var EventServiceContext = createContext(null);
|
|
1780
1677
|
function EventServiceProvider({
|
|
1781
1678
|
children,
|
|
1782
1679
|
supabaseClient,
|
|
@@ -1786,51 +1683,29 @@ function EventServiceProvider({
|
|
|
1786
1683
|
selectedOrganisation,
|
|
1787
1684
|
setSelectedEventId
|
|
1788
1685
|
}) {
|
|
1789
|
-
const eventServiceRef =
|
|
1790
|
-
const initializingRef =
|
|
1686
|
+
const eventServiceRef = useRef(null);
|
|
1687
|
+
const initializingRef = useRef(false);
|
|
1791
1688
|
if (!eventServiceRef.current) {
|
|
1792
1689
|
eventServiceRef.current = new EventService(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);
|
|
1793
1690
|
}
|
|
1794
1691
|
const eventService = eventServiceRef.current;
|
|
1795
|
-
|
|
1692
|
+
useEffect(() => {
|
|
1796
1693
|
let isMounted = true;
|
|
1797
|
-
logger.debug("EventServiceProvider", "useEffect triggered", {
|
|
1798
|
-
hasUser: !!user,
|
|
1799
|
-
userId: user?.id,
|
|
1800
|
-
hasSession: !!session,
|
|
1801
|
-
appName,
|
|
1802
|
-
isInitializing: initializingRef.current
|
|
1803
|
-
});
|
|
1804
1694
|
if (initializingRef.current) {
|
|
1805
|
-
logger.debug("EventServiceProvider", "Skipping - already initializing");
|
|
1806
1695
|
return;
|
|
1807
1696
|
}
|
|
1808
1697
|
const updateAndInitialize = async () => {
|
|
1809
1698
|
initializingRef.current = true;
|
|
1810
1699
|
try {
|
|
1811
|
-
logger.debug("EventServiceProvider", "Updating dependencies and initializing", {
|
|
1812
|
-
hasUser: !!user,
|
|
1813
|
-
userId: user?.id,
|
|
1814
|
-
hasSession: !!session,
|
|
1815
|
-
appName,
|
|
1816
|
-
hasSelectedOrganisation: !!selectedOrganisation
|
|
1817
|
-
});
|
|
1818
1700
|
await eventService.updateDependencies(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);
|
|
1819
1701
|
if (!isMounted) return;
|
|
1820
1702
|
if (user && session && supabaseClient && appName) {
|
|
1821
|
-
logger.debug("EventServiceProvider", "Initializing event service");
|
|
1822
1703
|
await eventService.initialize().catch((error) => {
|
|
1823
1704
|
if (isMounted) {
|
|
1824
1705
|
logger.error("EventServiceProvider", "Failed to initialize event service:", error);
|
|
1825
1706
|
}
|
|
1826
1707
|
});
|
|
1827
1708
|
} else {
|
|
1828
|
-
logger.debug("EventServiceProvider", "Skipping initialization - missing required dependencies", {
|
|
1829
|
-
hasUser: !!user,
|
|
1830
|
-
hasSession: !!session,
|
|
1831
|
-
hasSupabaseClient: !!supabaseClient,
|
|
1832
|
-
appName
|
|
1833
|
-
});
|
|
1834
1709
|
}
|
|
1835
1710
|
} finally {
|
|
1836
1711
|
initializingRef.current = false;
|
|
@@ -1842,20 +1717,17 @@ function EventServiceProvider({
|
|
|
1842
1717
|
initializingRef.current = false;
|
|
1843
1718
|
};
|
|
1844
1719
|
}, [supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId]);
|
|
1845
|
-
|
|
1720
|
+
useEffect(() => {
|
|
1846
1721
|
return () => {
|
|
1847
1722
|
eventService.cleanup();
|
|
1848
1723
|
};
|
|
1849
1724
|
}, [eventService]);
|
|
1850
|
-
const contextValue =
|
|
1725
|
+
const contextValue = useMemo(() => ({
|
|
1851
1726
|
eventService
|
|
1852
1727
|
}), [eventService]);
|
|
1853
|
-
return /* @__PURE__ */
|
|
1728
|
+
return /* @__PURE__ */ jsx(EventServiceContext.Provider, { value: contextValue, children });
|
|
1854
1729
|
}
|
|
1855
1730
|
|
|
1856
|
-
// src/providers/services/InactivityServiceProvider.tsx
|
|
1857
|
-
import { createContext as createContext4, useMemo as useMemo4, useEffect as useEffect4, useRef as useRef4 } from "react";
|
|
1858
|
-
|
|
1859
1731
|
// src/services/InactivityService.ts
|
|
1860
1732
|
var InactivityService = class extends BaseService {
|
|
1861
1733
|
constructor(supabaseClient, user, session, idleTimeoutMs = 30 * 60 * 1e3, warnBeforeMs = 60 * 1e3, onIdleLogout) {
|
|
@@ -2006,6 +1878,11 @@ var InactivityService = class extends BaseService {
|
|
|
2006
1878
|
} catch (error) {
|
|
2007
1879
|
logger.error("InactivityService", "Error during idle logout:", error);
|
|
2008
1880
|
}
|
|
1881
|
+
try {
|
|
1882
|
+
sessionStorage.clear();
|
|
1883
|
+
} catch (storageError) {
|
|
1884
|
+
logger.warn("InactivityService", "Failed to clear sessionStorage", { error: storageError });
|
|
1885
|
+
}
|
|
2009
1886
|
this.onIdleLogout?.("inactivity");
|
|
2010
1887
|
this.notify();
|
|
2011
1888
|
}
|
|
@@ -2026,6 +1903,11 @@ var InactivityService = class extends BaseService {
|
|
|
2026
1903
|
} catch (error) {
|
|
2027
1904
|
logger.error("InactivityService", "Error during manual sign out:", error);
|
|
2028
1905
|
}
|
|
1906
|
+
try {
|
|
1907
|
+
sessionStorage.clear();
|
|
1908
|
+
} catch (storageError) {
|
|
1909
|
+
logger.warn("InactivityService", "Failed to clear sessionStorage", { error: storageError });
|
|
1910
|
+
}
|
|
2029
1911
|
this.onIdleLogout?.("inactivity");
|
|
2030
1912
|
this.notify();
|
|
2031
1913
|
}
|
|
@@ -2070,27 +1952,34 @@ var InactivityService = class extends BaseService {
|
|
|
2070
1952
|
}
|
|
2071
1953
|
setupEventHandlers() {
|
|
2072
1954
|
if (typeof window === "undefined") return;
|
|
2073
|
-
let idleTimer = null;
|
|
2074
1955
|
let warningTimer = null;
|
|
1956
|
+
let logoutTimer = null;
|
|
1957
|
+
let countdownInterval = null;
|
|
2075
1958
|
let lastActivity = Date.now();
|
|
2076
|
-
let pollInterval = null;
|
|
2077
1959
|
let prevIsIdle = false;
|
|
2078
1960
|
let prevShowWarning = false;
|
|
2079
1961
|
let prevShowInactivityWarning = false;
|
|
2080
1962
|
let prevInactivityTimeRemaining = 0;
|
|
2081
1963
|
let prevTimeRemaining = this.idleTimeoutMs;
|
|
2082
|
-
const
|
|
1964
|
+
const getTimeUntilWarning = () => {
|
|
1965
|
+
const timeSinceActivity = Date.now() - lastActivity;
|
|
1966
|
+
return Math.max(0, this.idleTimeoutMs - this.warnBeforeMs - timeSinceActivity);
|
|
1967
|
+
};
|
|
1968
|
+
const getTimeUntilLogout = () => {
|
|
1969
|
+
const timeSinceActivity = Date.now() - lastActivity;
|
|
1970
|
+
return Math.max(0, this.idleTimeoutMs - timeSinceActivity);
|
|
1971
|
+
};
|
|
1972
|
+
const updateState = (forceNotify = false) => {
|
|
2083
1973
|
const now = Date.now();
|
|
2084
1974
|
const timeSinceActivity = now - lastActivity;
|
|
2085
1975
|
const timeUntilIdle = this.idleTimeoutMs - timeSinceActivity;
|
|
2086
|
-
const
|
|
2087
|
-
const
|
|
2088
|
-
const newShowWarning = newIsIdle && timeSinceActivity < this.idleTimeoutMs;
|
|
1976
|
+
const newIsIdle = timeSinceActivity >= this.idleTimeoutMs;
|
|
1977
|
+
const newShowWarning = timeSinceActivity >= this.idleTimeoutMs - this.warnBeforeMs && !newIsIdle;
|
|
2089
1978
|
const newShowInactivityWarning = newShowWarning;
|
|
2090
|
-
const newInactivityTimeRemaining = newShowWarning ? Math.ceil(
|
|
1979
|
+
const newInactivityTimeRemaining = newShowWarning ? Math.ceil(timeUntilIdle / 1e3) : 0;
|
|
2091
1980
|
const newTimeRemaining = Math.max(0, timeUntilIdle);
|
|
2092
|
-
const stateChanged = prevIsIdle !== newIsIdle || prevShowWarning !== newShowWarning || prevShowInactivityWarning !== newShowInactivityWarning || prevInactivityTimeRemaining !== newInactivityTimeRemaining || prevTimeRemaining !== newTimeRemaining;
|
|
2093
|
-
if (stateChanged) {
|
|
1981
|
+
const stateChanged = prevIsIdle !== newIsIdle || prevShowWarning !== newShowWarning || prevShowInactivityWarning !== newShowInactivityWarning || newShowWarning && prevInactivityTimeRemaining !== newInactivityTimeRemaining || prevTimeRemaining !== newTimeRemaining;
|
|
1982
|
+
if (stateChanged || forceNotify) {
|
|
2094
1983
|
this._isIdle = newIsIdle;
|
|
2095
1984
|
this._showWarning = newShowWarning;
|
|
2096
1985
|
this._showInactivityWarning = newShowInactivityWarning;
|
|
@@ -2101,73 +1990,123 @@ var InactivityService = class extends BaseService {
|
|
|
2101
1990
|
prevShowInactivityWarning = newShowInactivityWarning;
|
|
2102
1991
|
prevInactivityTimeRemaining = newInactivityTimeRemaining;
|
|
2103
1992
|
prevTimeRemaining = newTimeRemaining;
|
|
2104
|
-
|
|
2105
|
-
|
|
1993
|
+
if (stateChanged) {
|
|
1994
|
+
this.notify();
|
|
1995
|
+
}
|
|
1996
|
+
if (newIsIdle) {
|
|
2106
1997
|
this.handleIdleLogout();
|
|
2107
1998
|
}
|
|
2108
1999
|
}
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
idleTimer = null;
|
|
2112
|
-
}
|
|
2000
|
+
};
|
|
2001
|
+
const scheduleNextCheck = () => {
|
|
2113
2002
|
if (warningTimer) {
|
|
2114
2003
|
clearTimeout(warningTimer);
|
|
2115
2004
|
warningTimer = null;
|
|
2116
2005
|
}
|
|
2117
|
-
if (
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2006
|
+
if (logoutTimer) {
|
|
2007
|
+
clearTimeout(logoutTimer);
|
|
2008
|
+
logoutTimer = null;
|
|
2009
|
+
}
|
|
2010
|
+
if (countdownInterval) {
|
|
2011
|
+
clearInterval(countdownInterval);
|
|
2012
|
+
countdownInterval = null;
|
|
2013
|
+
}
|
|
2014
|
+
const timeUntilWarning = getTimeUntilWarning();
|
|
2015
|
+
const timeUntilLogout = getTimeUntilLogout();
|
|
2016
|
+
const timeSinceActivity = Date.now() - lastActivity;
|
|
2017
|
+
if (timeSinceActivity >= this.idleTimeoutMs) {
|
|
2018
|
+
return;
|
|
2019
|
+
}
|
|
2020
|
+
if (timeSinceActivity >= this.idleTimeoutMs - this.warnBeforeMs) {
|
|
2021
|
+
updateState();
|
|
2022
|
+
countdownInterval = setInterval(() => {
|
|
2023
|
+
updateState();
|
|
2024
|
+
if (Date.now() - lastActivity >= this.idleTimeoutMs) {
|
|
2025
|
+
if (countdownInterval) {
|
|
2026
|
+
clearInterval(countdownInterval);
|
|
2027
|
+
countdownInterval = null;
|
|
2028
|
+
}
|
|
2029
|
+
this.handleIdleLogout();
|
|
2030
|
+
}
|
|
2031
|
+
}, 1e3);
|
|
2032
|
+
logoutTimer = setTimeout(() => {
|
|
2033
|
+
if (countdownInterval) {
|
|
2034
|
+
clearInterval(countdownInterval);
|
|
2035
|
+
countdownInterval = null;
|
|
2036
|
+
}
|
|
2124
2037
|
this.handleIdleLogout();
|
|
2125
|
-
},
|
|
2038
|
+
}, timeUntilLogout);
|
|
2039
|
+
} else {
|
|
2040
|
+
const timeUntilWarningMs = timeUntilWarning;
|
|
2041
|
+
const adaptiveInterval = timeUntilWarningMs > 5 * 60 * 1e3 ? 60 * 1e3 : timeUntilWarningMs > 60 * 1e3 ? 10 * 1e3 : 1e3;
|
|
2042
|
+
warningTimer = setTimeout(() => {
|
|
2043
|
+
updateState();
|
|
2044
|
+
scheduleNextCheck();
|
|
2045
|
+
}, Math.min(adaptiveInterval, timeUntilWarningMs));
|
|
2126
2046
|
}
|
|
2127
2047
|
};
|
|
2128
2048
|
const resetTimers = () => {
|
|
2129
2049
|
lastActivity = Date.now();
|
|
2130
|
-
if (idleTimer) {
|
|
2131
|
-
clearTimeout(idleTimer);
|
|
2132
|
-
idleTimer = null;
|
|
2133
|
-
}
|
|
2134
2050
|
if (warningTimer) {
|
|
2135
2051
|
clearTimeout(warningTimer);
|
|
2136
2052
|
warningTimer = null;
|
|
2137
2053
|
}
|
|
2054
|
+
if (logoutTimer) {
|
|
2055
|
+
clearTimeout(logoutTimer);
|
|
2056
|
+
logoutTimer = null;
|
|
2057
|
+
}
|
|
2058
|
+
if (countdownInterval) {
|
|
2059
|
+
clearInterval(countdownInterval);
|
|
2060
|
+
countdownInterval = null;
|
|
2061
|
+
}
|
|
2062
|
+
const hadWarning = this._showWarning || this._showInactivityWarning;
|
|
2138
2063
|
this._showInactivityWarning = false;
|
|
2139
2064
|
this._inactivityTimeRemaining = 0;
|
|
2140
2065
|
this._isIdle = false;
|
|
2141
2066
|
this._showWarning = false;
|
|
2067
|
+
this._timeRemaining = this.idleTimeoutMs;
|
|
2142
2068
|
prevIsIdle = false;
|
|
2143
2069
|
prevShowWarning = false;
|
|
2144
2070
|
prevShowInactivityWarning = false;
|
|
2145
2071
|
prevInactivityTimeRemaining = 0;
|
|
2146
2072
|
prevTimeRemaining = this.idleTimeoutMs;
|
|
2073
|
+
if (hadWarning) {
|
|
2074
|
+
this.notify();
|
|
2075
|
+
}
|
|
2076
|
+
scheduleNextCheck();
|
|
2147
2077
|
};
|
|
2148
2078
|
const activityEvents = ["mousedown", "mousemove", "keypress", "scroll", "touchstart", "click"];
|
|
2079
|
+
let activityThrottleTimer = null;
|
|
2149
2080
|
const handleActivity = () => {
|
|
2150
|
-
|
|
2081
|
+
if (activityThrottleTimer) {
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2084
|
+
activityThrottleTimer = setTimeout(() => {
|
|
2085
|
+
activityThrottleTimer = null;
|
|
2086
|
+
resetTimers();
|
|
2087
|
+
}, 1e3);
|
|
2151
2088
|
};
|
|
2152
2089
|
activityEvents.forEach((event) => {
|
|
2153
2090
|
document.addEventListener(event, handleActivity, true);
|
|
2154
2091
|
});
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
}, 1e4);
|
|
2158
|
-
pollInactivityState();
|
|
2092
|
+
updateState(true);
|
|
2093
|
+
scheduleNextCheck();
|
|
2159
2094
|
this.cleanupHandlers = () => {
|
|
2160
|
-
if (idleTimer) {
|
|
2161
|
-
clearTimeout(idleTimer);
|
|
2162
|
-
idleTimer = null;
|
|
2163
|
-
}
|
|
2164
2095
|
if (warningTimer) {
|
|
2165
2096
|
clearTimeout(warningTimer);
|
|
2166
2097
|
warningTimer = null;
|
|
2167
2098
|
}
|
|
2168
|
-
if (
|
|
2169
|
-
|
|
2170
|
-
|
|
2099
|
+
if (logoutTimer) {
|
|
2100
|
+
clearTimeout(logoutTimer);
|
|
2101
|
+
logoutTimer = null;
|
|
2102
|
+
}
|
|
2103
|
+
if (countdownInterval) {
|
|
2104
|
+
clearInterval(countdownInterval);
|
|
2105
|
+
countdownInterval = null;
|
|
2106
|
+
}
|
|
2107
|
+
if (activityThrottleTimer) {
|
|
2108
|
+
clearTimeout(activityThrottleTimer);
|
|
2109
|
+
activityThrottleTimer = null;
|
|
2171
2110
|
}
|
|
2172
2111
|
activityEvents.forEach((event) => {
|
|
2173
2112
|
document.removeEventListener(event, handleActivity, true);
|
|
@@ -2180,13 +2119,9 @@ var InactivityService = class extends BaseService {
|
|
|
2180
2119
|
this._inactivityTimeRemaining = 0;
|
|
2181
2120
|
};
|
|
2182
2121
|
this._isTracking = true;
|
|
2183
|
-
this.notify();
|
|
2184
2122
|
}
|
|
2185
2123
|
};
|
|
2186
|
-
|
|
2187
|
-
// src/providers/services/InactivityServiceProvider.tsx
|
|
2188
|
-
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
2189
|
-
var InactivityServiceContext = createContext4(null);
|
|
2124
|
+
var InactivityServiceContext = createContext(null);
|
|
2190
2125
|
function InactivityServiceProvider({
|
|
2191
2126
|
children,
|
|
2192
2127
|
supabaseClient,
|
|
@@ -2198,12 +2133,12 @@ function InactivityServiceProvider({
|
|
|
2198
2133
|
// REQUIRED: No default - must be explicitly provided
|
|
2199
2134
|
onIdleLogout
|
|
2200
2135
|
}) {
|
|
2201
|
-
const inactivityServiceRef =
|
|
2136
|
+
const inactivityServiceRef = useRef(null);
|
|
2202
2137
|
if (!inactivityServiceRef.current) {
|
|
2203
2138
|
inactivityServiceRef.current = new InactivityService(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout);
|
|
2204
2139
|
}
|
|
2205
2140
|
const inactivityService = inactivityServiceRef.current;
|
|
2206
|
-
|
|
2141
|
+
useEffect(() => {
|
|
2207
2142
|
inactivityService.updateDependencies(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout);
|
|
2208
2143
|
let isMounted = true;
|
|
2209
2144
|
inactivityService.initialize().catch((error) => {
|
|
@@ -2215,27 +2150,24 @@ function InactivityServiceProvider({
|
|
|
2215
2150
|
isMounted = false;
|
|
2216
2151
|
};
|
|
2217
2152
|
}, [inactivityService, supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout]);
|
|
2218
|
-
|
|
2153
|
+
useEffect(() => {
|
|
2219
2154
|
return () => {
|
|
2220
2155
|
inactivityService.cleanup();
|
|
2221
2156
|
};
|
|
2222
2157
|
}, [inactivityService]);
|
|
2223
|
-
const contextValue =
|
|
2158
|
+
const contextValue = useMemo(() => ({
|
|
2224
2159
|
inactivityService
|
|
2225
2160
|
}), [inactivityService]);
|
|
2226
|
-
return /* @__PURE__ */
|
|
2161
|
+
return /* @__PURE__ */ jsx(InactivityServiceContext.Provider, { value: contextValue, children });
|
|
2227
2162
|
}
|
|
2228
|
-
|
|
2229
|
-
// src/hooks/services/useAuthService.ts
|
|
2230
|
-
import { useContext, useReducer, useEffect as useEffect5, useRef as useRef5 } from "react";
|
|
2231
2163
|
function useAuthService() {
|
|
2232
2164
|
const context = useContext(AuthServiceContext);
|
|
2233
2165
|
if (!context) {
|
|
2234
2166
|
throw new Error("useAuthService must be used within AuthServiceProvider");
|
|
2235
2167
|
}
|
|
2236
2168
|
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
2237
|
-
const timeoutRef =
|
|
2238
|
-
|
|
2169
|
+
const timeoutRef = useRef(null);
|
|
2170
|
+
useEffect(() => {
|
|
2239
2171
|
const debouncedUpdate = () => {
|
|
2240
2172
|
if (timeoutRef.current) {
|
|
2241
2173
|
clearTimeout(timeoutRef.current);
|
|
@@ -2255,17 +2187,14 @@ function useAuthService() {
|
|
|
2255
2187
|
}, [context.authService]);
|
|
2256
2188
|
return context.authService;
|
|
2257
2189
|
}
|
|
2258
|
-
|
|
2259
|
-
// src/hooks/services/useOrganisationService.ts
|
|
2260
|
-
import { useContext as useContext2, useReducer as useReducer2, useEffect as useEffect6, useRef as useRef6 } from "react";
|
|
2261
2190
|
function useOrganisationService() {
|
|
2262
|
-
const context =
|
|
2191
|
+
const context = useContext(OrganisationServiceContext);
|
|
2263
2192
|
if (!context) {
|
|
2264
2193
|
throw new Error("useOrganisationService must be used within OrganisationServiceProvider");
|
|
2265
2194
|
}
|
|
2266
|
-
const [, forceUpdate] =
|
|
2267
|
-
const timeoutRef =
|
|
2268
|
-
|
|
2195
|
+
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
2196
|
+
const timeoutRef = useRef(null);
|
|
2197
|
+
useEffect(() => {
|
|
2269
2198
|
const debouncedUpdate = () => {
|
|
2270
2199
|
if (timeoutRef.current) {
|
|
2271
2200
|
clearTimeout(timeoutRef.current);
|
|
@@ -2308,17 +2237,14 @@ function useOrganisations() {
|
|
|
2308
2237
|
getPrimaryOrganisation: () => organisationService.getPrimaryOrganisation()
|
|
2309
2238
|
};
|
|
2310
2239
|
}
|
|
2311
|
-
|
|
2312
|
-
// src/hooks/services/useEventService.ts
|
|
2313
|
-
import { useContext as useContext3, useReducer as useReducer3, useEffect as useEffect7, useRef as useRef7 } from "react";
|
|
2314
2240
|
function useEventService() {
|
|
2315
|
-
const context =
|
|
2241
|
+
const context = useContext(EventServiceContext);
|
|
2316
2242
|
if (!context) {
|
|
2317
2243
|
throw new Error("useEventService must be used within EventServiceProvider");
|
|
2318
2244
|
}
|
|
2319
|
-
const [, forceUpdate] =
|
|
2320
|
-
const timeoutRef =
|
|
2321
|
-
|
|
2245
|
+
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
2246
|
+
const timeoutRef = useRef(null);
|
|
2247
|
+
useEffect(() => {
|
|
2322
2248
|
const debouncedUpdate = () => {
|
|
2323
2249
|
if (timeoutRef.current) {
|
|
2324
2250
|
clearTimeout(timeoutRef.current);
|
|
@@ -2338,17 +2264,14 @@ function useEventService() {
|
|
|
2338
2264
|
}, [context.eventService]);
|
|
2339
2265
|
return context.eventService;
|
|
2340
2266
|
}
|
|
2341
|
-
|
|
2342
|
-
// src/hooks/services/useInactivityService.ts
|
|
2343
|
-
import { useContext as useContext4, useReducer as useReducer4, useEffect as useEffect8, useRef as useRef8 } from "react";
|
|
2344
2267
|
function useInactivityService() {
|
|
2345
|
-
const context =
|
|
2268
|
+
const context = useContext(InactivityServiceContext);
|
|
2346
2269
|
if (!context) {
|
|
2347
2270
|
throw new Error("useInactivityService must be used within InactivityServiceProvider");
|
|
2348
2271
|
}
|
|
2349
|
-
const [, forceUpdate] =
|
|
2350
|
-
const timeoutRef =
|
|
2351
|
-
|
|
2272
|
+
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
2273
|
+
const timeoutRef = useRef(null);
|
|
2274
|
+
useEffect(() => {
|
|
2352
2275
|
const debouncedUpdate = () => {
|
|
2353
2276
|
if (timeoutRef.current) {
|
|
2354
2277
|
clearTimeout(timeoutRef.current);
|
|
@@ -2368,19 +2291,16 @@ function useInactivityService() {
|
|
|
2368
2291
|
}, [context.inactivityService]);
|
|
2369
2292
|
return context.inactivityService;
|
|
2370
2293
|
}
|
|
2371
|
-
|
|
2372
|
-
// src/hooks/useSessionRestoration.ts
|
|
2373
|
-
import { useContext as useContext5, useMemo as useMemo5, useEffect as useEffect9, useState as useState2 } from "react";
|
|
2374
2294
|
var log = createLogger("useSessionRestoration");
|
|
2375
|
-
var SESSION_RESTORATION_TIMEOUT_MS =
|
|
2295
|
+
var SESSION_RESTORATION_TIMEOUT_MS = 1e4;
|
|
2376
2296
|
function useSessionRestoration() {
|
|
2377
|
-
const context =
|
|
2297
|
+
const context = useContext(AuthServiceContext);
|
|
2378
2298
|
if (!context) {
|
|
2379
2299
|
throw new Error("useSessionRestoration must be used within AuthServiceProvider");
|
|
2380
2300
|
}
|
|
2381
2301
|
const { sessionRestoration } = context;
|
|
2382
|
-
const [hasTimedOut, setHasTimedOut] =
|
|
2383
|
-
|
|
2302
|
+
const [hasTimedOut, setHasTimedOut] = useState(false);
|
|
2303
|
+
useEffect(() => {
|
|
2384
2304
|
let timeoutHandle = null;
|
|
2385
2305
|
if (sessionRestoration.isRestoring && !sessionRestoration.restorationComplete && !sessionRestoration.restorationError) {
|
|
2386
2306
|
setHasTimedOut(false);
|
|
@@ -2401,18 +2321,15 @@ function useSessionRestoration() {
|
|
|
2401
2321
|
sessionRestoration.restorationComplete,
|
|
2402
2322
|
sessionRestoration.restorationError
|
|
2403
2323
|
]);
|
|
2404
|
-
return
|
|
2324
|
+
return useMemo(() => ({
|
|
2405
2325
|
...sessionRestoration,
|
|
2406
2326
|
hasTimedOut,
|
|
2407
2327
|
timeoutMs: SESSION_RESTORATION_TIMEOUT_MS
|
|
2408
2328
|
}), [sessionRestoration, hasTimedOut]);
|
|
2409
2329
|
}
|
|
2410
|
-
|
|
2411
|
-
// src/providers/services/UnifiedAuthProvider.tsx
|
|
2412
|
-
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
2413
|
-
var UnifiedAuthContext = createContext5(void 0);
|
|
2330
|
+
var UnifiedAuthContext = createContext(void 0);
|
|
2414
2331
|
var useUnifiedAuth = () => {
|
|
2415
|
-
const context =
|
|
2332
|
+
const context = useContext(UnifiedAuthContext);
|
|
2416
2333
|
if (!context) {
|
|
2417
2334
|
logger.error("useUnifiedAuth", "useUnifiedAuth must be used within a UnifiedAuthProvider");
|
|
2418
2335
|
throw new Error("useUnifiedAuth must be used within a UnifiedAuthProvider");
|
|
@@ -2436,46 +2353,21 @@ function UnifiedAuthContextProvider({
|
|
|
2436
2353
|
restorationComplete,
|
|
2437
2354
|
restorationError
|
|
2438
2355
|
} = sessionRestorationState;
|
|
2439
|
-
const sessionRestoration =
|
|
2356
|
+
const sessionRestoration = useMemo(() => ({
|
|
2440
2357
|
isRestoring,
|
|
2441
2358
|
restorationComplete,
|
|
2442
2359
|
restorationError
|
|
2443
2360
|
}), [isRestoring, restorationComplete, restorationError]);
|
|
2444
|
-
|
|
2445
|
-
try {
|
|
2446
|
-
eventService = useEventService();
|
|
2447
|
-
} catch (error) {
|
|
2448
|
-
eventService = {
|
|
2449
|
-
getEvents: () => [],
|
|
2450
|
-
getSelectedEvent: () => null,
|
|
2451
|
-
isLoading: () => false,
|
|
2452
|
-
getError: () => null,
|
|
2453
|
-
setSelectedEvent: () => {
|
|
2454
|
-
},
|
|
2455
|
-
refreshEvents: async () => {
|
|
2456
|
-
},
|
|
2457
|
-
subscribe: () => () => {
|
|
2458
|
-
}
|
|
2459
|
-
// No-op subscribe/unsubscribe for fallback
|
|
2460
|
-
};
|
|
2461
|
-
}
|
|
2361
|
+
const eventService = useEventService();
|
|
2462
2362
|
const currentUser = authService.getUser();
|
|
2463
2363
|
const currentSession = authService.getSession();
|
|
2464
2364
|
const isAuth = !!(currentUser && currentSession);
|
|
2465
|
-
const supabase =
|
|
2466
|
-
const [appId, setAppId] =
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
hasSession: !!currentSession,
|
|
2472
|
-
isAuth
|
|
2473
|
-
});
|
|
2474
|
-
}, [currentUser?.id, currentSession?.access_token, isAuth, authService]);
|
|
2475
|
-
const isResolvingAppIdRef = useRef9(false);
|
|
2476
|
-
const resolvedAppIdRef = useRef9(void 0);
|
|
2477
|
-
const resolvedUserIdRef = useRef9(void 0);
|
|
2478
|
-
useEffect10(() => {
|
|
2365
|
+
const supabase = useMemo(() => supabaseClientProp, [supabaseClientProp]);
|
|
2366
|
+
const [appId, setAppId] = useState(void 0);
|
|
2367
|
+
const isResolvingAppIdRef = useRef(false);
|
|
2368
|
+
const resolvedAppIdRef = useRef(void 0);
|
|
2369
|
+
const resolvedUserIdRef = useRef(void 0);
|
|
2370
|
+
useEffect(() => {
|
|
2479
2371
|
if (!isAuth) {
|
|
2480
2372
|
resolvedAppIdRef.current = void 0;
|
|
2481
2373
|
resolvedUserIdRef.current = void 0;
|
|
@@ -2494,7 +2386,7 @@ function UnifiedAuthContextProvider({
|
|
|
2494
2386
|
resolvedUserIdRef.current = currentUserId;
|
|
2495
2387
|
const userId = currentUserId;
|
|
2496
2388
|
const appNameValue = appName;
|
|
2497
|
-
import(
|
|
2389
|
+
import('./api-Y4MQWOFW.js').then(async ({ resolveAppContext, setupRBAC: setupRBAC2 }) => {
|
|
2498
2390
|
try {
|
|
2499
2391
|
setupRBAC2(supabase);
|
|
2500
2392
|
const result = await resolveAppContext({
|
|
@@ -2524,8 +2416,8 @@ function UnifiedAuthContextProvider({
|
|
|
2524
2416
|
});
|
|
2525
2417
|
}
|
|
2526
2418
|
}, [isAuth, currentUser?.id, supabase, appName]);
|
|
2527
|
-
const [, forceUpdate] =
|
|
2528
|
-
const forceUpdateTimeoutRef =
|
|
2419
|
+
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
2420
|
+
const forceUpdateTimeoutRef = useRef(null);
|
|
2529
2421
|
const debouncedForceUpdate = useCallback(() => {
|
|
2530
2422
|
if (forceUpdateTimeoutRef.current) {
|
|
2531
2423
|
clearTimeout(forceUpdateTimeoutRef.current);
|
|
@@ -2535,17 +2427,17 @@ function UnifiedAuthContextProvider({
|
|
|
2535
2427
|
forceUpdateTimeoutRef.current = null;
|
|
2536
2428
|
}, 100);
|
|
2537
2429
|
}, [forceUpdate]);
|
|
2538
|
-
const authServiceRef =
|
|
2539
|
-
const organisationServiceRef =
|
|
2540
|
-
const eventServiceRef =
|
|
2541
|
-
const inactivityServiceRef =
|
|
2542
|
-
|
|
2430
|
+
const authServiceRef = useRef(authService);
|
|
2431
|
+
const organisationServiceRef = useRef(organisationService);
|
|
2432
|
+
const eventServiceRef = useRef(eventService);
|
|
2433
|
+
const inactivityServiceRef = useRef(inactivityService);
|
|
2434
|
+
useEffect(() => {
|
|
2543
2435
|
authServiceRef.current = authService;
|
|
2544
2436
|
organisationServiceRef.current = organisationService;
|
|
2545
2437
|
eventServiceRef.current = eventService;
|
|
2546
2438
|
inactivityServiceRef.current = inactivityService;
|
|
2547
2439
|
}, [authService, organisationService, eventService, inactivityService]);
|
|
2548
|
-
|
|
2440
|
+
useEffect(() => {
|
|
2549
2441
|
const unsubscribeAuth = authServiceRef.current.subscribe(debouncedForceUpdate);
|
|
2550
2442
|
const unsubscribeOrg = organisationServiceRef.current.subscribe(debouncedForceUpdate);
|
|
2551
2443
|
const unsubscribeEvent = eventServiceRef.current.subscribe(debouncedForceUpdate);
|
|
@@ -2575,19 +2467,19 @@ function UnifiedAuthContextProvider({
|
|
|
2575
2467
|
const rawEvents = eventService.getEvents();
|
|
2576
2468
|
const rawOrganisations = organisationService.getOrganisations();
|
|
2577
2469
|
const rawUserMemberships = organisationService.getUserMemberships();
|
|
2578
|
-
const events =
|
|
2470
|
+
const events = useMemo(() => {
|
|
2579
2471
|
return rawEvents;
|
|
2580
2472
|
}, [
|
|
2581
2473
|
// Create dependency string from event IDs - only changes when events actually change
|
|
2582
2474
|
rawEvents.map((e) => e.event_id || e.id).join(",")
|
|
2583
2475
|
]);
|
|
2584
|
-
const organisations =
|
|
2476
|
+
const organisations = useMemo(() => {
|
|
2585
2477
|
return rawOrganisations;
|
|
2586
2478
|
}, [
|
|
2587
2479
|
// Create dependency string from organisation IDs - only changes when orgs actually change
|
|
2588
2480
|
rawOrganisations.map((o) => o.id).join(",")
|
|
2589
2481
|
]);
|
|
2590
|
-
const userMemberships =
|
|
2482
|
+
const userMemberships = useMemo(() => {
|
|
2591
2483
|
return rawUserMemberships;
|
|
2592
2484
|
}, [
|
|
2593
2485
|
// Create dependency string from membership IDs - only changes when memberships actually change
|
|
@@ -2601,7 +2493,7 @@ function UnifiedAuthContextProvider({
|
|
|
2601
2493
|
const timeRemaining = inactivityService.getTimeRemaining();
|
|
2602
2494
|
const showWarning = inactivityService.isWarningShown();
|
|
2603
2495
|
const isTracking = inactivityService.isTracking();
|
|
2604
|
-
const inactivityState =
|
|
2496
|
+
const inactivityState = useMemo(() => ({
|
|
2605
2497
|
showInactivityWarning,
|
|
2606
2498
|
inactivityTimeRemaining,
|
|
2607
2499
|
isIdle,
|
|
@@ -2638,7 +2530,7 @@ function UnifiedAuthContextProvider({
|
|
|
2638
2530
|
const handleIdleLogout = () => inactivityService.handleIdleLogout();
|
|
2639
2531
|
const handleStaySignedIn = () => inactivityService.handleStaySignedIn();
|
|
2640
2532
|
const handleSignOutNow = () => inactivityService.handleSignOutNow();
|
|
2641
|
-
const prevStateRef =
|
|
2533
|
+
const prevStateRef = useRef(null);
|
|
2642
2534
|
const isDev = import.meta.env.DEV || import.meta.env.MODE === "development";
|
|
2643
2535
|
if (isDev) {
|
|
2644
2536
|
const currentState = {
|
|
@@ -2651,7 +2543,7 @@ function UnifiedAuthContextProvider({
|
|
|
2651
2543
|
prevStateRef.current = currentState;
|
|
2652
2544
|
}
|
|
2653
2545
|
}
|
|
2654
|
-
const contextValue =
|
|
2546
|
+
const contextValue = useMemo(() => {
|
|
2655
2547
|
return {
|
|
2656
2548
|
// Auth state
|
|
2657
2549
|
user: currentUser,
|
|
@@ -2769,7 +2661,7 @@ function UnifiedAuthContextProvider({
|
|
|
2769
2661
|
handleStaySignedIn,
|
|
2770
2662
|
handleSignOutNow
|
|
2771
2663
|
]);
|
|
2772
|
-
return /* @__PURE__ */
|
|
2664
|
+
return /* @__PURE__ */ jsx(UnifiedAuthContext.Provider, { value: contextValue, children });
|
|
2773
2665
|
}
|
|
2774
2666
|
function EventServiceProviderWrapper({
|
|
2775
2667
|
children,
|
|
@@ -2781,15 +2673,9 @@ function EventServiceProviderWrapper({
|
|
|
2781
2673
|
const { selectedOrganisation } = useOrganisations();
|
|
2782
2674
|
const setSelectedEventId = useCallback(() => {
|
|
2783
2675
|
}, []);
|
|
2784
|
-
|
|
2785
|
-
logger.debug("EventServiceProviderWrapper", "Rendering with props", {
|
|
2786
|
-
hasUser: !!user,
|
|
2787
|
-
userId: user?.id,
|
|
2788
|
-
hasSession: !!session,
|
|
2789
|
-
selectedOrganisationId: selectedOrganisation?.id
|
|
2790
|
-
});
|
|
2676
|
+
useEffect(() => {
|
|
2791
2677
|
}, [user?.id, session?.access_token, selectedOrganisation?.id]);
|
|
2792
|
-
return /* @__PURE__ */
|
|
2678
|
+
return /* @__PURE__ */ jsx(
|
|
2793
2679
|
EventServiceProvider,
|
|
2794
2680
|
{
|
|
2795
2681
|
supabaseClient,
|
|
@@ -2816,17 +2702,12 @@ function ServiceAwareProviders({
|
|
|
2816
2702
|
dangerouslyDisableInactivity
|
|
2817
2703
|
}) {
|
|
2818
2704
|
const authService = useAuthService();
|
|
2819
|
-
const [userState, setUserState] =
|
|
2820
|
-
const [sessionState, setSessionState] =
|
|
2821
|
-
|
|
2705
|
+
const [userState, setUserState] = useState(() => authService.getUser());
|
|
2706
|
+
const [sessionState, setSessionState] = useState(() => authService.getSession());
|
|
2707
|
+
useEffect(() => {
|
|
2822
2708
|
const unsubscribe = authService.subscribe(() => {
|
|
2823
2709
|
const newUser = authService.getUser();
|
|
2824
2710
|
const newSession = authService.getSession();
|
|
2825
|
-
logger.debug("ServiceAwareProviders", "Auth service notified, updating state", {
|
|
2826
|
-
hasUser: !!newUser,
|
|
2827
|
-
userId: newUser?.id,
|
|
2828
|
-
hasSession: !!newSession
|
|
2829
|
-
});
|
|
2830
2711
|
setUserState(newUser);
|
|
2831
2712
|
setSessionState(newSession);
|
|
2832
2713
|
});
|
|
@@ -2834,28 +2715,20 @@ function ServiceAwareProviders({
|
|
|
2834
2715
|
}, [authService]);
|
|
2835
2716
|
const user = userState;
|
|
2836
2717
|
const session = sessionState;
|
|
2837
|
-
|
|
2838
|
-
logger.debug("ServiceAwareProviders", `User/session state [AuthService ID:${authService.getInstanceId?.() || "unknown"}]`, {
|
|
2839
|
-
hasUser: !!user,
|
|
2840
|
-
userId: user?.id,
|
|
2841
|
-
hasSession: !!session,
|
|
2842
|
-
sessionToken: session?.access_token ? "present" : "missing"
|
|
2843
|
-
});
|
|
2844
|
-
}, [user?.id, session?.access_token, authService]);
|
|
2845
|
-
return /* @__PURE__ */ jsx5(
|
|
2718
|
+
return /* @__PURE__ */ jsx(
|
|
2846
2719
|
OrganisationServiceProvider,
|
|
2847
2720
|
{
|
|
2848
2721
|
supabaseClient,
|
|
2849
2722
|
user,
|
|
2850
2723
|
session,
|
|
2851
|
-
children: /* @__PURE__ */
|
|
2724
|
+
children: /* @__PURE__ */ jsx(
|
|
2852
2725
|
EventServiceProviderWrapper,
|
|
2853
2726
|
{
|
|
2854
2727
|
supabaseClient,
|
|
2855
2728
|
user,
|
|
2856
2729
|
session,
|
|
2857
2730
|
appName,
|
|
2858
|
-
children: /* @__PURE__ */
|
|
2731
|
+
children: /* @__PURE__ */ jsx(
|
|
2859
2732
|
InactivityServiceProvider,
|
|
2860
2733
|
{
|
|
2861
2734
|
supabaseClient,
|
|
@@ -2864,7 +2737,7 @@ function ServiceAwareProviders({
|
|
|
2864
2737
|
idleTimeoutMs,
|
|
2865
2738
|
warnBeforeMs,
|
|
2866
2739
|
onIdleLogout,
|
|
2867
|
-
children: /* @__PURE__ */
|
|
2740
|
+
children: /* @__PURE__ */ jsx(
|
|
2868
2741
|
UnifiedAuthContextProvider,
|
|
2869
2742
|
{
|
|
2870
2743
|
appName,
|
|
@@ -2903,8 +2776,8 @@ function UnifiedAuthProvider({
|
|
|
2903
2776
|
renderInactivityWarning,
|
|
2904
2777
|
dangerouslyDisableInactivity = false
|
|
2905
2778
|
}) {
|
|
2906
|
-
const clientRef =
|
|
2907
|
-
|
|
2779
|
+
const clientRef = useRef(supabaseClient);
|
|
2780
|
+
useEffect(() => {
|
|
2908
2781
|
if (clientRef.current !== supabaseClient) {
|
|
2909
2782
|
logger.warn("UnifiedAuthProvider", "Supabase client reference changed - this may indicate multiple client instances are being created", {
|
|
2910
2783
|
previousClient: clientRef.current,
|
|
@@ -2912,8 +2785,6 @@ function UnifiedAuthProvider({
|
|
|
2912
2785
|
note: 'Ensure you create the Supabase client once and reuse it. Creating multiple clients can cause performance issues and the "Multiple GoTrueClient instances" warning.'
|
|
2913
2786
|
});
|
|
2914
2787
|
clientRef.current = supabaseClient;
|
|
2915
|
-
} else {
|
|
2916
|
-
logger.debug("UnifiedAuthProvider", "Supabase client reference is stable");
|
|
2917
2788
|
}
|
|
2918
2789
|
}, [supabaseClient]);
|
|
2919
2790
|
if (supabaseClient && !isRBACInitialized()) {
|
|
@@ -2924,7 +2795,7 @@ function UnifiedAuthProvider({
|
|
|
2924
2795
|
logger.error("UnifiedAuthProvider", "Failed to initialize RBAC", err);
|
|
2925
2796
|
}
|
|
2926
2797
|
}
|
|
2927
|
-
return /* @__PURE__ */
|
|
2798
|
+
return /* @__PURE__ */ jsx(AuthServiceProvider, { supabaseClient, appName, children: /* @__PURE__ */ jsx(
|
|
2928
2799
|
ServiceAwareProviders,
|
|
2929
2800
|
{
|
|
2930
2801
|
supabaseClient,
|
|
@@ -2942,23 +2813,4 @@ function UnifiedAuthProvider({
|
|
|
2942
2813
|
) });
|
|
2943
2814
|
}
|
|
2944
2815
|
|
|
2945
|
-
export {
|
|
2946
|
-
AuthServiceContext,
|
|
2947
|
-
AuthServiceProvider,
|
|
2948
|
-
OrganisationServiceContext,
|
|
2949
|
-
OrganisationServiceProvider,
|
|
2950
|
-
EventServiceContext,
|
|
2951
|
-
EventServiceProvider,
|
|
2952
|
-
InactivityServiceContext,
|
|
2953
|
-
InactivityServiceProvider,
|
|
2954
|
-
useAuthService,
|
|
2955
|
-
useOrganisationService,
|
|
2956
|
-
useOrganisations,
|
|
2957
|
-
useEventService,
|
|
2958
|
-
useInactivityService,
|
|
2959
|
-
useSessionRestoration,
|
|
2960
|
-
UnifiedAuthContext,
|
|
2961
|
-
useUnifiedAuth,
|
|
2962
|
-
UnifiedAuthProvider
|
|
2963
|
-
};
|
|
2964
|
-
//# sourceMappingURL=chunk-AVMLPIM7.js.map
|
|
2816
|
+
export { AuthServiceContext, AuthServiceProvider, EventServiceContext, EventServiceProvider, InactivityServiceContext, InactivityServiceProvider, OrganisationServiceContext, OrganisationServiceProvider, UnifiedAuthContext, UnifiedAuthProvider, useAuthService, useEventService, useInactivityService, useOrganisationService, useOrganisations, useSessionRestoration, useUnifiedAuth };
|