@jmruthers/pace-core 0.6.1 → 0.6.2
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 +43 -10
- package/cursor-rules/00-pace-core-compliance.mdc +18 -91
- package/cursor-rules/01-standards-compliance.mdc +16 -47
- package/cursor-rules/02-project-structure.mdc +4 -4
- package/cursor-rules/03-solid-principles.mdc +45 -164
- package/cursor-rules/04-testing-standards.mdc +22 -69
- package/cursor-rules/05-bug-reports-and-features.mdc +2 -2
- package/cursor-rules/06-code-quality.mdc +42 -125
- package/cursor-rules/07-tech-stack-compliance.mdc +33 -128
- package/cursor-rules/08-markup-quality.mdc +452 -0
- package/cursor-rules/CHANGELOG.md +18 -0
- package/cursor-rules/README.md +2 -1
- package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-BPvc3Ka0.d.ts} +54 -0
- package/dist/{DataTable-CH1U5Tpy.d.ts → DataTable-BMRU8a1j.d.ts} +33 -1
- package/dist/{DataTable-DQ7RSOHE.js → DataTable-TPTKCX4D.js} +10 -9
- package/dist/{PublicPageProvider-ce4xlHYA.d.ts → PublicPageProvider-DC6kCaqf.d.ts} +356 -111
- package/dist/{UnifiedAuthProvider-ATAP5UTR.js → UnifiedAuthProvider-CH6Z342H.js} +3 -3
- package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CVcTjx-d.d.ts} +29 -0
- package/dist/{api-N774RPUA.js → api-MVVQZLJI.js} +2 -2
- package/dist/{chunk-KNC55RTG.js → chunk-24UVZUZG.js} +90 -54
- package/dist/chunk-24UVZUZG.js.map +1 -0
- package/dist/{chunk-4N5C5XZU.js → chunk-2UOI2FG5.js} +4 -4
- package/dist/chunk-2UOI2FG5.js.map +1 -0
- package/dist/{chunk-T33XF5ZC.js → chunk-3XC4CPTD.js} +4317 -3963
- package/dist/chunk-3XC4CPTD.js.map +1 -0
- package/dist/{chunk-4ZC4GX36.js → chunk-6J4GEEJR.js} +172 -45
- package/dist/chunk-6J4GEEJR.js.map +1 -0
- package/dist/{chunk-3QRJFVBR.js → chunk-6SOIHG6Z.js} +1 -1
- package/dist/chunk-6SOIHG6Z.js.map +1 -0
- package/dist/{chunk-BYFSK72L.js → chunk-EHMR7VYL.js} +4 -4
- package/dist/chunk-EHMR7VYL.js.map +1 -0
- package/dist/{chunk-I7PSE6JW.js → chunk-F2IMUDXZ.js} +2 -75
- package/dist/chunk-F2IMUDXZ.js.map +1 -0
- package/dist/{chunk-LXQLPRQ2.js → chunk-FFQEQTNW.js} +6 -8
- package/dist/chunk-FFQEQTNW.js.map +1 -0
- package/dist/chunk-FMUCXFII.js +76 -0
- package/dist/chunk-FMUCXFII.js.map +1 -0
- package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
- package/dist/chunk-L4OXEN46.js.map +1 -0
- package/dist/{chunk-R77UEZ4E.js → chunk-M43Y4SSO.js} +1 -1
- package/dist/chunk-M43Y4SSO.js.map +1 -0
- package/dist/{chunk-3XTALGJF.js → chunk-MMZ7JXPU.js} +60 -223
- package/dist/chunk-MMZ7JXPU.js.map +1 -0
- package/dist/{chunk-GLK6VM3F.js → chunk-NECFR5MM.js} +254 -170
- package/dist/chunk-NECFR5MM.js.map +1 -0
- package/dist/{chunk-JBKQ3SAO.js → chunk-SFZUDBL5.js} +40 -4
- package/dist/chunk-SFZUDBL5.js.map +1 -0
- package/dist/{chunk-XM25TVIE.js → chunk-XWQCNGTQ.js} +724 -363
- package/dist/chunk-XWQCNGTQ.js.map +1 -0
- package/dist/components.d.ts +5 -5
- package/dist/components.js +14 -11
- package/dist/components.js.map +1 -1
- package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
- package/dist/hooks.d.ts +55 -122
- package/dist/hooks.js +8 -12
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +60 -13
- package/dist/index.js +19 -19
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +21 -3
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +145 -114
- package/dist/rbac/index.js +8 -11
- package/dist/theming/runtime.d.ts +1 -13
- package/dist/theming/runtime.js +1 -1
- package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
- package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
- package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
- package/dist/types.d.ts +2 -2
- package/dist/{usePublicRouteParams-BJAlWfuJ.d.ts → usePublicRouteParams-1oMokgLF.d.ts} +31 -1
- package/dist/utils.d.ts +4 -5
- package/dist/utils.js +14 -14
- package/dist/utils.js.map +1 -1
- package/docs/api/README.md +7 -1
- package/docs/api/classes/ColumnFactory.md +8 -8
- package/docs/api/classes/InvalidScopeError.md +4 -4
- package/docs/api/classes/Logger.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +4 -4
- package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
- package/docs/api/classes/PermissionDeniedError.md +4 -4
- 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 +4 -4
- package/docs/api/classes/RBACNotInitializedError.md +4 -4
- package/docs/api/classes/SecureSupabaseClient.md +18 -15
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/enums/LogLevel.md +1 -1
- package/docs/api/enums/RBACErrorCode.md +1 -1
- package/docs/api/enums/RPCFunction.md +1 -1
- package/docs/api/interfaces/AddressFieldProps.md +1 -1
- package/docs/api/interfaces/AddressFieldRef.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +4 -4
- package/docs/api/interfaces/AutocompleteOptions.md +1 -1
- package/docs/api/interfaces/AvatarProps.md +1 -1
- package/docs/api/interfaces/BadgeProps.md +9 -2
- package/docs/api/interfaces/ButtonProps.md +7 -4
- package/docs/api/interfaces/CalendarProps.md +8 -5
- package/docs/api/interfaces/CardProps.md +8 -5
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/ComplianceResult.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +24 -21
- package/docs/api/interfaces/DataTableColumn.md +31 -31
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
- package/docs/api/interfaces/DatabaseIssue.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/ErrorBoundaryProps.md +147 -0
- package/docs/api/interfaces/ErrorBoundaryProviderProps.md +36 -0
- package/docs/api/interfaces/ErrorBoundaryState.md +75 -0
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +8 -8
- package/docs/api/interfaces/FileDisplayProps.md +1 -1
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +26 -23
- package/docs/api/interfaces/FooterProps.md +10 -8
- package/docs/api/interfaces/FormFieldProps.md +10 -10
- package/docs/api/interfaces/FormProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +7 -4
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoggerConfig.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +14 -11
- 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 +11 -11
- package/docs/api/interfaces/NavigationMenuProps.md +15 -15
- 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 +30 -27
- package/docs/api/interfaces/PaceLoginPageProps.md +6 -4
- 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/ParsedAddress.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProgressProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +7 -26
- package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
- package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
- package/docs/api/interfaces/PublicPageLayoutProps.md +7 -20
- package/docs/api/interfaces/QuickFix.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
- package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
- package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
- package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACContext.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
- package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
- package/docs/api/interfaces/RBACResult.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
- package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
- package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
- package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
- package/docs/api/interfaces/RBACRolesListParams.md +1 -1
- package/docs/api/interfaces/RBACRolesListResult.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
- package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
- package/docs/api/interfaces/ResourcePermissions.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +3 -3
- package/docs/api/interfaces/SetupIssue.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/TabsContentProps.md +1 -1
- package/docs/api/interfaces/TabsListProps.md +1 -1
- package/docs/api/interfaces/TabsProps.md +1 -1
- package/docs/api/interfaces/TabsTriggerProps.md +3 -3
- package/docs/api/interfaces/TextareaProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +4 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +58 -55
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +15 -13
- package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
- package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +11 -9
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +6 -6
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +9 -6
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +8 -5
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +12 -9
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +10 -7
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +14 -11
- package/docs/api/interfaces/UserMenuProps.md +8 -6
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +575 -634
- package/docs/architecture/database-schema-requirements.md +161 -0
- package/docs/core-concepts/rbac-system.md +3 -3
- package/docs/documentation-index.md +2 -4
- package/docs/getting-started/cursor-rules.md +2 -1
- package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
- package/docs/migration/MIGRATION_GUIDE.md +2 -24
- package/docs/migration/README.md +52 -6
- package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
- package/docs/migration/database-changes-december-2025.md +3 -3
- package/docs/rbac/event-based-apps.md +1 -1
- package/docs/rbac/getting-started.md +1 -1
- package/docs/rbac/quick-start.md +1 -1
- package/docs/standards/README.md +1 -0
- package/package.json +2 -1
- package/scripts/audit/core/checks/accessibility.cjs +197 -0
- package/scripts/audit/core/checks/api-usage.cjs +191 -0
- package/scripts/audit/core/checks/bundle.cjs +142 -0
- package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +714 -687
- package/scripts/audit/core/checks/config.cjs +54 -0
- package/scripts/audit/core/checks/coverage.cjs +84 -0
- package/scripts/audit/core/checks/dependencies.cjs +454 -0
- package/scripts/audit/core/checks/documentation.cjs +203 -0
- package/scripts/audit/core/checks/environment.cjs +128 -0
- package/scripts/audit/core/checks/error-handling.cjs +299 -0
- package/scripts/audit/core/checks/forms.cjs +172 -0
- package/scripts/audit/core/checks/heuristics.cjs +68 -0
- package/scripts/audit/core/checks/hooks.cjs +334 -0
- package/scripts/audit/core/checks/imports.cjs +244 -0
- package/scripts/audit/core/checks/performance.cjs +325 -0
- package/scripts/audit/core/checks/routes.cjs +117 -0
- package/scripts/audit/core/checks/state.cjs +130 -0
- package/scripts/audit/core/checks/structure.cjs +65 -0
- package/scripts/audit/core/checks/style.cjs +584 -0
- package/scripts/audit/core/checks/testing.cjs +122 -0
- package/scripts/audit/core/checks/typescript.cjs +61 -0
- package/scripts/audit/core/scanner.cjs +199 -0
- package/scripts/audit/core/utils.cjs +137 -0
- package/scripts/audit/index.cjs +223 -0
- package/scripts/audit/reporters/console.cjs +151 -0
- package/scripts/audit/reporters/json.cjs +54 -0
- package/scripts/audit/reporters/markdown.cjs +124 -0
- package/scripts/audit-consuming-app.cjs +61 -936
- package/scripts/build-docs/build-decision.js +240 -0
- package/scripts/build-docs/cache-utils.js +105 -0
- package/scripts/build-docs/content-normalization.js +150 -0
- package/scripts/build-docs/file-utils.js +105 -0
- package/scripts/build-docs/git-utils.js +86 -0
- package/scripts/build-docs/hash-utils.js +116 -0
- package/scripts/build-docs/typedoc-runner.js +220 -0
- package/scripts/build-docs-incremental.js +77 -913
- package/scripts/utils/command-runner.js +16 -11
- package/scripts/validate-formats.js +61 -56
- package/scripts/validate-master.js +74 -69
- package/scripts/validate-pre-publish.js +70 -65
- package/src/__tests__/hooks/usePermissions.test.ts +2 -2
- package/src/components/Alert/Alert.test.tsx +12 -18
- package/src/components/Alert/Alert.tsx +5 -7
- package/src/components/Avatar/Avatar.test.tsx +4 -4
- package/src/components/Badge/Badge.tsx +14 -0
- package/src/components/Button/Button.tsx +22 -0
- package/src/components/Calendar/Calendar.tsx +8 -2
- package/src/components/Card/Card.tsx +4 -0
- package/src/components/Checkbox/Checkbox.test.tsx +12 -12
- package/src/components/Checkbox/Checkbox.tsx +2 -2
- package/src/components/DataTable/DataTable.tsx +38 -4
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +18 -4
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
- package/src/components/DataTable/components/AccessDeniedPage.tsx +16 -25
- package/src/components/DataTable/components/ActionButtons.tsx +10 -7
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +1 -1
- package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
- package/src/components/DataTable/components/DataTableBody.tsx +8 -0
- package/src/components/DataTable/components/DataTableCore.tsx +196 -554
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
- package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
- package/src/components/DataTable/components/DataTableModals.tsx +8 -0
- package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
- package/src/components/DataTable/components/EditFields.tsx +307 -0
- package/src/components/DataTable/components/EditableRow.tsx +8 -0
- package/src/components/DataTable/components/EmptyState.tsx +10 -0
- package/src/components/DataTable/components/FilterRow.tsx +12 -0
- package/src/components/DataTable/components/GroupHeader.tsx +12 -0
- package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
- package/src/components/DataTable/components/ImportModal.tsx +7 -0
- package/src/components/DataTable/components/LoadingState.tsx +6 -0
- package/src/components/DataTable/components/PaginationControls.tsx +16 -1
- package/src/components/DataTable/components/RowComponent.tsx +391 -0
- package/src/components/DataTable/components/UnifiedTableBody.tsx +61 -849
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
- package/src/components/DataTable/components/cellValueUtils.ts +40 -0
- package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
- package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
- package/src/components/DataTable/context/DataTableContext.tsx +50 -0
- package/src/components/DataTable/core/ColumnFactory.ts +31 -0
- package/src/components/DataTable/core/DataTableContext.tsx +32 -1
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
- package/src/components/DataTable/hooks/useColumnReordering.ts +12 -0
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
- package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +124 -32
- package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
- package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
- package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
- package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
- package/src/components/DataTable/styles.ts +6 -6
- package/src/components/DataTable/types.ts +6 -10
- package/src/components/DataTable/utils/a11yUtils.ts +7 -0
- package/src/components/DataTable/utils/debugTools.ts +18 -113
- package/src/components/DataTable/utils/errorHandling.ts +12 -0
- package/src/components/DataTable/utils/exportUtils.ts +9 -0
- package/src/components/DataTable/utils/flexibleImport.ts +12 -48
- package/src/components/DataTable/utils/paginationUtils.ts +8 -0
- package/src/components/DataTable/utils/performanceUtils.ts +5 -1
- package/src/components/Dialog/Dialog.tsx +2 -2
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +45 -5
- package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
- package/src/components/ErrorBoundary/index.ts +27 -2
- package/src/components/EventSelector/EventSelector.tsx +3 -0
- package/src/components/FileDisplay/FileDisplay.tsx +32 -18
- package/src/components/FileUpload/FileUpload.tsx +22 -2
- package/src/components/Footer/Footer.test.tsx +16 -16
- package/src/components/Footer/Footer.tsx +14 -11
- package/src/components/Form/Form.tsx +1 -0
- package/src/components/Header/Header.tsx +21 -10
- package/src/components/Input/Input.test.tsx +2 -2
- package/src/components/Input/Input.tsx +8 -4
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
- package/src/components/LoginForm/LoginForm.tsx +4 -0
- package/src/components/NavigationMenu/NavigationMenu.tsx +14 -513
- package/src/components/NavigationMenu/types.ts +56 -0
- package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +3 -0
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -2
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +32 -11
- package/src/components/PaceAppLayout/test-setup.tsx +1 -2
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +3 -0
- package/src/components/PasswordChange/PasswordChangeForm.tsx +9 -0
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
- package/src/components/PublicLayout/PublicPageLayout.tsx +2 -5
- package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
- package/src/components/Select/Select.tsx +80 -434
- package/src/components/Select/context.ts +23 -0
- package/src/components/Select/hooks/useSelectEvents.ts +87 -0
- package/src/components/Select/hooks/useSelectSearch.ts +91 -0
- package/src/components/Select/hooks/useSelectState.ts +104 -0
- package/src/components/Select/index.ts +9 -1
- package/src/components/Select/types.ts +123 -0
- package/src/components/Select/utils/text.ts +26 -0
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +4 -5
- package/src/components/Switch/Switch.tsx +4 -4
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Toast/Toast.tsx +4 -0
- package/src/components/Tooltip/Tooltip.tsx +2 -2
- package/src/components/UserMenu/UserMenu.test.tsx +24 -11
- package/src/components/UserMenu/UserMenu.tsx +21 -18
- package/src/components/index.ts +2 -2
- package/src/hooks/__tests__/index.unit.test.ts +2 -5
- package/src/hooks/index.ts +1 -2
- package/src/hooks/public/usePublicEvent.ts +4 -0
- package/src/hooks/public/usePublicEventLogo.ts +4 -0
- package/src/hooks/public/usePublicFileDisplay.ts +4 -0
- package/src/hooks/public/usePublicRouteParams.ts +4 -0
- package/src/hooks/services/useAuth.ts +32 -0
- package/src/hooks/services/useCurrentEvent.ts +6 -0
- package/src/hooks/services/useCurrentOrganisation.ts +6 -0
- package/src/hooks/useDebounce.ts +9 -0
- package/src/hooks/useEventTheme.ts +6 -0
- package/src/hooks/useFileDisplay.ts +4 -0
- package/src/hooks/useFileReference.ts +25 -7
- package/src/hooks/useFileUrl.ts +11 -1
- package/src/hooks/useFocusManagement.ts +14 -0
- package/src/hooks/useFocusTrap.ts +3 -0
- package/src/hooks/useInactivityTracker.ts +3 -0
- package/src/hooks/useKeyboardShortcuts.ts +4 -0
- package/src/hooks/useOrganisationPermissions.ts +4 -0
- package/src/hooks/useOrganisationSecurity.ts +4 -0
- package/src/hooks/usePerformanceMonitor.ts +4 -0
- package/src/hooks/usePermissionCache.ts +7 -0
- package/src/hooks/useQueryCache.ts +12 -1
- package/src/hooks/useSessionRestoration.ts +4 -0
- package/src/hooks/useStorage.ts +4 -0
- package/src/hooks/useToast.ts +1 -1
- package/src/index.ts +2 -1
- package/src/providers/__tests__/OrganisationProvider.test.tsx +92 -70
- package/src/providers/services/AuthServiceProvider.tsx +18 -0
- package/src/providers/services/EventServiceProvider.tsx +18 -0
- package/src/providers/services/InactivityServiceProvider.tsx +18 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +36 -0
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +29 -13
- package/src/rbac/README.md +1 -1
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +2 -2
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
- package/src/rbac/adapters.tsx +14 -5
- package/src/rbac/api.ts +100 -67
- package/src/rbac/components/NavigationProvider.tsx +4 -1
- package/src/rbac/components/PagePermissionGuard.tsx +157 -17
- package/src/rbac/components/RoleBasedRouter.tsx +5 -1
- package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
- package/src/rbac/components/SecureDataProvider.tsx +20 -5
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
- package/src/rbac/engine.ts +38 -14
- package/src/rbac/hooks/permissions/index.ts +7 -0
- package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
- package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
- package/src/rbac/hooks/permissions/useCan.ts +347 -0
- package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
- package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
- package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
- package/src/rbac/hooks/useCan.test.ts +71 -64
- package/src/rbac/hooks/usePermissions.ts +14 -995
- package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
- package/src/rbac/hooks/useResourcePermissions.ts +14 -4
- package/src/rbac/hooks/useSecureSupabase.ts +33 -13
- package/src/rbac/permissions.ts +0 -30
- package/src/rbac/secureClient.ts +200 -61
- package/src/rbac/types.ts +8 -0
- package/src/theming/__tests__/parseEventColours.test.ts +6 -9
- package/src/theming/parseEventColours.ts +5 -19
- package/src/types/vitest-globals.d.ts +51 -26
- package/src/utils/__mocks__/supabaseMock.ts +1 -3
- package/src/utils/__tests__/formatting.unit.test.ts +4 -4
- package/src/utils/__tests__/index.unit.test.ts +2 -2
- package/src/utils/audit/audit.ts +0 -3
- package/src/utils/core/cn.ts +1 -1
- package/src/utils/file-reference/index.ts +53 -1
- package/src/utils/formatting/formatting.ts +8 -18
- package/src/utils/index.ts +0 -1
- package/dist/chunk-3QRJFVBR.js.map +0 -1
- package/dist/chunk-3XTALGJF.js.map +0 -1
- package/dist/chunk-4N5C5XZU.js.map +0 -1
- package/dist/chunk-4ZC4GX36.js.map +0 -1
- package/dist/chunk-BYFSK72L.js.map +0 -1
- package/dist/chunk-EXUD6RNJ.js +0 -451
- package/dist/chunk-EXUD6RNJ.js.map +0 -1
- package/dist/chunk-GLK6VM3F.js.map +0 -1
- package/dist/chunk-I7PSE6JW.js.map +0 -1
- package/dist/chunk-JBKQ3SAO.js.map +0 -1
- package/dist/chunk-KNC55RTG.js.map +0 -1
- package/dist/chunk-LXQLPRQ2.js.map +0 -1
- package/dist/chunk-R77UEZ4E.js.map +0 -1
- package/dist/chunk-SQGMNID3.js.map +0 -1
- package/dist/chunk-T33XF5ZC.js.map +0 -1
- package/dist/chunk-XM25TVIE.js.map +0 -1
- package/docs/api/classes/ErrorBoundary.md +0 -144
- package/docs/migration/quick-migration-guide.md +0 -356
- package/docs/migration/service-architecture.md +0 -281
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
- package/src/hooks/useSecureDataAccess.test.ts +0 -559
- package/src/hooks/useSecureDataAccess.ts +0 -681
- /package/dist/{DataTable-DQ7RSOHE.js.map → DataTable-TPTKCX4D.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-ATAP5UTR.js.map → UnifiedAuthProvider-CH6Z342H.js.map} +0 -0
- /package/dist/{api-N774RPUA.js.map → api-MVVQZLJI.js.map} +0 -0
- /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
- /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
- /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
- /package/docs/migration/{REACT_19_MIGRATION.md → V0.6.0_REACT_19_MIGRATION.md} +0 -0
|
@@ -14,9 +14,9 @@ import type {
|
|
|
14
14
|
import { createLogger } from '../../../utils/core/logger';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* Debug levels for controlling verbosity
|
|
17
|
+
* Debug levels for controlling verbosity (internal use only)
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
enum DebugLevel {
|
|
20
20
|
NONE = 0,
|
|
21
21
|
ERROR = 1,
|
|
22
22
|
WARN = 2,
|
|
@@ -26,9 +26,9 @@ export enum DebugLevel {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
|
-
* Performance debug configuration
|
|
29
|
+
* Performance debug configuration (internal use only)
|
|
30
30
|
*/
|
|
31
|
-
|
|
31
|
+
interface DebugConfig {
|
|
32
32
|
enabled: boolean;
|
|
33
33
|
level: DebugLevel;
|
|
34
34
|
logToConsole: boolean;
|
|
@@ -41,9 +41,9 @@ export interface DebugConfig {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* Default debug configuration
|
|
44
|
+
* Default debug configuration (internal use only)
|
|
45
45
|
*/
|
|
46
|
-
|
|
46
|
+
const DEFAULT_DEBUG_CONFIG: DebugConfig = {
|
|
47
47
|
enabled: import.meta.env.MODE === 'development',
|
|
48
48
|
level: DebugLevel.INFO,
|
|
49
49
|
logToConsole: true,
|
|
@@ -56,9 +56,9 @@ export const DEFAULT_DEBUG_CONFIG: DebugConfig = {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
|
-
* Debug log entry interface
|
|
59
|
+
* Debug log entry interface (internal use only)
|
|
60
60
|
*/
|
|
61
|
-
|
|
61
|
+
interface DebugLogEntry {
|
|
62
62
|
timestamp: number;
|
|
63
63
|
level: DebugLevel;
|
|
64
64
|
category: string;
|
|
@@ -70,9 +70,9 @@ export interface DebugLogEntry {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
|
-
* Performance timeline entry
|
|
73
|
+
* Performance timeline entry (internal use only)
|
|
74
74
|
*/
|
|
75
|
-
|
|
75
|
+
interface PerformanceTimelineEntry {
|
|
76
76
|
id: string;
|
|
77
77
|
operation: string;
|
|
78
78
|
startTime: number;
|
|
@@ -83,9 +83,9 @@ export interface PerformanceTimelineEntry {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
|
-
* Memory snapshot
|
|
86
|
+
* Memory snapshot (internal use only)
|
|
87
87
|
*/
|
|
88
|
-
|
|
88
|
+
interface MemorySnapshot {
|
|
89
89
|
timestamp: number;
|
|
90
90
|
heapUsed: number;
|
|
91
91
|
heapTotal: number;
|
|
@@ -94,9 +94,9 @@ export interface MemorySnapshot {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
/**
|
|
97
|
-
* Render performance data
|
|
97
|
+
* Render performance data (internal use only)
|
|
98
98
|
*/
|
|
99
|
-
|
|
99
|
+
interface RenderPerformanceData {
|
|
100
100
|
componentName: string;
|
|
101
101
|
renderCount: number;
|
|
102
102
|
totalRenderTime: number;
|
|
@@ -106,9 +106,9 @@ export interface RenderPerformanceData {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
|
-
* Advanced DataTable debugger
|
|
109
|
+
* Advanced DataTable debugger (internal use only)
|
|
110
110
|
*/
|
|
111
|
-
|
|
111
|
+
class DataTableDebugger {
|
|
112
112
|
private config: DebugConfig
|
|
113
113
|
private logger = createLogger('DataTableDebugger');
|
|
114
114
|
private logEntries: DebugLogEntry[] = [];
|
|
@@ -469,104 +469,9 @@ export class DataTableDebugger {
|
|
|
469
469
|
}
|
|
470
470
|
|
|
471
471
|
/**
|
|
472
|
-
* Global debugger instance
|
|
472
|
+
* Global debugger instance (internal use only)
|
|
473
473
|
*/
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
/**
|
|
477
|
-
* Performance profiler decorator
|
|
478
|
-
*/
|
|
479
|
-
export function profile(operation: string) {
|
|
480
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
481
|
-
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
|
482
|
-
const originalMethod = descriptor.value;
|
|
483
|
-
|
|
484
|
-
descriptor.value = async function (this: unknown, ...args: unknown[]) {
|
|
485
|
-
const operationId = `${target.constructor.name}.${propertyKey}_${Date.now()}`;
|
|
486
|
-
|
|
487
|
-
dataTableDebugger.startOperation(operationId, operation, {
|
|
488
|
-
className: target.constructor.name,
|
|
489
|
-
methodName: propertyKey,
|
|
490
|
-
args: args.length,
|
|
491
|
-
});
|
|
492
|
-
|
|
493
|
-
try {
|
|
494
|
-
const result = await originalMethod.apply(this, args);
|
|
495
|
-
dataTableDebugger.endOperation(operationId, { success: true });
|
|
496
|
-
return result;
|
|
497
|
-
} catch (error) {
|
|
498
|
-
dataTableDebugger.endOperation(operationId, { success: false, error: error instanceof Error ? error.message : String(error) });
|
|
499
|
-
dataTableDebugger.log(DebugLevel.ERROR, 'Performance', `Operation failed: ${operation}`, error);
|
|
500
|
-
throw error;
|
|
501
|
-
}
|
|
502
|
-
};
|
|
503
|
-
|
|
504
|
-
return descriptor;
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
/**
|
|
509
|
-
* Memory monitoring utility
|
|
510
|
-
*/
|
|
511
|
-
export class MemoryMonitor {
|
|
512
|
-
private debuggerInstance: DataTableDebugger;
|
|
513
|
-
private intervalId: NodeJS.Timeout | null = null;
|
|
514
|
-
|
|
515
|
-
constructor(debuggerInstance: DataTableDebugger = dataTableDebugger) {
|
|
516
|
-
this.debuggerInstance = debuggerInstance;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
start(interval: number = 5000): void {
|
|
520
|
-
this.stop(); // Stop any existing monitoring
|
|
521
|
-
|
|
522
|
-
this.intervalId = setInterval(() => {
|
|
523
|
-
this.debuggerInstance.takeMemorySnapshot('periodic');
|
|
524
|
-
}, interval);
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
stop(): void {
|
|
528
|
-
if (this.intervalId) {
|
|
529
|
-
clearInterval(this.intervalId);
|
|
530
|
-
this.intervalId = null;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
/**
|
|
536
|
-
* Performance monitoring React hook
|
|
537
|
-
*/
|
|
538
|
-
export function usePerformanceDebugger(componentName: string) {
|
|
539
|
-
const startTime = React.useRef<number>(0);
|
|
540
|
-
|
|
541
|
-
React.useEffect(() => {
|
|
542
|
-
startTime.current = performance.now();
|
|
543
|
-
|
|
544
|
-
return () => {
|
|
545
|
-
const renderTime = performance.now() - startTime.current;
|
|
546
|
-
dataTableDebugger.trackRender(componentName, renderTime);
|
|
547
|
-
};
|
|
548
|
-
});
|
|
549
|
-
|
|
550
|
-
const trackOperation = React.useCallback((operation: string, fn: () => unknown) => {
|
|
551
|
-
const operationId = `${componentName}_${operation}_${Date.now()}`;
|
|
552
|
-
dataTableDebugger.startOperation(operationId, operation);
|
|
553
|
-
|
|
554
|
-
try {
|
|
555
|
-
const result = fn();
|
|
556
|
-
dataTableDebugger.endOperation(operationId);
|
|
557
|
-
return result;
|
|
558
|
-
} catch (error) {
|
|
559
|
-
dataTableDebugger.endOperation(operationId, { error: error instanceof Error ? error.message : String(error) });
|
|
560
|
-
throw error;
|
|
561
|
-
}
|
|
562
|
-
}, [componentName]);
|
|
563
|
-
|
|
564
|
-
return {
|
|
565
|
-
trackOperation,
|
|
566
|
-
log: (level: DebugLevel, message: string, data?: unknown) =>
|
|
567
|
-
dataTableDebugger.log(level, componentName, message, data),
|
|
568
|
-
};
|
|
569
|
-
}
|
|
474
|
+
const dataTableDebugger = new DataTableDebugger();
|
|
570
475
|
|
|
571
476
|
/**
|
|
572
477
|
* Development tools integration
|
|
@@ -23,6 +23,10 @@ export enum DataTableErrorType {
|
|
|
23
23
|
MEMORY = 'memory'
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Custom error class for DataTable operations.
|
|
28
|
+
* Provides error type and recoverability information.
|
|
29
|
+
*/
|
|
26
30
|
export class DataTableError extends Error {
|
|
27
31
|
constructor(
|
|
28
32
|
message: string,
|
|
@@ -34,6 +38,10 @@ export class DataTableError extends Error {
|
|
|
34
38
|
}
|
|
35
39
|
}
|
|
36
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Error recovery manager for DataTable.
|
|
43
|
+
* Handles error recovery strategies and error logging.
|
|
44
|
+
*/
|
|
37
45
|
export class ErrorRecoveryManager {
|
|
38
46
|
constructor(private config: FallbackConfig) {}
|
|
39
47
|
|
|
@@ -46,6 +54,10 @@ export class ErrorRecoveryManager {
|
|
|
46
54
|
}
|
|
47
55
|
}
|
|
48
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Memory monitor for DataTable.
|
|
59
|
+
* Tracks memory usage and provides warnings when thresholds are exceeded.
|
|
60
|
+
*/
|
|
49
61
|
export class MemoryMonitor {
|
|
50
62
|
constructor(private threshold: number = 100) {}
|
|
51
63
|
|
|
@@ -333,6 +333,15 @@ export async function exportToCSVWithTableRows(
|
|
|
333
333
|
* - Triggers browser download
|
|
334
334
|
* - Throws error if export fails
|
|
335
335
|
*/
|
|
336
|
+
/**
|
|
337
|
+
* Exports DataTable data to CSV format.
|
|
338
|
+
* Handles column mapping, data formatting, and browser download.
|
|
339
|
+
*
|
|
340
|
+
* @template TData - The type of data records in the table
|
|
341
|
+
* @param data - Array of data records to export
|
|
342
|
+
* @param columns - Column definitions for export
|
|
343
|
+
* @param filename - Name of the CSV file to download
|
|
344
|
+
*/
|
|
336
345
|
export function exportToCSV<TData extends DataRecord>(
|
|
337
346
|
data: TData[],
|
|
338
347
|
columns: ExportColumn[],
|
|
@@ -11,10 +11,18 @@
|
|
|
11
11
|
import { createLogger } from '../../../utils/core/logger';
|
|
12
12
|
import type { CellValue } from '../types';
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Column mapping interface for CSV import.
|
|
16
|
+
* Maps target field names to possible CSV column names.
|
|
17
|
+
*/
|
|
14
18
|
export interface ColumnMapping {
|
|
15
19
|
[targetField: string]: string[];
|
|
16
20
|
}
|
|
17
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Options for flexible CSV import.
|
|
24
|
+
* Configures column mapping, date parsing, validation, and other import settings.
|
|
25
|
+
*/
|
|
18
26
|
export interface ImportOptions {
|
|
19
27
|
columnMappings?: ColumnMapping;
|
|
20
28
|
dateFormats?: readonly string[];
|
|
@@ -160,6 +168,10 @@ export interface ImportError {
|
|
|
160
168
|
message: string;
|
|
161
169
|
}
|
|
162
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Import warning interface.
|
|
173
|
+
* Represents warnings encountered during CSV import.
|
|
174
|
+
*/
|
|
163
175
|
export interface ImportWarning {
|
|
164
176
|
row: number;
|
|
165
177
|
field: string;
|
|
@@ -609,54 +621,6 @@ export const commonMappings = {
|
|
|
609
621
|
}
|
|
610
622
|
};
|
|
611
623
|
|
|
612
|
-
/**
|
|
613
|
-
* Helper function to create import options with predefined date format sets
|
|
614
|
-
*/
|
|
615
|
-
export function createImportOptions(options: Partial<ImportOptions> = {}): ImportOptions {
|
|
616
|
-
return {
|
|
617
|
-
dateFormats: DATE_FORMAT_SETS.ALL,
|
|
618
|
-
strictDateParsing: false,
|
|
619
|
-
...options,
|
|
620
|
-
};
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
/**
|
|
624
|
-
* Helper function to create import options for specific regions
|
|
625
|
-
*/
|
|
626
|
-
export function createRegionalImportOptions(region: 'US' | 'EUROPEAN' | 'ISO' | 'NATURAL' | 'ALL', options: Partial<ImportOptions> = {}): ImportOptions {
|
|
627
|
-
return {
|
|
628
|
-
dateFormats: DATE_FORMAT_SETS[region],
|
|
629
|
-
strictDateParsing: false,
|
|
630
|
-
...options,
|
|
631
|
-
};
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
/**
|
|
635
|
-
* Helper function to test if a string can be parsed as a date
|
|
636
|
-
*/
|
|
637
|
-
export function testDateParsing(dateStr: string, formats?: string[]): { success: boolean; parsedDate?: Date; matchedFormat?: string } {
|
|
638
|
-
if (!dateStr || typeof dateStr !== 'string') {
|
|
639
|
-
return { success: false };
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
const testFormats = formats || DATE_FORMAT_SETS.ALL;
|
|
643
|
-
|
|
644
|
-
for (const format of testFormats) {
|
|
645
|
-
// This is a simplified version of the parseDateWithFormat function
|
|
646
|
-
// In a real implementation, you'd want to reuse the actual parsing logic
|
|
647
|
-
try {
|
|
648
|
-
const date = new Date(dateStr);
|
|
649
|
-
if (!isNaN(date.getTime())) {
|
|
650
|
-
return { success: true, parsedDate: date, matchedFormat: 'native' };
|
|
651
|
-
}
|
|
652
|
-
} catch (error) {
|
|
653
|
-
// Continue to next format
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
return { success: false };
|
|
658
|
-
}
|
|
659
|
-
|
|
660
624
|
/**
|
|
661
625
|
* Helper function to get suggested date formats based on sample data
|
|
662
626
|
*/
|
|
@@ -121,6 +121,14 @@ export interface PaginationBinding {
|
|
|
121
121
|
* });
|
|
122
122
|
* ```
|
|
123
123
|
*/
|
|
124
|
+
/**
|
|
125
|
+
* Creates a unified pagination binding that works across all pagination modes.
|
|
126
|
+
* Provides consistent pagination state and actions regardless of client/server/hybrid mode.
|
|
127
|
+
*
|
|
128
|
+
* @template TData - The type of data records in the table
|
|
129
|
+
* @param config - Pagination binding configuration
|
|
130
|
+
* @returns Unified pagination state and actions
|
|
131
|
+
*/
|
|
124
132
|
export function getPaginationBinding<TData extends DataRecord>(
|
|
125
133
|
config: PaginationBindingConfig<TData>
|
|
126
134
|
): PaginationBinding {
|
|
@@ -17,7 +17,7 @@ import type {
|
|
|
17
17
|
// ============================================================================
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Determines the optimal pagination mode based on dataset size
|
|
20
|
+
* Determines the optimal pagination mode based on dataset size.
|
|
21
21
|
*
|
|
22
22
|
* IMPORTANT: This function NEVER returns 'server' mode - it only returns 'client' or 'hybrid'.
|
|
23
23
|
* Server mode should ONLY be used when serverSide config is explicitly provided.
|
|
@@ -26,6 +26,10 @@ import type {
|
|
|
26
26
|
*
|
|
27
27
|
* For large datasets (>10k rows), returns 'hybrid' which still uses client-side pagination
|
|
28
28
|
* but with optimizations. If true server-side pagination is needed, serverSide config must be provided.
|
|
29
|
+
*
|
|
30
|
+
* @param dataLength - Number of rows in the dataset
|
|
31
|
+
* @param serverSideThreshold - Threshold for switching to hybrid mode (default: 10000)
|
|
32
|
+
* @returns Optimal pagination mode ('client' or 'hybrid')
|
|
29
33
|
*/
|
|
30
34
|
export function determinePaginationMode(
|
|
31
35
|
dataLength: number,
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
* </DialogHeader>
|
|
44
44
|
* <DialogBody>
|
|
45
45
|
* <section className="space-y-4">
|
|
46
|
-
* <
|
|
46
|
+
* <fieldset className="grid grid-cols-4 items-center gap-4">
|
|
47
47
|
* <Label htmlFor="name" className="text-right">Name</Label>
|
|
48
48
|
* <Input id="name" defaultValue="John Doe" className="col-span-3" />
|
|
49
|
-
* </
|
|
49
|
+
* </fieldset>
|
|
50
50
|
* </section>
|
|
51
51
|
* </DialogBody>
|
|
52
52
|
* <DialogFooter>
|
|
@@ -8,7 +8,8 @@ import React from 'react';
|
|
|
8
8
|
import { screen, waitFor } from '@testing-library/react';
|
|
9
9
|
import userEvent from '@testing-library/user-event';
|
|
10
10
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
11
|
-
import { ErrorBoundary } from './
|
|
11
|
+
import { ErrorBoundary } from './index';
|
|
12
|
+
import { ErrorBoundaryProvider } from './ErrorBoundaryContext';
|
|
12
13
|
import { renderWithProviders } from '../../__tests__/helpers/test-utils';
|
|
13
14
|
|
|
14
15
|
// Mock the performance budget monitor
|
|
@@ -778,4 +779,182 @@ describe('ErrorBoundary Component', () => {
|
|
|
778
779
|
}
|
|
779
780
|
vi.clearAllMocks();
|
|
780
781
|
});
|
|
782
|
+
|
|
783
|
+
describe('Global Error Handler', () => {
|
|
784
|
+
it('uses global error handler when no onError prop is provided', async () => {
|
|
785
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
786
|
+
const globalErrorHandler = vi.fn();
|
|
787
|
+
|
|
788
|
+
renderWithProviders(
|
|
789
|
+
<ErrorBoundaryProvider defaultErrorHandler={globalErrorHandler}>
|
|
790
|
+
<ErrorBoundary componentName="TestComponent">
|
|
791
|
+
<ThrowingComponent />
|
|
792
|
+
</ErrorBoundary>
|
|
793
|
+
</ErrorBoundaryProvider>
|
|
794
|
+
);
|
|
795
|
+
|
|
796
|
+
await waitFor(() => {
|
|
797
|
+
expect(globalErrorHandler).toHaveBeenCalledTimes(1);
|
|
798
|
+
expect(globalErrorHandler).toHaveBeenCalledWith(
|
|
799
|
+
expect.any(Error),
|
|
800
|
+
expect.any(Object), // errorInfo
|
|
801
|
+
expect.any(String), // errorId
|
|
802
|
+
'TestComponent' // componentName
|
|
803
|
+
);
|
|
804
|
+
}, { interval: 10 });
|
|
805
|
+
|
|
806
|
+
consoleSpy.mockRestore();
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
it('uses global error handler with default component name when componentName not provided', async () => {
|
|
810
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
811
|
+
const globalErrorHandler = vi.fn();
|
|
812
|
+
|
|
813
|
+
renderWithProviders(
|
|
814
|
+
<ErrorBoundaryProvider defaultErrorHandler={globalErrorHandler}>
|
|
815
|
+
<ErrorBoundary>
|
|
816
|
+
<ThrowingComponent />
|
|
817
|
+
</ErrorBoundary>
|
|
818
|
+
</ErrorBoundaryProvider>
|
|
819
|
+
);
|
|
820
|
+
|
|
821
|
+
await waitFor(() => {
|
|
822
|
+
expect(globalErrorHandler).toHaveBeenCalledTimes(1);
|
|
823
|
+
expect(globalErrorHandler).toHaveBeenCalledWith(
|
|
824
|
+
expect.any(Error),
|
|
825
|
+
expect.any(Object), // errorInfo
|
|
826
|
+
expect.any(String), // errorId
|
|
827
|
+
'Unknown Component' // componentName (default)
|
|
828
|
+
);
|
|
829
|
+
}, { interval: 10 });
|
|
830
|
+
|
|
831
|
+
consoleSpy.mockRestore();
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
it('prefers onError prop over global error handler', async () => {
|
|
835
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
836
|
+
const globalErrorHandler = vi.fn();
|
|
837
|
+
const localErrorHandler = vi.fn();
|
|
838
|
+
|
|
839
|
+
renderWithProviders(
|
|
840
|
+
<ErrorBoundaryProvider defaultErrorHandler={globalErrorHandler}>
|
|
841
|
+
<ErrorBoundary
|
|
842
|
+
componentName="TestComponent"
|
|
843
|
+
onError={localErrorHandler}
|
|
844
|
+
>
|
|
845
|
+
<ThrowingComponent />
|
|
846
|
+
</ErrorBoundary>
|
|
847
|
+
</ErrorBoundaryProvider>
|
|
848
|
+
);
|
|
849
|
+
|
|
850
|
+
await waitFor(() => {
|
|
851
|
+
expect(localErrorHandler).toHaveBeenCalledTimes(1);
|
|
852
|
+
expect(globalErrorHandler).not.toHaveBeenCalled();
|
|
853
|
+
}, { interval: 10 });
|
|
854
|
+
|
|
855
|
+
consoleSpy.mockRestore();
|
|
856
|
+
});
|
|
857
|
+
|
|
858
|
+
it('does not call global handler when ErrorBoundary is not wrapped in provider', async () => {
|
|
859
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
860
|
+
const globalErrorHandler = vi.fn();
|
|
861
|
+
|
|
862
|
+
// Render without provider
|
|
863
|
+
renderWithProviders(
|
|
864
|
+
<ErrorBoundary componentName="TestComponent">
|
|
865
|
+
<ThrowingComponent />
|
|
866
|
+
</ErrorBoundary>
|
|
867
|
+
);
|
|
868
|
+
|
|
869
|
+
await waitFor(() => {
|
|
870
|
+
expect(screen.getByText('Error in TestComponent')).toBeInTheDocument();
|
|
871
|
+
}, { interval: 10 });
|
|
872
|
+
|
|
873
|
+
// Global handler should not be called since there's no provider
|
|
874
|
+
expect(globalErrorHandler).not.toHaveBeenCalled();
|
|
875
|
+
|
|
876
|
+
consoleSpy.mockRestore();
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
it('works with nested ErrorBoundary providers (inner provider overrides outer)', async () => {
|
|
880
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
881
|
+
const outerErrorHandler = vi.fn();
|
|
882
|
+
const innerErrorHandler = vi.fn();
|
|
883
|
+
|
|
884
|
+
renderWithProviders(
|
|
885
|
+
<ErrorBoundaryProvider defaultErrorHandler={outerErrorHandler}>
|
|
886
|
+
<ErrorBoundary componentName="Outer">
|
|
887
|
+
<ErrorBoundaryProvider defaultErrorHandler={innerErrorHandler}>
|
|
888
|
+
<ErrorBoundary componentName="Inner">
|
|
889
|
+
<ThrowingComponent />
|
|
890
|
+
</ErrorBoundary>
|
|
891
|
+
</ErrorBoundaryProvider>
|
|
892
|
+
</ErrorBoundary>
|
|
893
|
+
</ErrorBoundaryProvider>
|
|
894
|
+
);
|
|
895
|
+
|
|
896
|
+
await waitFor(() => {
|
|
897
|
+
expect(innerErrorHandler).toHaveBeenCalledTimes(1);
|
|
898
|
+
expect(innerErrorHandler).toHaveBeenCalledWith(
|
|
899
|
+
expect.any(Error),
|
|
900
|
+
expect.any(Object),
|
|
901
|
+
expect.any(String),
|
|
902
|
+
'Inner'
|
|
903
|
+
);
|
|
904
|
+
// Outer handler should not be called for inner boundary
|
|
905
|
+
expect(outerErrorHandler).not.toHaveBeenCalled();
|
|
906
|
+
}, { interval: 10 });
|
|
907
|
+
|
|
908
|
+
consoleSpy.mockRestore();
|
|
909
|
+
});
|
|
910
|
+
|
|
911
|
+
it('allows ErrorBoundaryProvider without defaultErrorHandler (no-op)', async () => {
|
|
912
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
913
|
+
|
|
914
|
+
renderWithProviders(
|
|
915
|
+
<ErrorBoundaryProvider>
|
|
916
|
+
<ErrorBoundary componentName="TestComponent">
|
|
917
|
+
<ThrowingComponent />
|
|
918
|
+
</ErrorBoundary>
|
|
919
|
+
</ErrorBoundaryProvider>
|
|
920
|
+
);
|
|
921
|
+
|
|
922
|
+
await waitFor(() => {
|
|
923
|
+
expect(screen.getByText('Error in TestComponent')).toBeInTheDocument();
|
|
924
|
+
}, { interval: 10 });
|
|
925
|
+
|
|
926
|
+
// Should render error UI without calling any handler
|
|
927
|
+
expect(screen.getByText('Error in TestComponent')).toBeInTheDocument();
|
|
928
|
+
|
|
929
|
+
consoleSpy.mockRestore();
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
it('passes correct error information to global handler', async () => {
|
|
933
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
934
|
+
const globalErrorHandler = vi.fn();
|
|
935
|
+
const testError = new Error('Custom test error');
|
|
936
|
+
|
|
937
|
+
renderWithProviders(
|
|
938
|
+
<ErrorBoundaryProvider defaultErrorHandler={globalErrorHandler}>
|
|
939
|
+
<ErrorBoundary componentName="TestComponent">
|
|
940
|
+
<ThrowingComponent errorMessage="Custom test error" />
|
|
941
|
+
</ErrorBoundary>
|
|
942
|
+
</ErrorBoundaryProvider>
|
|
943
|
+
);
|
|
944
|
+
|
|
945
|
+
await waitFor(() => {
|
|
946
|
+
expect(globalErrorHandler).toHaveBeenCalledTimes(1);
|
|
947
|
+
const callArgs = globalErrorHandler.mock.calls[0];
|
|
948
|
+
expect(callArgs[0]).toBeInstanceOf(Error);
|
|
949
|
+
expect(callArgs[0].message).toBe('Custom test error');
|
|
950
|
+
expect(callArgs[1]).toBeDefined(); // errorInfo
|
|
951
|
+
expect(callArgs[1].componentStack).toBeDefined();
|
|
952
|
+
expect(typeof callArgs[2]).toBe('string'); // errorId
|
|
953
|
+
expect(callArgs[2]).toMatch(/^error_/); // errorId format
|
|
954
|
+
expect(callArgs[3]).toBe('TestComponent'); // componentName
|
|
955
|
+
}, { interval: 10 });
|
|
956
|
+
|
|
957
|
+
consoleSpy.mockRestore();
|
|
958
|
+
});
|
|
959
|
+
});
|
|
781
960
|
});
|
|
@@ -25,10 +25,35 @@
|
|
|
25
25
|
* <MyComponent />
|
|
26
26
|
* </ErrorBoundary>
|
|
27
27
|
*
|
|
28
|
+
* // Using global error handler (recommended for applications)
|
|
29
|
+
* import { ErrorBoundaryProvider, ErrorBoundary } from '@jmruthers/pace-core';
|
|
30
|
+
*
|
|
31
|
+
* // Setup once in main.tsx
|
|
32
|
+
* <ErrorBoundaryProvider
|
|
33
|
+
* defaultErrorHandler={(error, errorInfo, errorId, componentName) => {
|
|
34
|
+
* if (import.meta.env.DEV) {
|
|
35
|
+
* console.error(`[${componentName}] ErrorBoundary caught error:`, error, errorInfo);
|
|
36
|
+
* }
|
|
37
|
+
* errorTracking.captureException(error, {
|
|
38
|
+
* componentStack: errorInfo.componentStack,
|
|
39
|
+
* errorBoundary: true,
|
|
40
|
+
* errorId,
|
|
41
|
+
* componentName,
|
|
42
|
+
* });
|
|
43
|
+
* }}
|
|
44
|
+
* >
|
|
45
|
+
* <App />
|
|
46
|
+
* </ErrorBoundaryProvider>
|
|
47
|
+
*
|
|
48
|
+
* // Then use ErrorBoundary without onError prop - uses global handler
|
|
49
|
+
* <ErrorBoundary componentName="AppRoot">
|
|
50
|
+
* <AppContent />
|
|
51
|
+
* </ErrorBoundary>
|
|
52
|
+
*
|
|
28
53
|
* // Error boundary with custom fallback
|
|
29
54
|
* <ErrorBoundary
|
|
30
55
|
* componentName="UserProfile"
|
|
31
|
-
* fallback={<
|
|
56
|
+
* fallback={<section>Something went wrong loading the profile.</section>}
|
|
32
57
|
* onError={(error, errorInfo, errorId) => {
|
|
33
58
|
* console.log('Error caught:', errorId, error);
|
|
34
59
|
* }}
|
|
@@ -58,6 +83,16 @@
|
|
|
58
83
|
* </ErrorBoundary>
|
|
59
84
|
* <Footer />
|
|
60
85
|
* </ErrorBoundary>
|
|
86
|
+
*
|
|
87
|
+
* // Per-instance onError overrides global handler
|
|
88
|
+
* <ErrorBoundary
|
|
89
|
+
* componentName="SpecialCase"
|
|
90
|
+
* onError={(error, errorInfo, errorId) => {
|
|
91
|
+
* // Custom handling for this specific case - global handler won't be called
|
|
92
|
+
* }}
|
|
93
|
+
* >
|
|
94
|
+
* <SpecialComponent />
|
|
95
|
+
* </ErrorBoundary>
|
|
61
96
|
* ```
|
|
62
97
|
*
|
|
63
98
|
* @accessibility
|
|
@@ -120,6 +155,8 @@ export interface ErrorBoundaryProps {
|
|
|
120
155
|
enableRetry?: boolean;
|
|
121
156
|
/** Whether to enable error reporting */
|
|
122
157
|
enableReporting?: boolean;
|
|
158
|
+
/** Internal: Global error handler from context (not part of public API) */
|
|
159
|
+
_globalErrorHandler?: (error: Error, errorInfo: React.ErrorInfo, errorId: string, componentName: string) => void;
|
|
123
160
|
}
|
|
124
161
|
|
|
125
162
|
/**
|
|
@@ -162,15 +199,16 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt
|
|
|
162
199
|
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
|
163
200
|
const { componentName = 'Unknown Component', onError, enableReporting = true } = this.props;
|
|
164
201
|
const errorId = this.state.errorId!;
|
|
202
|
+
const componentNameForHandler = componentName || 'Unknown Component';
|
|
165
203
|
|
|
166
204
|
this.setState({ errorInfo });
|
|
167
205
|
|
|
168
206
|
// Enhanced logging with component name and error ID
|
|
169
|
-
logger.error('ErrorBoundary', `[${
|
|
207
|
+
logger.error('ErrorBoundary', `[${componentNameForHandler}] Caught error ${errorId}:`, error, errorInfo);
|
|
170
208
|
|
|
171
209
|
// Performance monitoring - track error occurrence
|
|
172
210
|
performanceBudgetMonitor.measure('ERROR_BOUNDARY_TRIGGER', 1, {
|
|
173
|
-
componentName,
|
|
211
|
+
componentName: componentNameForHandler,
|
|
174
212
|
errorId,
|
|
175
213
|
errorMessage: error.message,
|
|
176
214
|
stack: error.stack?.substring(0, 200), // Truncated stack trace
|
|
@@ -178,12 +216,14 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt
|
|
|
178
216
|
|
|
179
217
|
// Report error if enabled
|
|
180
218
|
if (enableReporting) {
|
|
181
|
-
this.reportError(errorId,
|
|
219
|
+
this.reportError(errorId, componentNameForHandler);
|
|
182
220
|
}
|
|
183
221
|
|
|
184
|
-
// Call
|
|
222
|
+
// Call error handler: prefer prop onError, fall back to global handler from props
|
|
185
223
|
if (onError) {
|
|
186
224
|
onError(error, errorInfo, errorId);
|
|
225
|
+
} else if (this.props._globalErrorHandler) {
|
|
226
|
+
this.props._globalErrorHandler(error, errorInfo, errorId, componentNameForHandler);
|
|
187
227
|
}
|
|
188
228
|
}
|
|
189
229
|
|