@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
|
@@ -37,18 +37,20 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
37
37
|
restorationError: null,
|
|
38
38
|
};
|
|
39
39
|
private restorationTimeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
40
|
-
|
|
40
|
+
// Increased timeout to handle hard refresh scenarios where localStorage access
|
|
41
|
+
// and session restoration may take longer, especially with organisation/event context
|
|
42
|
+
private readonly restorationTimeoutMs = 10000; // 10 seconds (increased from 5)
|
|
41
43
|
private restorationStartTime: number | null = null;
|
|
42
44
|
private appName: string | undefined = undefined;
|
|
43
45
|
private errorHandler: ((event: ErrorEvent) => void) | null = null;
|
|
44
46
|
private unhandledRejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;
|
|
47
|
+
private wasAuthenticatedRef: boolean = false; // Track previous auth state to detect transitions
|
|
45
48
|
|
|
46
49
|
constructor(supabaseClient: SupabaseClient, appName?: string) {
|
|
47
50
|
super();
|
|
48
51
|
this.instanceId = ++AuthService.instanceCount;
|
|
49
52
|
this.supabaseClient = supabaseClient;
|
|
50
53
|
this.appName = appName;
|
|
51
|
-
logger.debug('AuthService', `Instance created [ID:${this.instanceId}]`, { appName });
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
getInstanceId(): number {
|
|
@@ -57,11 +59,8 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
57
59
|
|
|
58
60
|
// Auth state getters
|
|
59
61
|
getUser(): User | null {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
} else {
|
|
63
|
-
logger.debug('AuthService', `getUser() [ID:${this.instanceId}] returning null`);
|
|
64
|
-
}
|
|
62
|
+
// Removed debug logging - getUser() is called frequently and state changes
|
|
63
|
+
// are already logged in the auth state change handler
|
|
65
64
|
return this.user;
|
|
66
65
|
}
|
|
67
66
|
|
|
@@ -112,6 +111,15 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
112
111
|
this.authError = null;
|
|
113
112
|
this.user = data.user;
|
|
114
113
|
this.session = data.session;
|
|
114
|
+
|
|
115
|
+
// Clear persistence immediately on successful login
|
|
116
|
+
// This prevents dialogs/forms/datatables from auto-opening with stale state
|
|
117
|
+
// We clear here synchronously before components can mount and check persisted state
|
|
118
|
+
// Also clear old unscoped keys to prevent data leakage
|
|
119
|
+
if (!this.wasAuthenticatedRef && data.user) {
|
|
120
|
+
this.clearPersistenceOnLogin(null, true);
|
|
121
|
+
this.wasAuthenticatedRef = true;
|
|
122
|
+
}
|
|
115
123
|
}
|
|
116
124
|
|
|
117
125
|
this.notify();
|
|
@@ -151,6 +159,14 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
151
159
|
this.authError = null;
|
|
152
160
|
this.user = data.user;
|
|
153
161
|
this.session = data.session;
|
|
162
|
+
|
|
163
|
+
// Clear persistence immediately on successful signup/login
|
|
164
|
+
// This prevents dialogs/forms/datatables from auto-opening with stale state
|
|
165
|
+
// Also clear old unscoped keys to prevent data leakage
|
|
166
|
+
if (!this.wasAuthenticatedRef && data.user) {
|
|
167
|
+
this.clearPersistenceOnLogin(null, true);
|
|
168
|
+
this.wasAuthenticatedRef = true;
|
|
169
|
+
}
|
|
154
170
|
}
|
|
155
171
|
|
|
156
172
|
this.notify();
|
|
@@ -179,6 +195,14 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
179
195
|
try {
|
|
180
196
|
const { error } = await this.supabaseClient.auth.signOut();
|
|
181
197
|
|
|
198
|
+
// Clear sessionStorage on logout
|
|
199
|
+
try {
|
|
200
|
+
sessionStorage.clear();
|
|
201
|
+
} catch (storageError) {
|
|
202
|
+
// Ignore storage errors (e.g., in private browsing mode)
|
|
203
|
+
logger.warn('AuthService', 'Failed to clear sessionStorage', { error: storageError });
|
|
204
|
+
}
|
|
205
|
+
|
|
182
206
|
if (error) {
|
|
183
207
|
this.authError = error;
|
|
184
208
|
} else {
|
|
@@ -190,6 +214,14 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
190
214
|
this.notify();
|
|
191
215
|
return { user: null, session: null, error };
|
|
192
216
|
} catch (error) {
|
|
217
|
+
// Clear sessionStorage even on error
|
|
218
|
+
try {
|
|
219
|
+
sessionStorage.clear();
|
|
220
|
+
} catch (storageError) {
|
|
221
|
+
// Ignore storage errors (e.g., in private browsing mode)
|
|
222
|
+
logger.warn('AuthService', 'Failed to clear sessionStorage', { error: storageError });
|
|
223
|
+
}
|
|
224
|
+
|
|
193
225
|
// Convert regular Error to AuthError if needed
|
|
194
226
|
const authError = error instanceof AuthError
|
|
195
227
|
? error
|
|
@@ -400,6 +432,56 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
400
432
|
}
|
|
401
433
|
}
|
|
402
434
|
|
|
435
|
+
/**
|
|
436
|
+
* Clear pace-core persistence entries from sessionStorage
|
|
437
|
+
* This includes dialog, form, and datatable persistence
|
|
438
|
+
*
|
|
439
|
+
* @param userId - Optional user ID to clear only that user's persistence.
|
|
440
|
+
* If not provided, clears all pace-core persistence (for user changes).
|
|
441
|
+
* @param clearUnscoped - If true, also clears old unscoped keys (without :user: prefix)
|
|
442
|
+
*/
|
|
443
|
+
private clearPersistenceOnLogin(userId?: string | null, clearUnscoped: boolean = true): void {
|
|
444
|
+
if (typeof window === 'undefined' || !window.sessionStorage) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
try {
|
|
449
|
+
const keysToRemove: string[] = [];
|
|
450
|
+
|
|
451
|
+
// Collect all pace-core persistence keys
|
|
452
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
|
453
|
+
const key = sessionStorage.key(i);
|
|
454
|
+
if (key && (
|
|
455
|
+
key.startsWith('pace-core:draft:') ||
|
|
456
|
+
key.startsWith('pace-core:dialog:')
|
|
457
|
+
)) {
|
|
458
|
+
// If userId is provided, only clear keys for that user
|
|
459
|
+
// Otherwise, clear all (for user changes or fresh login)
|
|
460
|
+
if (userId && !key.includes(`:user:${userId}`)) {
|
|
461
|
+
// Also clear old unscoped keys (without :user: prefix) if requested
|
|
462
|
+
if (clearUnscoped && !key.includes(':user:')) {
|
|
463
|
+
keysToRemove.push(key);
|
|
464
|
+
}
|
|
465
|
+
continue; // Skip keys that don't match this user
|
|
466
|
+
}
|
|
467
|
+
keysToRemove.push(key);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Remove all collected keys
|
|
472
|
+
keysToRemove.forEach(key => {
|
|
473
|
+
try {
|
|
474
|
+
sessionStorage.removeItem(key);
|
|
475
|
+
} catch (error) {
|
|
476
|
+
logger.warn('AuthService', `Failed to remove persistence key: ${key}`, error);
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
} catch (error) {
|
|
481
|
+
logger.warn('AuthService', `Failed to clear persistence [ID:${this.instanceId}]:`, error);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
403
485
|
private async setupAuthStateListener(): Promise<void> {
|
|
404
486
|
if (!this.supabaseClient) {
|
|
405
487
|
this.authLoading = false;
|
|
@@ -411,16 +493,20 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
411
493
|
const subscription = this.supabaseClient.auth.onAuthStateChange(
|
|
412
494
|
(event: AuthChangeEvent, session: SupabaseSession | null) => {
|
|
413
495
|
try {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
496
|
+
|
|
497
|
+
// Track authentication state transition
|
|
498
|
+
const wasAuthenticated = this.wasAuthenticatedRef;
|
|
499
|
+
const isNowAuthenticated = !!session?.user;
|
|
500
|
+
const previousUserId = this.user?.id || null;
|
|
501
|
+
const newUserId = session?.user?.id || null;
|
|
502
|
+
const userChanged = previousUserId !== null && newUserId !== null && previousUserId !== newUserId;
|
|
503
|
+
|
|
419
504
|
// Handle different auth events
|
|
420
505
|
if (event === 'SIGNED_OUT') {
|
|
421
506
|
this.session = null;
|
|
422
507
|
this.user = null;
|
|
423
508
|
this.authError = null;
|
|
509
|
+
this.wasAuthenticatedRef = false;
|
|
424
510
|
|
|
425
511
|
// Automatic session tracking (non-blocking)
|
|
426
512
|
if (session?.user) {
|
|
@@ -437,6 +523,19 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
437
523
|
this.authError = null;
|
|
438
524
|
}
|
|
439
525
|
|
|
526
|
+
// Clear persistence when:
|
|
527
|
+
// 1. Transitioning from unauthenticated to authenticated (fresh login) - clear all + old unscoped keys
|
|
528
|
+
// 2. User changes (different user logs in) - clear previous user's persistence + old unscoped keys
|
|
529
|
+
if (!wasAuthenticated && isNowAuthenticated && event === 'SIGNED_IN') {
|
|
530
|
+
// Fresh login - clear all persistence including old unscoped keys
|
|
531
|
+
this.clearPersistenceOnLogin(null, true);
|
|
532
|
+
} else if (userChanged && previousUserId) {
|
|
533
|
+
// User changed - clear previous user's persistence + old unscoped keys
|
|
534
|
+
this.clearPersistenceOnLogin(previousUserId, true);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
this.wasAuthenticatedRef = isNowAuthenticated;
|
|
538
|
+
|
|
440
539
|
// Automatic session tracking for login (non-blocking)
|
|
441
540
|
// Only track on SIGNED_IN, not TOKEN_REFRESHED (to avoid duplicate login records)
|
|
442
541
|
if (event === 'SIGNED_IN' && session?.user) {
|
|
@@ -446,10 +545,30 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
446
545
|
}
|
|
447
546
|
} else if (event === 'INITIAL_SESSION') {
|
|
448
547
|
if (session) {
|
|
548
|
+
const previousUserId = this.user?.id || null;
|
|
549
|
+
const newUserId = session.user?.id || null;
|
|
550
|
+
const userChanged = previousUserId !== null && newUserId !== null && previousUserId !== newUserId;
|
|
551
|
+
|
|
449
552
|
this.session = session;
|
|
450
553
|
this.user = session.user ?? null;
|
|
451
554
|
this.authError = null;
|
|
452
555
|
|
|
556
|
+
// Clear persistence if user changed (e.g., different user's session restored)
|
|
557
|
+
// This prevents data leakage when a different user's session is restored
|
|
558
|
+
if (userChanged && previousUserId) {
|
|
559
|
+
// Clear previous user's persistence + old unscoped keys
|
|
560
|
+
this.clearPersistenceOnLogin(previousUserId, true);
|
|
561
|
+
} else if (!wasAuthenticated && !!session.user) {
|
|
562
|
+
// Fresh login on INITIAL_SESSION - clear all persistence including old unscoped keys
|
|
563
|
+
this.clearPersistenceOnLogin(null, true);
|
|
564
|
+
}
|
|
565
|
+
// Don't clear persistence on INITIAL_SESSION for same user - this is just session restoration
|
|
566
|
+
// Persistence should only be cleared on actual SIGNED_IN events or user changes
|
|
567
|
+
// INITIAL_SESSION happens on page load/refresh, and we want to preserve
|
|
568
|
+
// dialog/form/datatable state across page refreshes for the same user
|
|
569
|
+
|
|
570
|
+
this.wasAuthenticatedRef = !!session.user;
|
|
571
|
+
|
|
453
572
|
// Reset restoration state if valid session arrives after earlier failure
|
|
454
573
|
// This clears stale errors when session eventually succeeds
|
|
455
574
|
const hasTimeoutError = this.sessionRestorationState.restorationError?.name === 'SessionRestorationTimeoutError';
|
|
@@ -460,6 +579,7 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
460
579
|
}
|
|
461
580
|
} else {
|
|
462
581
|
// No session in INITIAL_SESSION event - user is not authenticated
|
|
582
|
+
this.wasAuthenticatedRef = false;
|
|
463
583
|
// Finish restoration to clear loading state
|
|
464
584
|
if (this.sessionRestorationState.isRestoring) {
|
|
465
585
|
this.finishSessionRestoration();
|
|
@@ -471,11 +591,6 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
471
591
|
// before checking authentication state
|
|
472
592
|
this.authLoading = false;
|
|
473
593
|
|
|
474
|
-
// Final check: Ensure state matches what we just logged
|
|
475
|
-
logger.debug('AuthService', `State synchronized after INITIAL_SESSION [ID:${this.instanceId}]`, {
|
|
476
|
-
hasUser: !!this.user,
|
|
477
|
-
userId: this.user?.id
|
|
478
|
-
});
|
|
479
594
|
|
|
480
595
|
this.notify();
|
|
481
596
|
return; // Return early to avoid setting loading to false again below
|
|
@@ -484,12 +599,6 @@ export class AuthService extends BaseService implements IAuthService {
|
|
|
484
599
|
// For other events (SIGNED_IN, SIGNED_OUT, TOKEN_REFRESHED), set loading to false and notify
|
|
485
600
|
this.authLoading = false;
|
|
486
601
|
|
|
487
|
-
// Final check: Ensure state matches what we just logged
|
|
488
|
-
logger.debug('AuthService', `State synchronized after event [ID:${this.instanceId}]`, {
|
|
489
|
-
event,
|
|
490
|
-
hasUser: !!this.user,
|
|
491
|
-
userId: this.user?.id
|
|
492
|
-
});
|
|
493
602
|
|
|
494
603
|
this.notify();
|
|
495
604
|
} catch (error) {
|
|
@@ -59,11 +59,6 @@ export class EventService extends BaseService implements IEventService {
|
|
|
59
59
|
this.appName = appName;
|
|
60
60
|
this.selectedOrganisation = selectedOrganisation;
|
|
61
61
|
this.setSelectedEventId = setSelectedEventId;
|
|
62
|
-
logger.debug('EventService', `Instance created [ID:${this.instanceId}]`, {
|
|
63
|
-
appName,
|
|
64
|
-
hasUser: !!user,
|
|
65
|
-
userId: user?.id
|
|
66
|
-
});
|
|
67
62
|
}
|
|
68
63
|
|
|
69
64
|
getInstanceId(): number {
|
|
@@ -112,11 +107,6 @@ export class EventService extends BaseService implements IEventService {
|
|
|
112
107
|
this.userClearedEventRef = false;
|
|
113
108
|
this.hasAutoSelectedRef = false;
|
|
114
109
|
|
|
115
|
-
logger.debug('EventService', `User changed [ID:${this.instanceId}]`, {
|
|
116
|
-
previousUserId,
|
|
117
|
-
newUserId,
|
|
118
|
-
willInitialize: newUserId !== null
|
|
119
|
-
});
|
|
120
110
|
}
|
|
121
111
|
|
|
122
112
|
this.supabaseClient = supabaseClient;
|
|
@@ -142,10 +132,6 @@ export class EventService extends BaseService implements IEventService {
|
|
|
142
132
|
|
|
143
133
|
if (isRBACInitialized()) {
|
|
144
134
|
this.isSuperAdmin = await checkSuperAdmin(user.id as UUID);
|
|
145
|
-
logger.debug('EventService', 'Super admin status updated in updateDependencies', {
|
|
146
|
-
userId: user.id,
|
|
147
|
-
isSuperAdmin: this.isSuperAdmin
|
|
148
|
-
});
|
|
149
135
|
} else {
|
|
150
136
|
// RBAC not initialized - this should be rare since UnifiedAuthProvider initializes it synchronously
|
|
151
137
|
// Keep existing value (don't reset to false) to avoid clearing a previously determined super admin status
|
|
@@ -260,11 +246,6 @@ export class EventService extends BaseService implements IEventService {
|
|
|
260
246
|
});
|
|
261
247
|
// Reset the user cleared flag when selecting an event
|
|
262
248
|
this.userClearedEventRef = false;
|
|
263
|
-
logger.debug('EventService', 'Event selected', {
|
|
264
|
-
eventId: event.event_id,
|
|
265
|
-
eventName: event.event_name,
|
|
266
|
-
userClearedEventRef: this.userClearedEventRef
|
|
267
|
-
});
|
|
268
249
|
} else {
|
|
269
250
|
const previousEventId = this.selectedEvent?.event_id;
|
|
270
251
|
this.selectedEvent = null;
|
|
@@ -277,11 +258,6 @@ export class EventService extends BaseService implements IEventService {
|
|
|
277
258
|
this.hasAutoSelectedRef = false;
|
|
278
259
|
// Mark that user explicitly cleared the event to prevent auto-selection
|
|
279
260
|
this.userClearedEventRef = true;
|
|
280
|
-
logger.debug('EventService', 'Event cleared via setSelectedEvent(null)', {
|
|
281
|
-
previousEventId,
|
|
282
|
-
userClearedEventRef: this.userClearedEventRef,
|
|
283
|
-
stackTrace: new Error().stack
|
|
284
|
-
});
|
|
285
261
|
}
|
|
286
262
|
this.notify();
|
|
287
263
|
}
|
|
@@ -407,13 +383,11 @@ export class EventService extends BaseService implements IEventService {
|
|
|
407
383
|
protected async doInitialize(): Promise<void> {
|
|
408
384
|
// Skip if already initialized
|
|
409
385
|
if (this.isInitializedRef) {
|
|
410
|
-
logger.debug('EventService', 'Skipping initialization - already initialized');
|
|
411
386
|
return;
|
|
412
387
|
}
|
|
413
388
|
|
|
414
389
|
// Skip if already fetching
|
|
415
390
|
if (this.isFetchingRef) {
|
|
416
|
-
logger.debug('EventService', 'Skipping initialization - already fetching');
|
|
417
391
|
return;
|
|
418
392
|
}
|
|
419
393
|
|
|
@@ -430,27 +404,14 @@ export class EventService extends BaseService implements IEventService {
|
|
|
430
404
|
// For event-required apps, selectedOrganisation may be null (org derived from event)
|
|
431
405
|
// For org-required apps, selectedOrganisation is required
|
|
432
406
|
if (!this.user) {
|
|
433
|
-
logger.debug('EventService', 'Skipping initialization - no user');
|
|
434
407
|
return;
|
|
435
408
|
}
|
|
436
409
|
|
|
437
|
-
logger.debug('EventService', 'Initializing', {
|
|
438
|
-
userId: this.user.id,
|
|
439
|
-
appName: this.appName,
|
|
440
|
-
hasSelectedOrganisation: !!this.selectedOrganisation,
|
|
441
|
-
hasSupabaseClient: !!this.supabaseClient,
|
|
442
|
-
hasSession: !!this.session
|
|
443
|
-
});
|
|
444
|
-
|
|
445
410
|
// Initial setup - fetch events on initialization
|
|
446
411
|
await this.fetchEvents(false);
|
|
447
412
|
|
|
448
413
|
// Mark as initialized after successful fetch
|
|
449
414
|
this.isInitializedRef = true;
|
|
450
|
-
logger.debug('EventService', 'Initialization complete', {
|
|
451
|
-
eventsCount: this.events.length,
|
|
452
|
-
hasError: !!this.error
|
|
453
|
-
});
|
|
454
415
|
}
|
|
455
416
|
|
|
456
417
|
protected doCleanup(): void {
|
|
@@ -505,10 +466,6 @@ export class EventService extends BaseService implements IEventService {
|
|
|
505
466
|
userIsSuperAdmin = await checkSuperAdmin(this.user.id as UUID);
|
|
506
467
|
// Update cached value for future use
|
|
507
468
|
this.isSuperAdmin = userIsSuperAdmin;
|
|
508
|
-
logger.debug('EventService', 'Super admin check completed', {
|
|
509
|
-
userId: this.user.id,
|
|
510
|
-
isSuperAdmin: userIsSuperAdmin
|
|
511
|
-
});
|
|
512
469
|
} else {
|
|
513
470
|
// RBAC not initialized - this should be rare since UnifiedAuthProvider initializes it synchronously
|
|
514
471
|
// Use cached value from updateDependencies as fallback
|
|
@@ -544,10 +501,6 @@ export class EventService extends BaseService implements IEventService {
|
|
|
544
501
|
} else {
|
|
545
502
|
// No context available - pass null to get all accessible events via event-app roles
|
|
546
503
|
// This allows users with event-app roles to see their events even without org context
|
|
547
|
-
logger.debug('EventService', 'No organisation context available, fetching all accessible events', {
|
|
548
|
-
hasSelectedEvent: !!this.selectedEvent,
|
|
549
|
-
hasSelectedOrganisation: !!this.selectedOrganisation
|
|
550
|
-
});
|
|
551
504
|
organisationIdForRpc = null; // Will return events user has access to via event-app roles
|
|
552
505
|
}
|
|
553
506
|
}
|
|
@@ -580,14 +533,6 @@ export class EventService extends BaseService implements IEventService {
|
|
|
580
533
|
|
|
581
534
|
// Call the RPC function following the established pattern
|
|
582
535
|
// For super admins, pass null for p_organisation_id to see all events
|
|
583
|
-
logger.debug('EventService', 'Fetching events', {
|
|
584
|
-
userId: this.user.id,
|
|
585
|
-
organisationIdForRpc,
|
|
586
|
-
appName: this.appName,
|
|
587
|
-
hasSelectedEvent: !!this.selectedEvent,
|
|
588
|
-
hasSelectedOrganisation: !!this.selectedOrganisation,
|
|
589
|
-
isSuperAdmin: userIsSuperAdmin
|
|
590
|
-
});
|
|
591
536
|
|
|
592
537
|
let { data, error: rpcError } = await this.supabaseClient.rpc('data_user_events_get', {
|
|
593
538
|
p_user_id: this.user.id,
|
|
@@ -595,11 +540,6 @@ export class EventService extends BaseService implements IEventService {
|
|
|
595
540
|
p_app_name: this.appName
|
|
596
541
|
});
|
|
597
542
|
|
|
598
|
-
logger.debug('EventService', 'RPC response', {
|
|
599
|
-
dataLength: data?.length || 0,
|
|
600
|
-
hasError: !!rpcError,
|
|
601
|
-
error: rpcError
|
|
602
|
-
});
|
|
603
543
|
|
|
604
544
|
if (rpcError) {
|
|
605
545
|
logger.error('EventService', 'RPC error fetching events:', rpcError);
|
|
@@ -671,10 +611,7 @@ export class EventService extends BaseService implements IEventService {
|
|
|
671
611
|
this.setSelectedEventId?.(null);
|
|
672
612
|
// Restore the previous userClearedEventRef value - this was an automatic clear, not user-initiated
|
|
673
613
|
this.userClearedEventRef = previousUserClearedRef;
|
|
674
|
-
|
|
675
|
-
previousEventId: selectedEventId,
|
|
676
|
-
eventsCount: transformedEvents.length
|
|
677
|
-
});
|
|
614
|
+
// Cleared selected event - no longer in events list
|
|
678
615
|
}
|
|
679
616
|
}
|
|
680
617
|
|
|
@@ -685,62 +622,32 @@ export class EventService extends BaseService implements IEventService {
|
|
|
685
622
|
if (!skipLoadPersisted) {
|
|
686
623
|
const persistedEventLoaded = await this.loadPersistedEvent(transformedEvents);
|
|
687
624
|
|
|
688
|
-
logger.debug('EventService', 'Event selection check', {
|
|
689
|
-
persistedEventLoaded,
|
|
690
|
-
userClearedEventRef: this.userClearedEventRef,
|
|
691
|
-
eventsCount: transformedEvents.length,
|
|
692
|
-
hasSelectedEvent: !!this.selectedEvent
|
|
693
|
-
});
|
|
694
|
-
|
|
695
625
|
// If no persisted event was loaded and user hasn't explicitly cleared an event, auto-select the next event
|
|
696
626
|
if (!persistedEventLoaded && !this.userClearedEventRef) {
|
|
697
627
|
const nextEvent = this.getNextEventByDate(transformedEvents);
|
|
698
|
-
logger.debug('EventService', 'Auto-selection attempt', {
|
|
699
|
-
nextEventFound: !!nextEvent,
|
|
700
|
-
nextEventId: nextEvent?.event_id,
|
|
701
|
-
nextEventDate: nextEvent?.event_date
|
|
702
|
-
});
|
|
703
628
|
if (nextEvent) {
|
|
704
629
|
this.hasAutoSelectedRef = true;
|
|
705
630
|
// Use setSelectedEvent() to ensure consistent behavior
|
|
706
631
|
// Theme will be applied by useEventTheme() hook
|
|
707
632
|
this.setSelectedEvent(nextEvent);
|
|
708
|
-
logger.debug('EventService', 'Auto-selected next event', {
|
|
709
|
-
eventId: nextEvent.event_id,
|
|
710
|
-
eventName: nextEvent.event_name,
|
|
711
|
-
eventDate: nextEvent.event_date
|
|
712
|
-
});
|
|
713
|
-
} else {
|
|
714
|
-
logger.debug('EventService', 'No next event found for auto-selection', {
|
|
715
|
-
eventsCount: transformedEvents.length,
|
|
716
|
-
eventsWithDates: transformedEvents.filter(e => e.event_date).length
|
|
717
|
-
});
|
|
718
633
|
}
|
|
719
634
|
} else if (persistedEventLoaded) {
|
|
720
|
-
|
|
635
|
+
// Skipped auto-selection - persisted event loaded
|
|
721
636
|
} else if (this.userClearedEventRef) {
|
|
722
|
-
|
|
637
|
+
// Skipped auto-selection - user explicitly cleared event
|
|
723
638
|
}
|
|
724
639
|
} else {
|
|
725
640
|
// If skipping persisted event load, still do auto-selection for new users
|
|
726
641
|
if (!this.userClearedEventRef) {
|
|
727
642
|
const nextEvent = this.getNextEventByDate(transformedEvents);
|
|
728
|
-
logger.debug('EventService', 'Auto-selection attempt (skip persisted)', {
|
|
729
|
-
nextEventFound: !!nextEvent,
|
|
730
|
-
nextEventId: nextEvent?.event_id
|
|
731
|
-
});
|
|
732
643
|
if (nextEvent) {
|
|
733
644
|
this.hasAutoSelectedRef = true;
|
|
734
645
|
// Use setSelectedEvent() to ensure consistent behavior
|
|
735
646
|
// Theme will be applied by useEventTheme() hook
|
|
736
647
|
this.setSelectedEvent(nextEvent);
|
|
737
|
-
logger.debug('EventService', 'Auto-selected next event (skip persisted)', {
|
|
738
|
-
eventId: nextEvent.event_id,
|
|
739
|
-
eventName: nextEvent.event_name
|
|
740
|
-
});
|
|
741
648
|
}
|
|
742
649
|
} else {
|
|
743
|
-
|
|
650
|
+
// Skipped auto-selection (skip persisted) - user explicitly cleared event
|
|
744
651
|
}
|
|
745
652
|
}
|
|
746
653
|
}
|