@jmruthers/pace-core 0.5.68 → 0.5.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{DataTable-4IUY7BXB.js → DataTable-OSELOGMA.js} +6 -6
- package/dist/{PublicLoadingSpinner-DdKXTkCZ.d.ts → PublicLoadingSpinner-DLpF5bbs.d.ts} +78 -2
- package/dist/{chunk-OPCWH3A4.js → chunk-4YMVZ76F.js} +7 -6
- package/dist/chunk-4YMVZ76F.js.map +1 -0
- package/dist/{chunk-NN45OBIS.js → chunk-5G7JA3L5.js} +3 -5
- package/dist/{chunk-NN45OBIS.js.map → chunk-5G7JA3L5.js.map} +1 -1
- package/dist/{chunk-U6GPOF6J.js → chunk-5NV76BYF.js} +666 -110
- package/dist/chunk-5NV76BYF.js.map +1 -0
- package/dist/{chunk-D7ARGIA3.js → chunk-6RBH67W7.js} +23 -6
- package/dist/chunk-6RBH67W7.js.map +1 -0
- package/dist/{chunk-ZPG4XPV5.js → chunk-BHBMXMLT.js} +5 -7
- package/dist/chunk-BHBMXMLT.js.map +1 -0
- package/dist/{chunk-ZMS23NS5.js → chunk-FOT3WUV6.js} +3 -5
- package/dist/{chunk-ZMS23NS5.js.map → chunk-FOT3WUV6.js.map} +1 -1
- package/dist/{chunk-MOJXHWDE.js → chunk-GCUIIBLB.js} +382 -5
- package/dist/chunk-GCUIIBLB.js.map +1 -0
- package/dist/{chunk-PXWEDX7Y.js → chunk-KWQH4VO3.js} +3 -3
- package/dist/{chunk-ZPK5656W.js → chunk-O3NWNXDY.js} +4 -5
- package/dist/chunk-O3NWNXDY.js.map +1 -0
- package/dist/{chunk-KRCRNXPD.js → chunk-OTJUAYBG.js} +81 -18
- package/dist/chunk-OTJUAYBG.js.map +1 -0
- package/dist/chunk-SMJZMKYN.js +141 -0
- package/dist/chunk-SMJZMKYN.js.map +1 -0
- package/dist/{chunk-UYA6U6H7.js → chunk-V2TE7LOF.js} +4 -4
- package/dist/{chunk-L3RV2ALE.js → chunk-VKOCWWVY.js} +6 -1
- package/dist/{chunk-L3RV2ALE.js.map → chunk-VKOCWWVY.js.map} +1 -1
- package/dist/components.d.ts +4 -79
- package/dist/components.js +23 -581
- package/dist/components.js.map +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +9 -6
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +32 -19
- package/dist/index.js.map +1 -1
- package/dist/providers.js +6 -7
- package/dist/rbac/index.js +6 -6
- package/dist/styles/index.js +2 -2
- package/dist/theming/runtime.d.ts +4 -3
- package/dist/theming/runtime.js +3 -1
- package/dist/{usePublicRouteParams-CdoFxnJK.d.ts → usePublicRouteParams-Ua1Vz-HG.d.ts} +35 -1
- package/dist/utils.d.ts +4 -1
- package/dist/utils.js +3 -3
- package/docs/DOCUMENTATION_CHECKLIST.md +281 -0
- package/docs/README.md +22 -10
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +129 -0
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventContextType.md +7 -7
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/EventProviderProps.md +2 -2
- package/docs/api/interfaces/FileDisplayProps.md +107 -0
- package/docs/api/interfaces/FileMetadata.md +129 -0
- package/docs/api/interfaces/FileReference.md +118 -0
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +85 -0
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +2 -2
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContextType.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACProviderProps.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +228 -23
- package/docs/architecture/services.md +374 -0
- package/docs/best-practices/README.md +1 -1
- package/docs/best-practices/testing.md +1 -1
- package/docs/breaking-changes.md +182 -0
- package/docs/common-patterns.md +445 -0
- package/docs/core-concepts/authentication.md +26 -11
- package/docs/core-concepts/events.md +2 -0
- package/docs/core-concepts/organisations.md +2 -0
- package/docs/core-concepts/permissions.md +2 -0
- package/docs/{INDEX.md → documentation-index.md} +26 -38
- package/docs/faq.md +286 -0
- package/docs/{FILE_REFERENCE_SYSTEM.md → file-reference-system.md} +1 -1
- package/docs/getting-started/installation-guide.md +284 -0
- package/docs/getting-started/quick-start.md +8 -1
- package/docs/implementation-guides/app-layout.md +3 -1
- package/docs/implementation-guides/data-tables.md +2 -0
- package/docs/implementation-guides/dynamic-colors.md +47 -2
- package/docs/implementation-guides/event-theming-summary.md +220 -0
- package/docs/implementation-guides/forms.md +9 -7
- package/docs/implementation-guides/navigation.md +2 -0
- package/docs/migration/service-architecture.md +351 -0
- package/docs/rbac/README-rbac-rls-integration.md +2 -2
- package/docs/rbac/README.md +1 -1
- package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
- package/docs/rbac/quick-start.md +2 -0
- package/docs/rbac/rbac-rls-integration.md +2 -2
- package/docs/style-guide.md +136 -1
- package/docs/testing/README.md +1 -1
- package/docs/troubleshooting/authentication-issues.md +334 -0
- package/docs/troubleshooting/common-issues.md +2 -0
- package/docs/troubleshooting/styling-issues.md +199 -144
- package/docs/usage.md +23 -2
- package/package.json +3 -2
- package/src/__tests__/{TESTING_GUIDELINES.md → TEST_GUIDE_CURSOR.md} +20 -0
- package/src/__tests__/TEST_GUIDE_HUMAN.md +103 -0
- package/src/__tests__/fixtures/test-data.ts +90 -0
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +260 -0
- package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +224 -0
- package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +273 -0
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +98 -0
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +436 -0
- package/src/__tests__/helpers/__tests__/timer-utils.test.ts +371 -0
- package/src/__tests__/helpers/component-test-utils.tsx +14 -4
- package/src/__tests__/helpers/optimized-test-setup.ts +68 -0
- package/src/__tests__/helpers/test-providers.tsx +329 -0
- package/src/__tests__/helpers/test-utils.tsx +91 -45
- package/src/__tests__/helpers/timer-utils.ts +71 -0
- package/src/__tests__/hooks/usePermissions.test.ts +1 -5
- package/src/__tests__/integration/UserProfile.test.tsx +1 -5
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +42 -12
- package/src/__tests__/setup.ts +34 -28
- package/src/components/Alert/Alert.test.tsx +1 -5
- package/src/components/Avatar/Avatar.test.tsx +1 -5
- package/src/components/Button/Button.test.tsx +4 -20
- package/src/components/Card/Card.test.tsx +1 -5
- package/src/components/Checkbox/Checkbox.test.tsx +1 -5
- package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -5
- package/src/components/DataTable/__tests__/DataTable.test.tsx +45 -49
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +1 -5
- package/src/components/DataTable/__tests__/styles.test.ts +382 -0
- package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +409 -0
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +634 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +519 -0
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +714 -0
- package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +592 -0
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +354 -0
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +539 -0
- package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +1 -5
- package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +1 -8
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +34 -38
- package/src/components/Footer/Footer.test.tsx +1 -5
- package/src/components/Form/Form.test.tsx +22 -35
- package/src/components/Header/Header.test.tsx +1 -9
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +1 -5
- package/src/components/Input/Input.test.tsx +2 -10
- package/src/components/LoginForm/LoginForm.test.tsx +1 -5
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +24 -24
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +1 -6
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +6 -16
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +1 -4
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +1 -5
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +1 -7
- package/src/components/PasswordReset/PasswordChangeForm.test.tsx +1 -9
- package/src/components/PasswordReset/PasswordResetForm.test.tsx +1 -9
- package/src/components/PublicLayout/PublicErrorBoundary.tsx +4 -5
- package/src/components/PublicLayout/PublicPageHeader.tsx +13 -9
- package/src/components/PublicLayout/__tests__/EventLogo.test.tsx +666 -0
- package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +457 -0
- package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +393 -0
- package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +351 -0
- package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +374 -0
- package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +388 -0
- package/src/components/Select/Select.bug-test.tsx +69 -0
- package/src/components/Select/Select.refactored.tsx +497 -0
- package/src/components/Select/Select.test.tsx +42 -49
- package/src/components/Select/Select.tsx +5 -2
- package/src/components/Select/hooks.ts +254 -0
- package/src/components/Switch/Switch.test.tsx +1 -5
- package/src/components/Table/__tests__/Table.test.tsx +775 -0
- package/src/components/Toast/Toast.test.tsx +15 -8
- package/src/components/Tooltip/Tooltip.test.tsx +1 -5
- package/src/components/UserMenu/UserMenu.test.tsx +3 -15
- package/src/components/__tests__/FileDisplay.test.tsx +575 -0
- package/src/components/__tests__/FileUpload.test.tsx +446 -0
- package/src/components/__tests__/SuperAdminGuard.test.tsx +422 -354
- package/src/hooks/__tests__/ServiceHooks.test.tsx +613 -0
- package/src/hooks/__tests__/hooks.integration.test.tsx +1 -10
- package/src/hooks/__tests__/useApiFetch.unit.test.ts +10 -14
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +307 -0
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +1 -6
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +1 -5
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +6 -9
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +321 -0
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +583 -0
- package/src/hooks/__tests__/usePublicEventLogo.unit.test.ts +640 -0
- package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +435 -0
- package/src/hooks/__tests__/useRBAC.unit.test.ts +10 -10
- package/src/hooks/__tests__/useStorage.unit.test.ts +751 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/public/usePublicEvent.ts +30 -9
- package/src/hooks/public/usePublicRouteParams.ts +13 -3
- package/src/hooks/services/useAuth.ts +50 -0
- package/src/hooks/services/useAuthService.ts +30 -0
- package/src/hooks/services/useCurrentEvent.ts +36 -0
- package/src/hooks/services/useCurrentOrganisation.ts +52 -0
- package/src/hooks/services/useEventService.ts +30 -0
- package/src/hooks/services/useInactivityService.ts +30 -0
- package/src/hooks/services/useOrganisationService.ts +30 -0
- package/src/hooks/services/usePermissions.ts +70 -0
- package/src/hooks/services/useRBACService.ts +30 -0
- package/src/hooks/useCounter.test.ts +1 -5
- package/src/hooks/useEventTheme.ts +86 -0
- package/src/hooks/useOrganisationPermissions.test.ts +2 -5
- package/src/hooks/useOrganisationSecurity.test.ts +1 -5
- package/src/hooks/usePermissionCache.test.ts +1 -5
- package/src/hooks/usePermissionCheck.ts +150 -0
- package/src/hooks/useSecureDataAccess.test.ts +1 -5
- package/src/index.ts +7 -0
- package/src/providers/EventProvider.tsx +58 -2
- package/src/providers/OrganisationProvider.test.tsx +1 -5
- package/src/providers/OrganisationProvider.tsx +56 -4
- package/src/providers/UnifiedAuthProvider.test.tsx +1 -5
- package/src/providers/__tests__/AuthProvider.test.tsx +105 -439
- package/src/providers/__tests__/AuthProvider.test.tsx.backup +771 -0
- package/src/providers/__tests__/EventProvider.test.tsx +211 -110
- package/src/providers/__tests__/EventProvider.test.tsx.backup +824 -0
- package/src/providers/__tests__/InactivityProvider.test.tsx +1 -5
- package/src/providers/__tests__/OrganisationProvider.test.tsx +97 -261
- package/src/providers/__tests__/OrganisationProvider.test.tsx.backup +820 -0
- package/src/providers/__tests__/ServiceProviders.test.tsx +477 -0
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +72 -504
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup +911 -0
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup2 +166 -0
- package/src/providers/services/AuthServiceProvider.tsx +65 -0
- package/src/providers/services/EventServiceProvider.tsx +83 -0
- package/src/providers/services/InactivityServiceProvider.tsx +83 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +77 -0
- package/src/providers/services/RBACServiceProvider.tsx +79 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +368 -0
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +210 -0
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +269 -0
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +892 -0
- package/src/rbac/__tests__/engine.comprehensive.test.ts +954 -0
- package/src/rbac/__tests__/integration.authflow.test.tsx +1 -5
- package/src/rbac/__tests__/integration.navigation.test.tsx +1 -4
- package/src/rbac/__tests__/rbac-core.test.tsx +2 -7
- package/src/rbac/__tests__/rbac-functions.test.ts +1 -9
- package/src/rbac/__tests__/rbac-integration.test.ts +1 -9
- package/src/rbac/api.test.ts +1 -9
- package/src/rbac/cache.test.ts +10 -8
- package/src/rbac/cli/__tests__/policy-manager.test.ts +339 -0
- package/src/rbac/components/EnhancedNavigationMenu.test.tsx +1 -5
- package/src/rbac/components/NavigationProvider.test.tsx +1 -5
- package/src/rbac/components/PagePermissionProvider.test.tsx +1 -5
- package/src/rbac/components/SecureDataProvider.test.tsx +1 -5
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +25 -29
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +27 -30
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +23 -27
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +18 -22
- package/src/rbac/config.test.ts +1 -5
- package/src/rbac/hooks/useCan.test.ts +262 -9
- package/src/rbac/hooks/usePermissions.test.ts +246 -6
- package/src/rbac/hooks/useRBAC.simple.test.ts +1 -5
- package/src/rbac/hooks/useRBAC.test.ts +472 -198
- package/src/rbac/providers/__tests__/RBACProvider.test.tsx +1 -9
- package/src/services/AuthService.ts +416 -0
- package/src/services/EventService.ts +366 -0
- package/src/services/InactivityService.ts +388 -0
- package/src/services/OrganisationService.ts +592 -0
- package/src/services/RBACService.ts +522 -0
- package/src/services/__tests__/AuthService.test.ts +356 -0
- package/src/services/__tests__/BaseService.test.ts +314 -0
- package/src/services/__tests__/EventService.test.ts +489 -0
- package/src/services/__tests__/InactivityService.test.ts +403 -0
- package/src/services/__tests__/OrganisationService.test.ts +660 -0
- package/src/services/__tests__/RBACService.test.ts +492 -0
- package/src/services/base/BaseService.ts +87 -0
- package/src/services/interfaces/IAuthService.ts +39 -0
- package/src/services/interfaces/IEventService.ts +30 -0
- package/src/services/interfaces/IInactivityService.ts +31 -0
- package/src/services/interfaces/IOrganisationService.ts +41 -0
- package/src/services/interfaces/IRBACService.ts +62 -0
- package/src/theming/__tests__/runtime.test.ts +560 -0
- package/src/theming/runtime.ts +71 -28
- package/src/types/__tests__/file-reference.test.ts +447 -0
- package/src/types/__tests__/organisation.test.ts +1133 -0
- package/src/types/__tests__/theme.test.ts +830 -0
- package/src/types/__tests__/type-validation.test.ts +527 -0
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +1 -5
- package/src/utils/__tests__/debugLogger.test.ts +417 -0
- package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -6
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -5
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +35 -35
- package/src/utils/__tests__/organisationContext.unit.test.ts +1 -5
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +5 -11
- package/src/utils/__tests__/secureErrors.unit.test.ts +1 -6
- package/src/utils/__tests__/secureStorage.unit.test.ts +1 -5
- package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -5
- package/src/utils/__tests__/sessionTracking.unit.test.ts +1 -5
- package/src/utils/appIdResolver.test.ts +6 -10
- package/src/utils/appNameResolver.simple.test.ts +142 -0
- package/src/utils/appNameResolver.test.ts +31 -458
- package/src/utils/appNameResolver.test.ts.backup +494 -0
- package/src/utils/debugLogger.ts +26 -5
- package/src/utils/formatDate.test.ts +1 -5
- package/src/utils/organisationContext.test.ts +1 -5
- package/src/utils/performanceBudgets.ts +3 -4
- package/src/utils/secureDataAccess.test.ts +1 -5
- package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -5
- package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +1 -5
- package/dist/chunk-D7ARGIA3.js.map +0 -1
- package/dist/chunk-IPCH4YPT.js +0 -315
- package/dist/chunk-IPCH4YPT.js.map +0 -1
- package/dist/chunk-KRCRNXPD.js.map +0 -1
- package/dist/chunk-MOJXHWDE.js.map +0 -1
- package/dist/chunk-N2EUGZRW.js +0 -98
- package/dist/chunk-N2EUGZRW.js.map +0 -1
- package/dist/chunk-OPCWH3A4.js.map +0 -1
- package/dist/chunk-U6GPOF6J.js.map +0 -1
- package/dist/chunk-ZPG4XPV5.js.map +0 -1
- package/dist/chunk-ZPK5656W.js.map +0 -1
- package/docs/getting-started/installation.md +0 -269
- package/src/__tests__/REBUILD_PLAN.md +0 -223
- package/src/styles/base.css +0 -208
- package/src/styles/semantic.css +0 -24
- /package/dist/{DataTable-4IUY7BXB.js.map → DataTable-OSELOGMA.js.map} +0 -0
- /package/dist/{chunk-PXWEDX7Y.js.map → chunk-KWQH4VO3.js.map} +0 -0
- /package/dist/{chunk-UYA6U6H7.js.map → chunk-V2TE7LOF.js.map} +0 -0
package/src/hooks/index.ts
CHANGED
|
@@ -22,6 +22,9 @@ export { useFocusTrap } from './useFocusTrap';
|
|
|
22
22
|
export { useKeyboardShortcuts } from './useKeyboardShortcuts';
|
|
23
23
|
export { useIsMobile } from './useIsMobile';
|
|
24
24
|
|
|
25
|
+
// === EVENT THEMING HOOK ===
|
|
26
|
+
export { useEventTheme } from './useEventTheme';
|
|
27
|
+
|
|
25
28
|
// === DATA & STATE HOOKS ===
|
|
26
29
|
export { useDebounce } from './useDebounce';
|
|
27
30
|
export { useDataTableState } from './useDataTableState';
|
|
@@ -172,9 +172,12 @@ export function usePublicEvent(
|
|
|
172
172
|
|
|
173
173
|
try {
|
|
174
174
|
// Try to call the public event RPC function first
|
|
175
|
-
const
|
|
175
|
+
const response = await (supabase as any).rpc('get_public_event_by_code', {
|
|
176
176
|
event_code_param: eventCode
|
|
177
177
|
});
|
|
178
|
+
|
|
179
|
+
const data = response?.data;
|
|
180
|
+
const rpcError = response?.error;
|
|
178
181
|
|
|
179
182
|
if (rpcError) {
|
|
180
183
|
// If RPC function doesn't exist or schema cache issue, try refresh first, then fallback
|
|
@@ -188,10 +191,13 @@ export function usePublicEvent(
|
|
|
188
191
|
|
|
189
192
|
// Try RPC call one more time after refresh
|
|
190
193
|
try {
|
|
191
|
-
const
|
|
194
|
+
const retryResponse = await (supabase as any).rpc('get_public_event_by_code', {
|
|
192
195
|
event_code_param: eventCode
|
|
193
196
|
});
|
|
194
197
|
|
|
198
|
+
const retryData = retryResponse?.data;
|
|
199
|
+
const retryError = retryResponse?.error;
|
|
200
|
+
|
|
195
201
|
if (!retryError && retryData && retryData.length > 0) {
|
|
196
202
|
eventData = retryData[0];
|
|
197
203
|
} else {
|
|
@@ -201,7 +207,7 @@ export function usePublicEvent(
|
|
|
201
207
|
console.warn('[usePublicEvent] RPC still failing after cache refresh, falling back to direct table access');
|
|
202
208
|
|
|
203
209
|
// Fallback: Direct table access with public RLS policy
|
|
204
|
-
const
|
|
210
|
+
const tableResponse2 = await (supabase as any)
|
|
205
211
|
.from('event')
|
|
206
212
|
.select(`
|
|
207
213
|
event_id,
|
|
@@ -227,8 +233,11 @@ export function usePublicEvent(
|
|
|
227
233
|
.limit(1)
|
|
228
234
|
.single();
|
|
229
235
|
|
|
236
|
+
const tableData = tableResponse2?.data;
|
|
237
|
+
const tableError = tableResponse2?.error;
|
|
238
|
+
|
|
230
239
|
if (tableError) {
|
|
231
|
-
throw new Error(tableError
|
|
240
|
+
throw new Error(tableError?.message || 'Failed to fetch event from table');
|
|
232
241
|
}
|
|
233
242
|
|
|
234
243
|
if (!tableData) {
|
|
@@ -238,7 +247,7 @@ export function usePublicEvent(
|
|
|
238
247
|
}
|
|
239
248
|
|
|
240
249
|
// Get event logo from file_references
|
|
241
|
-
const
|
|
250
|
+
const logoResponse = await (supabase as any)
|
|
242
251
|
.from('file_references')
|
|
243
252
|
.select('file_path')
|
|
244
253
|
.eq('table_name', 'event')
|
|
@@ -247,6 +256,8 @@ export function usePublicEvent(
|
|
|
247
256
|
.eq('file_metadata->>category', 'event_logos')
|
|
248
257
|
.limit(1)
|
|
249
258
|
.single();
|
|
259
|
+
|
|
260
|
+
const logoData = logoResponse?.data;
|
|
250
261
|
|
|
251
262
|
eventData = {
|
|
252
263
|
...tableData,
|
|
@@ -254,7 +265,12 @@ export function usePublicEvent(
|
|
|
254
265
|
};
|
|
255
266
|
}
|
|
256
267
|
} else {
|
|
257
|
-
|
|
268
|
+
// For RPC errors that aren't schema cache issues, throw immediately without fallback
|
|
269
|
+
const errorMessage = rpcError?.message || rpcError?.toString() || 'Failed to fetch event';
|
|
270
|
+
setEvent(null);
|
|
271
|
+
setError(new Error(errorMessage));
|
|
272
|
+
setIsLoading(false);
|
|
273
|
+
return;
|
|
258
274
|
}
|
|
259
275
|
} else {
|
|
260
276
|
if (!data || data.length === 0 || !data[0]) {
|
|
@@ -268,7 +284,7 @@ export function usePublicEvent(
|
|
|
268
284
|
// If RPC call fails for any reason (including schema cache issues), try direct table access
|
|
269
285
|
console.warn('[usePublicEvent] RPC call failed, falling back to direct table access:', rpcError);
|
|
270
286
|
|
|
271
|
-
const
|
|
287
|
+
const tableResponse = await (supabase as any)
|
|
272
288
|
.from('event')
|
|
273
289
|
.select(`
|
|
274
290
|
event_id,
|
|
@@ -294,8 +310,11 @@ export function usePublicEvent(
|
|
|
294
310
|
.limit(1)
|
|
295
311
|
.single();
|
|
296
312
|
|
|
313
|
+
const tableData = tableResponse?.data;
|
|
314
|
+
const tableError = tableResponse?.error;
|
|
315
|
+
|
|
297
316
|
if (tableError) {
|
|
298
|
-
throw new Error(tableError
|
|
317
|
+
throw new Error(tableError?.message || 'Failed to fetch event from table');
|
|
299
318
|
}
|
|
300
319
|
|
|
301
320
|
if (!tableData) {
|
|
@@ -305,7 +324,7 @@ export function usePublicEvent(
|
|
|
305
324
|
}
|
|
306
325
|
|
|
307
326
|
// Get event logo from file_references
|
|
308
|
-
const
|
|
327
|
+
const logoResponse = await (supabase as any)
|
|
309
328
|
.from('file_references')
|
|
310
329
|
.select('file_path')
|
|
311
330
|
.eq('table_name', 'event')
|
|
@@ -314,6 +333,8 @@ export function usePublicEvent(
|
|
|
314
333
|
.eq('file_metadata->>category', 'event_logos')
|
|
315
334
|
.limit(1)
|
|
316
335
|
.single();
|
|
336
|
+
|
|
337
|
+
const logoData = logoResponse?.data;
|
|
317
338
|
|
|
318
339
|
eventData = {
|
|
319
340
|
...tableData,
|
|
@@ -87,15 +87,25 @@ interface UsePublicRouteParamsOptions {
|
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
89
|
* Validate event code format
|
|
90
|
-
* Event codes should be alphanumeric with optional hyphens/underscores
|
|
90
|
+
* Event codes should be alphanumeric with optional hyphens/underscores in the middle
|
|
91
91
|
*/
|
|
92
92
|
function validateEventCodeFormat(eventCode: string): boolean {
|
|
93
93
|
if (!eventCode || typeof eventCode !== 'string') return false;
|
|
94
94
|
|
|
95
95
|
// Allow alphanumeric characters, hyphens, and underscores
|
|
96
96
|
// Length between 3 and 50 characters
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
// Must not start or end with hyphen/underscore
|
|
98
|
+
const eventCodeRegex = /^[a-zA-Z0-9][a-zA-Z0-9_-]{1,48}[a-zA-Z0-9]$/;
|
|
99
|
+
const matchesFormat = eventCodeRegex.test(eventCode);
|
|
100
|
+
|
|
101
|
+
if (!matchesFormat) return false;
|
|
102
|
+
|
|
103
|
+
// Additional check: no consecutive hyphens or underscores
|
|
104
|
+
if (eventCode.includes('--') || eventCode.includes('__') || eventCode.includes('-_') || eventCode.includes('_-')) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return true;
|
|
99
109
|
}
|
|
100
110
|
|
|
101
111
|
/**
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Auth Convenience Hook
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Hooks/Services
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* Convenience hook for authentication.
|
|
8
|
+
* Returns just the auth state and methods needed by components.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useAuthService } from './useAuthService';
|
|
12
|
+
import { type User, type Session, AuthError } from '@supabase/supabase-js';
|
|
13
|
+
|
|
14
|
+
export interface AuthState {
|
|
15
|
+
user: User | null;
|
|
16
|
+
session: Session | null;
|
|
17
|
+
isAuthenticated: boolean;
|
|
18
|
+
authLoading: boolean;
|
|
19
|
+
authError: AuthError | null;
|
|
20
|
+
error: AuthError | null; // Alias for authError for backward compatibility
|
|
21
|
+
supabase: any | null;
|
|
22
|
+
|
|
23
|
+
// Auth methods
|
|
24
|
+
signIn: (email: string, password?: string) => Promise<{ error: AuthError | null }>;
|
|
25
|
+
signUp: (email: string, password: string) => Promise<{ error: AuthError | null }>;
|
|
26
|
+
signOut: () => Promise<{ error: AuthError | null }>;
|
|
27
|
+
resetPassword: (email: string) => Promise<{ error: AuthError | null }>;
|
|
28
|
+
updatePassword: (password: string) => Promise<{ error: AuthError | null }>;
|
|
29
|
+
refreshSession: () => Promise<{ error: AuthError | null }>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function useAuth(): AuthState {
|
|
33
|
+
const authService = useAuthService();
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
user: authService.getUser(),
|
|
37
|
+
session: authService.getSession(),
|
|
38
|
+
isAuthenticated: authService.isAuthenticated(),
|
|
39
|
+
authLoading: authService.isLoading(),
|
|
40
|
+
authError: authService.getError(),
|
|
41
|
+
error: authService.getError(), // Alias for backward compatibility
|
|
42
|
+
supabase: authService.getSupabaseClient(),
|
|
43
|
+
signIn: authService.signIn.bind(authService),
|
|
44
|
+
signUp: authService.signUp.bind(authService),
|
|
45
|
+
signOut: authService.signOut.bind(authService),
|
|
46
|
+
resetPassword: authService.resetPassword.bind(authService),
|
|
47
|
+
updatePassword: authService.updatePassword.bind(authService),
|
|
48
|
+
refreshSession: authService.refreshSession.bind(authService),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Auth Service Hook
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Hooks/Services
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* React hook for AuthService.
|
|
8
|
+
* Provides authentication service with reactive state updates.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useContext, useReducer, useEffect } from 'react';
|
|
12
|
+
import { AuthServiceContext } from '../../providers/services/AuthServiceProvider';
|
|
13
|
+
import { AuthService } from '../../services/AuthService';
|
|
14
|
+
|
|
15
|
+
export function useAuthService(): AuthService {
|
|
16
|
+
const context = useContext(AuthServiceContext);
|
|
17
|
+
|
|
18
|
+
if (!context) {
|
|
19
|
+
throw new Error('useAuthService must be used within AuthServiceProvider');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Subscribe to service state changes
|
|
23
|
+
const [, forceUpdate] = useReducer(x => x + 1, 0);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
return context.authService.subscribe(() => forceUpdate());
|
|
27
|
+
}, [context.authService]);
|
|
28
|
+
|
|
29
|
+
return context.authService;
|
|
30
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Current Event Convenience Hook
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Hooks/Services
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* Convenience hook for current event.
|
|
8
|
+
* Returns just the event state and methods needed by components.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useEventService } from './useEventService';
|
|
12
|
+
import { Event } from '../../types/unified';
|
|
13
|
+
|
|
14
|
+
export interface CurrentEventState {
|
|
15
|
+
events: Event[];
|
|
16
|
+
selectedEvent: Event | null;
|
|
17
|
+
isLoading: boolean;
|
|
18
|
+
error: Error | null;
|
|
19
|
+
|
|
20
|
+
// Event methods
|
|
21
|
+
setSelectedEvent: (event: Event | null) => void;
|
|
22
|
+
refreshEvents: () => Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function useCurrentEvent(): CurrentEventState {
|
|
26
|
+
const eventService = useEventService();
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
events: eventService.getEvents(),
|
|
30
|
+
selectedEvent: eventService.getSelectedEvent(),
|
|
31
|
+
isLoading: eventService.isLoading(),
|
|
32
|
+
error: eventService.getError(),
|
|
33
|
+
setSelectedEvent: eventService.setSelectedEvent.bind(eventService),
|
|
34
|
+
refreshEvents: eventService.refreshEvents.bind(eventService),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Current Organisation Convenience Hook
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Hooks/Services
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* Convenience hook for current organisation.
|
|
8
|
+
* Returns just the organisation state and methods needed by components.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useOrganisationService } from './useOrganisationService';
|
|
12
|
+
import type { Organisation, OrganisationMembership } from '../../types/organisation';
|
|
13
|
+
|
|
14
|
+
export interface CurrentOrganisationState {
|
|
15
|
+
selectedOrganisation: Organisation | null;
|
|
16
|
+
organisations: Organisation[];
|
|
17
|
+
userMemberships: OrganisationMembership[];
|
|
18
|
+
isLoading: boolean;
|
|
19
|
+
error: Error | null;
|
|
20
|
+
hasValidOrganisationContext: boolean;
|
|
21
|
+
isContextReady: boolean;
|
|
22
|
+
|
|
23
|
+
// Organisation methods
|
|
24
|
+
switchOrganisation: (orgId: string) => Promise<void>;
|
|
25
|
+
getUserRole: (orgId?: string) => string;
|
|
26
|
+
validateOrganisationAccess: (orgId: string) => boolean;
|
|
27
|
+
refreshOrganisations: () => Promise<void>;
|
|
28
|
+
ensureOrganisationContext: () => Organisation;
|
|
29
|
+
isOrganisationSecure: () => boolean;
|
|
30
|
+
getPrimaryOrganisation: () => Organisation | null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function useCurrentOrganisation(): CurrentOrganisationState {
|
|
34
|
+
const organisationService = useOrganisationService();
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
selectedOrganisation: organisationService.getSelectedOrganisation(),
|
|
38
|
+
organisations: organisationService.getOrganisations(),
|
|
39
|
+
userMemberships: organisationService.getUserMemberships(),
|
|
40
|
+
isLoading: organisationService.isLoading(),
|
|
41
|
+
error: organisationService.getError(),
|
|
42
|
+
hasValidOrganisationContext: organisationService.hasValidOrganisationContext(),
|
|
43
|
+
isContextReady: organisationService.isContextReady(),
|
|
44
|
+
switchOrganisation: organisationService.switchOrganisation.bind(organisationService),
|
|
45
|
+
getUserRole: organisationService.getUserRole.bind(organisationService),
|
|
46
|
+
validateOrganisationAccess: organisationService.validateOrganisationAccess.bind(organisationService),
|
|
47
|
+
refreshOrganisations: organisationService.refreshOrganisations.bind(organisationService),
|
|
48
|
+
ensureOrganisationContext: organisationService.ensureOrganisationContext.bind(organisationService),
|
|
49
|
+
isOrganisationSecure: organisationService.isOrganisationSecure.bind(organisationService),
|
|
50
|
+
getPrimaryOrganisation: organisationService.getPrimaryOrganisation.bind(organisationService),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Event Service Hook
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Hooks/Services
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* React hook for EventService.
|
|
8
|
+
* Provides event service with reactive state updates.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useContext, useReducer, useEffect } from 'react';
|
|
12
|
+
import { EventServiceContext } from '../../providers/services/EventServiceProvider';
|
|
13
|
+
import { EventService } from '../../services/EventService';
|
|
14
|
+
|
|
15
|
+
export function useEventService(): EventService {
|
|
16
|
+
const context = useContext(EventServiceContext);
|
|
17
|
+
|
|
18
|
+
if (!context) {
|
|
19
|
+
throw new Error('useEventService must be used within EventServiceProvider');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Subscribe to service state changes
|
|
23
|
+
const [, forceUpdate] = useReducer(x => x + 1, 0);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
return context.eventService.subscribe(() => forceUpdate());
|
|
27
|
+
}, [context.eventService]);
|
|
28
|
+
|
|
29
|
+
return context.eventService;
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Inactivity Service Hook
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Hooks/Services
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* React hook for InactivityService.
|
|
8
|
+
* Provides inactivity service with reactive state updates.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useContext, useReducer, useEffect } from 'react';
|
|
12
|
+
import { InactivityServiceContext } from '../../providers/services/InactivityServiceProvider';
|
|
13
|
+
import { InactivityService } from '../../services/InactivityService';
|
|
14
|
+
|
|
15
|
+
export function useInactivityService(): InactivityService {
|
|
16
|
+
const context = useContext(InactivityServiceContext);
|
|
17
|
+
|
|
18
|
+
if (!context) {
|
|
19
|
+
throw new Error('useInactivityService must be used within InactivityServiceProvider');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Subscribe to service state changes
|
|
23
|
+
const [, forceUpdate] = useReducer(x => x + 1, 0);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
return context.inactivityService.subscribe(() => forceUpdate());
|
|
27
|
+
}, [context.inactivityService]);
|
|
28
|
+
|
|
29
|
+
return context.inactivityService;
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Organisation Service Hook
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Hooks/Services
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* React hook for OrganisationService.
|
|
8
|
+
* Provides organisation service with reactive state updates.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useContext, useReducer, useEffect } from 'react';
|
|
12
|
+
import { OrganisationServiceContext } from '../../providers/services/OrganisationServiceProvider';
|
|
13
|
+
import { OrganisationService } from '../../services/OrganisationService';
|
|
14
|
+
|
|
15
|
+
export function useOrganisationService(): OrganisationService {
|
|
16
|
+
const context = useContext(OrganisationServiceContext);
|
|
17
|
+
|
|
18
|
+
if (!context) {
|
|
19
|
+
throw new Error('useOrganisationService must be used within OrganisationServiceProvider');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Subscribe to service state changes
|
|
23
|
+
const [, forceUpdate] = useReducer(x => x + 1, 0);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
return context.organisationService.subscribe(() => forceUpdate());
|
|
27
|
+
}, [context.organisationService]);
|
|
28
|
+
|
|
29
|
+
return context.organisationService;
|
|
30
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Permissions Convenience Hook
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Hooks/Services
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* Convenience hook for permissions.
|
|
8
|
+
* Returns just the permission state and methods needed by components.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useRBACService } from './useRBACService';
|
|
12
|
+
import { AccessLevel } from '../../types/unified';
|
|
13
|
+
|
|
14
|
+
export interface PermissionsState {
|
|
15
|
+
permissions: Record<string, boolean>;
|
|
16
|
+
roles: string[];
|
|
17
|
+
accessLevel: AccessLevel;
|
|
18
|
+
rbacLoading: boolean;
|
|
19
|
+
rbacError: Error | null;
|
|
20
|
+
selectedEventId: string | null;
|
|
21
|
+
appConfig: any | null;
|
|
22
|
+
userEventAccess: any[];
|
|
23
|
+
eventAccessLoading: boolean;
|
|
24
|
+
selectedOrganisationId: string | null;
|
|
25
|
+
|
|
26
|
+
// Permission methods
|
|
27
|
+
hasPermission: (permission: string, orgId?: string) => boolean;
|
|
28
|
+
hasAnyPermission: (permissions: string[], orgId?: string) => boolean;
|
|
29
|
+
hasAllPermissions: (permissions: string[], orgId?: string) => boolean;
|
|
30
|
+
hasRole: (role: string) => boolean;
|
|
31
|
+
hasAccessLevel: (level: AccessLevel) => boolean;
|
|
32
|
+
canAccess: (resource: string, action: string, orgId?: string) => boolean;
|
|
33
|
+
validatePermission: (permission: string, orgId?: string) => Promise<boolean>;
|
|
34
|
+
validateAccess: (resource: string, action: string, orgId?: string) => Promise<boolean>;
|
|
35
|
+
refreshPermissions: (eventId?: string, orgId?: string) => Promise<void>;
|
|
36
|
+
setSelectedEventId: (eventId: string | null) => void;
|
|
37
|
+
loadUserEventAccess: (orgId?: string) => Promise<void>;
|
|
38
|
+
getUserEventAccess: (eventId: string) => any | undefined;
|
|
39
|
+
requireOrganisationContext: () => string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function usePermissions(): PermissionsState {
|
|
43
|
+
const rbacService = useRBACService();
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
permissions: rbacService.getPermissions(),
|
|
47
|
+
roles: rbacService.getRoles(),
|
|
48
|
+
accessLevel: rbacService.getAccessLevel(),
|
|
49
|
+
rbacLoading: rbacService.isLoading(),
|
|
50
|
+
rbacError: rbacService.getError(),
|
|
51
|
+
selectedEventId: rbacService.getSelectedEventId(),
|
|
52
|
+
appConfig: rbacService.getAppConfig(),
|
|
53
|
+
userEventAccess: rbacService.getUserEventAccess(),
|
|
54
|
+
eventAccessLoading: rbacService.isEventAccessLoading(),
|
|
55
|
+
selectedOrganisationId: rbacService.getSelectedOrganisationId(),
|
|
56
|
+
hasPermission: rbacService.hasPermission.bind(rbacService),
|
|
57
|
+
hasAnyPermission: rbacService.hasAnyPermission.bind(rbacService),
|
|
58
|
+
hasAllPermissions: rbacService.hasAllPermissions.bind(rbacService),
|
|
59
|
+
hasRole: rbacService.hasRole.bind(rbacService),
|
|
60
|
+
hasAccessLevel: rbacService.hasAccessLevel.bind(rbacService),
|
|
61
|
+
canAccess: rbacService.canAccess.bind(rbacService),
|
|
62
|
+
validatePermission: rbacService.validatePermission.bind(rbacService),
|
|
63
|
+
validateAccess: rbacService.validateAccess.bind(rbacService),
|
|
64
|
+
refreshPermissions: rbacService.refreshPermissions.bind(rbacService),
|
|
65
|
+
setSelectedEventId: rbacService.setSelectedEventId.bind(rbacService),
|
|
66
|
+
loadUserEventAccess: rbacService.loadUserEventAccess.bind(rbacService),
|
|
67
|
+
getUserEventAccess: rbacService.getUserEventAccess.bind(rbacService),
|
|
68
|
+
requireOrganisationContext: rbacService.requireOrganisationContext.bind(rbacService),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file RBAC Service Hook
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Hooks/Services
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* React hook for RBACService.
|
|
8
|
+
* Provides RBAC service with reactive state updates.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useContext, useReducer, useEffect } from 'react';
|
|
12
|
+
import { RBACServiceContext } from '../../providers/services/RBACServiceProvider';
|
|
13
|
+
import { RBACService } from '../../services/RBACService';
|
|
14
|
+
|
|
15
|
+
export function useRBACService(): RBACService {
|
|
16
|
+
const context = useContext(RBACServiceContext);
|
|
17
|
+
|
|
18
|
+
if (!context) {
|
|
19
|
+
throw new Error('useRBACService must be used within RBACServiceProvider');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Subscribe to service state changes
|
|
23
|
+
const [, forceUpdate] = useReducer(x => x + 1, 0);
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
return context.rbacService.subscribe(() => forceUpdate());
|
|
27
|
+
}, [context.rbacService]);
|
|
28
|
+
|
|
29
|
+
return context.rbacService;
|
|
30
|
+
}
|
|
@@ -19,11 +19,7 @@ const useCounter = (initialValue = 0) => {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
describe('useCounter Hook', () => {
|
|
22
|
-
|
|
23
|
-
vi.clearAllMocks();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
describe('Initialization', () => {
|
|
22
|
+
describe('Initialization', () => {
|
|
27
23
|
it('initializes with default value', () => {
|
|
28
24
|
const { result } = renderHook(() => useCounter());
|
|
29
25
|
expect(result.current.count).toBe(0);
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Event Theme Hook
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Hooks/EventTheme
|
|
5
|
+
* @since 2.0.0
|
|
6
|
+
*
|
|
7
|
+
* Hook that automatically applies event-specific theming when an event is selected.
|
|
8
|
+
* This ensures consistent UX across all apps in the pace suite.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* import { useEventTheme } from '@jmruthers/pace-core/hooks';
|
|
13
|
+
*
|
|
14
|
+
* function MyApp() {
|
|
15
|
+
* // Automatically applies event colors when event is selected
|
|
16
|
+
* useEventTheme();
|
|
17
|
+
*
|
|
18
|
+
* return <div>Your app content</div>;
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { useEffect } from 'react';
|
|
24
|
+
import { useEvents } from '../providers/EventProvider';
|
|
25
|
+
import { applyPalette, clearPalette } from '../theming/runtime';
|
|
26
|
+
import type { PaletteData, ColorPalette } from '../theming/runtime';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Hook that automatically applies event-specific theming
|
|
30
|
+
*
|
|
31
|
+
* This hook watches the selected event and applies its colors using the theming system.
|
|
32
|
+
* It will:
|
|
33
|
+
* - Apply event colors when an event with `event_colours` is selected
|
|
34
|
+
* - Clear theming when no event is selected
|
|
35
|
+
* - Handle cleanup when the component unmounts
|
|
36
|
+
*
|
|
37
|
+
* @returns void - This is an effect hook with no return value
|
|
38
|
+
*/
|
|
39
|
+
export function useEventTheme(): void {
|
|
40
|
+
const { selectedEvent } = useEvents();
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
// If there's no selected event, clear any dynamic theming
|
|
44
|
+
if (!selectedEvent) {
|
|
45
|
+
clearPalette();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Check if the event has theme colors
|
|
50
|
+
const eventColours = selectedEvent.event_colours;
|
|
51
|
+
|
|
52
|
+
if (!eventColours || typeof eventColours !== 'object') {
|
|
53
|
+
clearPalette();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Validate that event_colours has the expected structure
|
|
58
|
+
const palette = eventColours as Partial<PaletteData>;
|
|
59
|
+
|
|
60
|
+
// Check if we have at least one valid palette (main, sec, or acc)
|
|
61
|
+
if (!palette.main && !palette.sec && !palette.acc) {
|
|
62
|
+
clearPalette();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Apply the palette
|
|
67
|
+
// The system expects main, sec, and acc, so we ensure all are present (empty if needed)
|
|
68
|
+
const fullPalette: PaletteData = {
|
|
69
|
+
main: (palette.main as ColorPalette) || {},
|
|
70
|
+
sec: (palette.sec as ColorPalette) || {},
|
|
71
|
+
acc: (palette.acc as ColorPalette) || {},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
applyPalette(fullPalette);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error('[useEventTheme] Failed to apply event palette:', error);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Cleanup function to clear palette when component unmounts or event changes
|
|
81
|
+
return () => {
|
|
82
|
+
// Don't clear on unmount since we want the theme to persist
|
|
83
|
+
// The next event selection will update it
|
|
84
|
+
};
|
|
85
|
+
}, [selectedEvent]);
|
|
86
|
+
}
|
|
@@ -36,16 +36,13 @@ describe('useOrganisationPermissions', () => {
|
|
|
36
36
|
...overrides
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
+
// Set up default mock for all tests
|
|
39
40
|
beforeEach(() => {
|
|
40
41
|
vi.clearAllMocks();
|
|
41
42
|
mockUseOrganisations.mockReturnValue(createMockOrganisations() as any);
|
|
42
43
|
});
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
vi.restoreAllMocks();
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
describe('Hook Initialization', () => {
|
|
45
|
+
describe('Hook Initialization', () => {
|
|
49
46
|
it('initializes with default organisation', () => {
|
|
50
47
|
const { result } = renderHook(() => useOrganisationPermissions());
|
|
51
48
|
|
|
@@ -122,11 +122,7 @@ describe('useOrganisationSecurity', () => {
|
|
|
122
122
|
} as any);
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
vi.restoreAllMocks();
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
describe('Super Admin Context', () => {
|
|
125
|
+
describe('Super Admin Context', () => {
|
|
130
126
|
it('detects super admin from app_metadata', () => {
|
|
131
127
|
const superAdminUser = {
|
|
132
128
|
...mockUser,
|
|
@@ -39,11 +39,7 @@ describe('usePermissionCache', () => {
|
|
|
39
39
|
mockUseRBAC.mockReturnValue(stableMockRBAC);
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
vi.restoreAllMocks();
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
describe('Hook Initialization', () => {
|
|
42
|
+
describe('Hook Initialization', () => {
|
|
47
43
|
it('initializes with default configuration', () => {
|
|
48
44
|
const { result } = renderHook(() => usePermissionCache());
|
|
49
45
|
|