@jmruthers/pace-core 0.6.10 → 0.6.11
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 +21 -0
- package/audit-tool/00-dependencies.cjs +46 -13
- package/audit-tool/audits/01-pace-core-compliance.cjs +96 -21
- package/audit-tool/audits/02-project-structure.cjs +13 -3
- package/audit-tool/audits/03-architecture.cjs +78 -4
- package/audit-tool/audits/04-code-quality.cjs +9 -2
- package/audit-tool/audits/05-styling.cjs +19 -7
- package/audit-tool/audits/06-security-rbac.cjs +105 -14
- package/audit-tool/audits/07-api-tech-stack.cjs +31 -15
- package/audit-tool/audits/08-testing-documentation.cjs +11 -3
- package/audit-tool/audits/09-operations.cjs +19 -7
- package/audit-tool/index.cjs +22 -11
- package/audit-tool/utils/report-utils.cjs +4 -0
- package/cursor-rules/01-pace-core-compliance.mdc +1 -0
- package/cursor-rules/02-project-structure.mdc +1 -0
- package/cursor-rules/03-architecture.mdc +3 -1
- package/cursor-rules/04-code-quality.mdc +1 -0
- package/cursor-rules/05-styling.mdc +41 -7
- package/cursor-rules/06-security-rbac.mdc +2 -1
- package/cursor-rules/07-api-tech-stack.mdc +1 -0
- package/cursor-rules/08-testing-documentation.mdc +1 -0
- package/cursor-rules/09-operations.mdc +1 -0
- package/dist/{DataTable-SAXFG4XI.js → DataTable-EFYP2QLE.js} +10 -7
- package/dist/{InactivityServiceProvider-DHryoh6K.d.ts → InactivityServiceProvider-BbxwwDz1.d.ts} +10 -1
- package/dist/{UnifiedAuthProvider-CiBAl9-s.d.ts → UnifiedAuthProvider-Bkt_tzdS.d.ts} +56 -24
- package/dist/{api-F47QJ7FX.js → api-BZR2CYXL.js} +3 -2
- package/dist/api-result-USV1Czr-.d.ts +51 -0
- package/dist/{audit-Z6ZZBWLU.js → audit-HI2DHUVU.js} +2 -1
- package/dist/{auth-BZOJqrdd.d.ts → auth-JvdRVaud.d.ts} +1 -1
- package/dist/{chunk-KSNLMI7N.js → chunk-2DL2WSOE.js} +1 -155
- package/dist/{chunk-MPY44PWB.js → chunk-2OEVOGGR.js} +4648 -3560
- package/dist/chunk-44CNXN4P.js +15 -0
- package/dist/{chunk-Y4PF6HIM.js → chunk-4R3T5ENU.js} +867 -786
- package/dist/{chunk-LNHFAF4X.js → chunk-7A6IMHH2.js} +289 -247
- package/dist/chunk-CU2BU2MQ.js +2 -0
- package/dist/{chunk-JJEYZ3DX.js → chunk-D6BMFMQZ.js} +37 -2
- package/dist/{chunk-BCTXBU6U.js → chunk-ENLXB7GP.js} +88 -71
- package/dist/{chunk-FBZ7U3ID.js → chunk-J2KQK6DG.js} +937 -987
- package/dist/{chunk-TFIPNIPE.js → chunk-KJXRL3XE.js} +3300 -2245
- package/dist/{chunk-3GWSPISD.js → chunk-L5LFKKLJ.js} +1 -1
- package/dist/{chunk-X5EAU5G7.js → chunk-PCSHBLPB.js} +132 -114
- package/dist/{chunk-NIU6DPQV.js → chunk-QRYSEPHB.js} +2 -0
- package/dist/{chunk-KYURMOQM.js → chunk-V7FTM2LU.js} +423 -320
- package/dist/chunk-WY6Y7KC3.js +264 -0
- package/dist/{chunk-FN52B75D.js → chunk-XOJME5T7.js} +176 -15
- package/dist/{chunk-7YDC7LMU.js → chunk-XPFVT3GN.js} +71 -66
- package/dist/{chunk-66R6RLUZ.js → chunk-YFTFFJIV.js} +3 -3
- package/dist/{chunk-W46INAVW.js → chunk-YYTWKVHO.js} +688 -570
- package/dist/components.d.ts +8 -7
- package/dist/components.js +17 -15
- package/dist/{database.generated-DT8JTZiP.d.ts → database.generated-qkdoiVrJ.d.ts} +45 -10
- package/dist/eslint-rules/index.cjs +3 -0
- package/dist/eslint-rules/rules/03-architecture.cjs +74 -0
- package/dist/eslint-rules/rules/06-security-rbac.cjs +74 -0
- package/dist/{event-WTAQuGcq.d.ts → event-BfCox3N2.d.ts} +36 -10
- package/dist/{file-reference-BavO2eQj.d.ts → file-reference-DU1hcawx.d.ts} +29 -13
- package/dist/hooks.d.ts +22 -9
- package/dist/hooks.js +34 -25
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +1 -0
- package/dist/index.d.ts +66 -177
- package/dist/index.js +316 -340
- package/dist/pagination-BW1mqywp.d.ts +201 -0
- package/dist/providers.d.ts +6 -5
- package/dist/providers.js +5 -3
- package/dist/rbac/index.d.ts +123 -138
- package/dist/rbac/index.js +10 -8
- package/dist/theming/runtime.d.ts +19 -2
- package/dist/theming/runtime.js +1 -1
- package/dist/{timezone-K-ptz3HO.d.ts → timezone-BTWWXKVY.d.ts} +1 -1
- package/dist/types.d.ts +17 -10
- package/dist/types.js +1 -0
- package/dist/{usePublicPageContext-vxBlEHO9.d.ts → usePublicPageContext-B91dGYW1.d.ts} +433 -356
- package/dist/{usePublicRouteParams-G3Ks53mk.d.ts → usePublicRouteParams-BgV6VhMi.d.ts} +73 -4
- package/dist/utils.d.ts +163 -145
- package/dist/utils.js +42 -25
- package/docs/api/modules.md +782 -643
- package/docs/api-reference/rpc-functions.md +12 -3
- package/docs/core-concepts/rbac-system.md +8 -0
- package/docs/getting-started/cursor-rules.md +17 -20
- package/docs/getting-started/dependencies.md +1 -1
- package/docs/getting-started/setup.md +235 -0
- package/docs/implementation-guides/authentication.md +27 -0
- package/docs/implementation-guides/data-tables.md +176 -3
- package/docs/migration/ApiResult-migration.md +25 -0
- package/docs/rbac/api-reference.md +33 -31
- package/docs/standards/0-standards-overview.md +50 -15
- package/docs/standards/1-pace-core-compliance-standards.md +62 -57
- package/docs/standards/2-project-structure-standards.md +33 -16
- package/docs/standards/3-architecture-standards.md +41 -1
- package/docs/standards/4-code-quality-standards.md +26 -6
- package/docs/standards/5-styling-standards.md +35 -1
- package/docs/standards/6-security-rbac-standards.md +66 -0
- package/docs/standards/7-api-tech-stack-standards.md +25 -14
- package/docs/standards/8-testing-documentation-standards.md +31 -0
- package/docs/standards/9-operations-standards.md +19 -0
- package/docs/standards/README.md +20 -201
- package/docs/testing/test-setup-for-consumers.md +2 -0
- package/docs/troubleshooting/common-issues.md +17 -1
- package/docs/troubleshooting/organisation-context-setup.md +8 -0
- package/docs/troubleshooting/print-event-name-css-variable-analysis.md +217 -0
- package/eslint-config-pace-core.cjs +20 -0
- package/package.json +14 -20
- package/scripts/{build-docs-incremental.js → build-docs.js} +3 -2
- package/scripts/setup.cjs +536 -0
- package/scripts/validate.cjs +480 -0
- package/src/__tests__/helpers/{__tests__/component-test-utils.test.tsx → component-test-utils.test.tsx} +3 -3
- package/src/__tests__/helpers/{__tests__/optimized-test-setup.test.ts → optimized-test-setup.test.ts} +2 -2
- package/src/__tests__/helpers/{__tests__/supabaseMock.test.ts → supabaseMock.test.ts} +2 -2
- package/src/__tests__/helpers/{__tests__/test-providers.test.tsx → test-providers.test.tsx} +1 -1
- package/src/__tests__/helpers/test-providers.tsx +37 -39
- package/src/__tests__/helpers/{__tests__/test-utils.test.tsx → test-utils.test.tsx} +4 -3
- package/src/__tests__/helpers/{__tests__/timer-utils.test.ts → timer-utils.test.ts} +2 -2
- package/src/assets/app-icons/index.test.ts +304 -0
- package/src/components/AddressField/AddressField.test.tsx +1 -1
- package/src/components/AddressField/AddressField.tsx +238 -212
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/Card/Card.test.tsx +172 -17
- package/src/components/Card/Card.tsx +19 -10
- package/src/components/ContextSelector/ContextSelector.internals.tsx +204 -0
- package/src/components/ContextSelector/{__tests__/ContextSelector.test.tsx → ContextSelector.test.tsx} +6 -6
- package/src/components/ContextSelector/ContextSelector.tsx +66 -280
- package/src/components/ContextSelector/ContextSelector.types.ts +35 -0
- package/src/components/ContextSelector/useContextSelectorState.tsx +195 -0
- package/src/components/DataTable/AUDIT_REPORT.md +59 -44
- package/src/components/DataTable/{__tests__/DataTable.comprehensive.test.tsx → DataTable.comprehensive.test.tsx} +6 -6
- package/src/components/DataTable/{__tests__/DataTable.default-state.test.tsx → DataTable.default-state.test.tsx} +5 -5
- package/src/components/DataTable/{__tests__/DataTable.export.test.tsx → DataTable.export.test.tsx} +10 -10
- package/src/components/DataTable/{__tests__/DataTable.grouping-aggregation.test.tsx → DataTable.grouping-aggregation.test.tsx} +6 -6
- package/src/components/DataTable/{__tests__/DataTable.hooks.test.tsx → DataTable.hooks.test.tsx} +6 -6
- package/src/components/DataTable/{__tests__/DataTable.select-label-display.test.tsx → DataTable.select-label-display.test.tsx} +6 -6
- package/src/components/DataTable/DataTable.test.tsx +787 -416
- package/src/components/DataTable/DataTable.tsx +12 -12
- package/src/components/DataTable/DataTableCore.integration.test.tsx +458 -0
- package/src/components/DataTable/{__tests__/DataTableCore.test-setup.ts → DataTableCore.test-setup.ts} +10 -9
- package/src/components/DataTable/{__tests__/DataTableCore.test.tsx → DataTableCore.test.tsx} +8 -8
- package/src/components/DataTable/{__tests__/README.md → README.md} +17 -7
- package/src/components/DataTable/TESTING.md +101 -0
- package/src/components/DataTable/{__tests__/a11y.basic.test.tsx → a11y.basic.test.tsx} +34 -34
- package/src/components/DataTable/components/DataTableCore.tsx +104 -864
- package/src/components/DataTable/components/{__tests__/GroupingDropdown.test.tsx → GroupingDropdown.test.tsx} +17 -8
- package/src/components/DataTable/components/GroupingDropdown.tsx +2 -2
- package/src/components/DataTable/components/ImportModal.tsx +61 -559
- package/src/components/DataTable/components/ImportModalFileSection.tsx +148 -0
- package/src/components/DataTable/context/{__tests__/DataTableContext.test.tsx → DataTableContext.test.tsx} +2 -2
- package/src/components/DataTable/context/DataTableContext.tsx +7 -6
- package/src/components/DataTable/core/{__tests__/ColumnFactory.test.ts → ColumnFactory.test.ts} +2 -2
- package/src/components/DataTable/hooks/{__tests__/useColumnOrderPersistence.test.ts → useColumnOrderPersistence.test.ts} +2 -2
- package/src/components/DataTable/hooks/{__tests__/useColumnVisibilityPersistence.test.ts → useColumnVisibilityPersistence.test.ts} +2 -2
- package/src/components/DataTable/hooks/{__tests__/useDataTableConfiguration.test.ts → useDataTableConfiguration.test.ts} +3 -3
- package/src/components/DataTable/hooks/useDataTableConfiguration.ts +14 -2
- package/src/components/DataTable/hooks/{__tests__/useDataTableDataPipeline.test.ts → useDataTableDataPipeline.test.ts} +6 -6
- package/src/components/DataTable/hooks/useDataTableDeletionBatching.test.ts +127 -0
- package/src/components/DataTable/hooks/useDataTableDeletionBatching.ts +106 -0
- package/src/components/DataTable/hooks/useDataTableEffectiveActions.test.ts +461 -0
- package/src/components/DataTable/hooks/useDataTableEffectiveActions.ts +238 -0
- package/src/components/DataTable/hooks/useDataTableLayoutHandlers.test.ts +296 -0
- package/src/components/DataTable/hooks/useDataTableLayoutHandlers.ts +175 -0
- package/src/components/DataTable/hooks/useDataTablePaginationSync.test.ts +203 -0
- package/src/components/DataTable/hooks/useDataTablePaginationSync.ts +109 -0
- package/src/components/DataTable/hooks/{__tests__/useDataTablePermissions.test.ts → useDataTablePermissions.test.ts} +11 -11
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +79 -247
- package/src/components/DataTable/hooks/useDataTablePipeline.test.tsx +219 -0
- package/src/components/DataTable/hooks/useDataTablePipeline.tsx +239 -0
- package/src/components/DataTable/hooks/useDataTableRenderGuard.test.tsx +316 -0
- package/src/components/DataTable/hooks/useDataTableRenderGuard.tsx +195 -0
- package/src/components/DataTable/hooks/useDataTableScope.test.ts +110 -0
- package/src/components/DataTable/hooks/useDataTableScope.ts +123 -0
- package/src/components/DataTable/hooks/{__tests__/useDataTableState.test.ts → useDataTableState.test.ts} +47 -5
- package/src/components/DataTable/hooks/useDataTableState.ts +145 -94
- package/src/components/DataTable/hooks/useDataTableStateAndPersistence.test.ts +277 -0
- package/src/components/DataTable/hooks/useDataTableStateAndPersistence.ts +222 -0
- package/src/components/DataTable/hooks/useDataTableSuperAdmin.test.ts +93 -0
- package/src/components/DataTable/hooks/useDataTableSuperAdmin.ts +86 -0
- package/src/components/DataTable/hooks/useDataTableTableInstance.test.ts +185 -0
- package/src/components/DataTable/hooks/useDataTableTableInstance.ts +178 -0
- package/src/components/DataTable/hooks/{__tests__/useEffectiveColumnOrder.test.ts → useEffectiveColumnOrder.test.ts} +2 -2
- package/src/components/DataTable/hooks/{__tests__/useHierarchicalState.test.ts → useHierarchicalState.test.ts} +2 -2
- package/src/components/DataTable/{components/hooks → hooks}/useImportModalFocus.test.ts +3 -3
- package/src/components/DataTable/{components/hooks → hooks}/useImportModalFocus.ts +2 -2
- package/src/components/DataTable/hooks/useImportModalState.test.ts +390 -0
- package/src/components/DataTable/hooks/useImportModalState.ts +345 -0
- package/src/components/DataTable/hooks/{__tests__/useKeyboardNavigation.test.ts → useKeyboardNavigation.test.ts} +3 -3
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +309 -269
- package/src/components/DataTable/{components/hooks → hooks}/usePermissionTracking.test.ts +3 -3
- package/src/components/DataTable/{components/hooks → hooks}/usePermissionTracking.ts +3 -3
- package/src/components/DataTable/hooks/{__tests__/useServerSideDataEffect.test.ts → useServerSideDataEffect.test.ts} +2 -2
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +14 -3
- package/src/components/DataTable/hooks/{__tests__/useTableColumns.test.ts → useTableColumns.test.ts} +2 -2
- package/src/components/DataTable/hooks/{__tests__/useTableHandlers.test.ts → useTableHandlers.test.ts} +25 -4
- package/src/components/DataTable/hooks/useTableHandlers.ts +5 -2
- package/src/components/DataTable/index.ts +18 -17
- package/src/components/DataTable/{__tests__/keyboard.test.tsx → keyboard.test.tsx} +41 -63
- package/src/components/DataTable/{__tests__/mocks → mocks}/MockRBACProvider.tsx +1 -1
- package/src/components/DataTable/{__tests__/pagination.modes.test.tsx → pagination.modes.test.tsx} +6 -6
- package/src/components/DataTable/{__tests__/ssr.strict-mode.test.tsx → ssr.strict-mode.test.tsx} +2 -2
- package/src/components/DataTable/{__tests__/styles.test.ts → styles.test.ts} +1 -4
- package/src/components/DataTable/styles.ts +0 -1
- package/src/components/DataTable/test-utils/MockDataTableComponents.tsx +55 -0
- package/src/components/DataTable/{__tests__/test-utils → test-utils}/dataFactories.ts +2 -2
- package/src/components/DataTable/test-utils/featureConfig.ts +10 -0
- package/src/components/DataTable/{__tests__/test-utils/sharedTestUtils.tsx → test-utils/sharedTestUtils.ts} +97 -66
- package/src/components/DataTable/{__tests__/test-utils.ts → test-utils.ts} +1 -1
- package/src/components/DataTable/types/actions.ts +71 -0
- package/src/components/DataTable/types/base.ts +39 -0
- package/src/components/DataTable/types/columns.ts +125 -0
- package/src/components/DataTable/types/export.ts +32 -0
- package/src/components/DataTable/types/features.ts +81 -0
- package/src/components/DataTable/types/hierarchical.ts +44 -0
- package/src/components/DataTable/types/index.ts +43 -0
- package/src/components/DataTable/types/pagination.ts +85 -0
- package/src/components/DataTable/types/performance.ts +47 -0
- package/src/components/DataTable/types/props.ts +62 -0
- package/src/components/DataTable/types/rbac.ts +45 -0
- package/src/components/DataTable/{components/__tests__ → ui/layout}/DataTableCore.test.tsx +430 -28
- package/src/components/DataTable/ui/layout/DataTableCore.tsx +345 -0
- package/src/components/DataTable/{components/__tests__ → ui/layout}/DataTableErrorBoundary.test.tsx +4 -4
- package/src/components/DataTable/{components → ui/layout}/DataTableErrorBoundary.tsx +7 -7
- package/src/components/DataTable/ui/layout/DataTableLayout.test.tsx +1352 -0
- package/src/components/DataTable/ui/layout/DataTableLayout.tsx +661 -0
- package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.test.tsx +91 -0
- package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.tsx +43 -0
- package/src/components/DataTable/ui/modals/DataTableModals.test.tsx +749 -0
- package/src/components/DataTable/{components → ui/modals}/DataTableModals.tsx +36 -28
- package/src/components/DataTable/ui/modals/ImportModal.test.tsx +1834 -0
- package/src/components/DataTable/ui/modals/ImportModal.tsx +197 -0
- package/src/components/DataTable/ui/modals/ImportModalFailedRowsSection.tsx +60 -0
- package/src/components/DataTable/ui/modals/ImportModalFileSection.tsx +148 -0
- package/src/components/DataTable/ui/modals/ImportModalPreviewSection.tsx +60 -0
- package/src/components/DataTable/ui/modals/ImportModalSummarySection.tsx +59 -0
- package/src/components/DataTable/ui/modals/importModalPersistence.ts +73 -0
- package/src/components/DataTable/{components/__tests__ → ui/shared}/AccessDeniedPage.test.tsx +2 -2
- package/src/components/DataTable/{components → ui/shared}/AccessDeniedPage.tsx +2 -2
- package/src/components/DataTable/{components/__tests__ → ui/shared}/ActionButtons.test.tsx +6 -4
- package/src/components/DataTable/{components → ui/shared}/ActionButtons.tsx +4 -4
- package/src/components/DataTable/{components/__tests__ → ui/shared}/ColumnFilter.test.tsx +29 -16
- package/src/components/DataTable/{components → ui/shared}/ColumnFilter.tsx +4 -4
- package/src/components/DataTable/{components/__tests__ → ui/shared}/PaginationControls.test.tsx +38 -16
- package/src/components/DataTable/{components → ui/shared}/PaginationControls.tsx +21 -15
- package/src/components/DataTable/{components/__tests__ → ui/shared}/SortIndicator.test.tsx +2 -2
- package/src/components/DataTable/{components → ui/shared}/SortIndicator.tsx +1 -1
- package/src/components/DataTable/{components/__tests__ → ui/table}/EditFields.test.tsx +3 -3
- package/src/components/DataTable/{components → ui/table}/EditFields.tsx +138 -69
- package/src/components/DataTable/{components/__tests__ → ui/table}/EditableRow.test.tsx +36 -27
- package/src/components/DataTable/{components → ui/table}/EditableRow.tsx +86 -104
- package/src/components/DataTable/{components/__tests__ → ui/table}/EmptyState.test.tsx +2 -62
- package/src/components/DataTable/{components → ui/table}/EmptyState.tsx +7 -15
- package/src/components/DataTable/{components/__tests__ → ui/table}/FilterRow.test.tsx +5 -4
- package/src/components/DataTable/{components → ui/table}/FilterRow.tsx +3 -3
- package/src/components/DataTable/{components/__tests__ → ui/table}/LoadingState.test.tsx +6 -10
- package/src/components/DataTable/{components → ui/table}/LoadingState.tsx +4 -4
- package/src/components/DataTable/{components/__tests__ → ui/table}/RowComponent.test.tsx +412 -17
- package/src/components/DataTable/{components → ui/table}/RowComponent.tsx +183 -177
- package/src/components/DataTable/{components/__tests__ → ui/table}/UnifiedTableBody.test.tsx +425 -16
- package/src/components/DataTable/ui/table/UnifiedTableBody.tsx +440 -0
- package/src/components/DataTable/{components/__tests__ → ui/table}/cellValueUtils.test.ts +2 -2
- package/src/components/DataTable/{components → ui/table}/cellValueUtils.ts +1 -1
- package/src/components/DataTable/{components/__tests__ → ui/toolbar}/BulkOperationsDropdown.test.tsx +12 -5
- package/src/components/DataTable/{components → ui/toolbar}/BulkOperationsDropdown.tsx +3 -3
- package/src/components/DataTable/{components/__tests__ → ui/toolbar}/ColumnVisibilityDropdown.test.tsx +7 -4
- package/src/components/DataTable/{components → ui/toolbar}/ColumnVisibilityDropdown.tsx +7 -7
- package/src/components/DataTable/{components/__tests__ → ui/toolbar}/DataTableToolbar.test.tsx +4 -4
- package/src/components/DataTable/{components → ui/toolbar}/DataTableToolbar.tsx +4 -4
- package/src/components/DataTable/ui/toolbar/GroupingDropdown.test.tsx +621 -0
- package/src/components/DataTable/ui/toolbar/GroupingDropdown.tsx +107 -0
- package/src/components/DataTable/utils/{__tests__/a11yUtils.test.ts → a11yUtils.test.ts} +2 -2
- package/src/components/DataTable/utils/{__tests__/aggregationUtils.test.ts → aggregationUtils.test.ts} +3 -3
- package/src/components/DataTable/utils/{__tests__/columnUtils.test.ts → columnUtils.test.ts} +2 -2
- package/src/components/DataTable/utils/csvParse.test.ts +74 -0
- package/src/components/DataTable/utils/csvParse.ts +65 -0
- package/src/components/DataTable/utils/{__tests__/errorHandling.test.ts → errorHandling.test.ts} +2 -2
- package/src/components/DataTable/utils/{__tests__/exportUtils.test.ts → exportUtils.test.ts} +3 -3
- package/src/components/DataTable/utils/{__tests__/flexibleImport.test.ts → flexibleImport.test.ts} +2 -2
- package/src/components/DataTable/utils/flexibleImport.ts +3 -186
- package/src/components/DataTable/utils/{__tests__/hierarchicalSorting.test.ts → hierarchicalSorting.test.ts} +3 -3
- package/src/components/DataTable/utils/{__tests__/hierarchicalUtils.test.ts → hierarchicalUtils.test.ts} +3 -3
- package/src/components/DataTable/utils/importDateParser.test.ts +162 -0
- package/src/components/DataTable/utils/importDateParser.ts +114 -0
- package/src/components/DataTable/utils/importValueParser.test.ts +138 -0
- package/src/components/DataTable/utils/importValueParser.ts +91 -0
- package/src/components/DataTable/utils/{__tests__/paginationUtils.test.ts → paginationUtils.test.ts} +2 -2
- package/src/components/DataTable/utils/paginationUtils.ts +6 -3
- package/src/components/DataTable/utils/{__tests__/performanceUtils.test.ts → performanceUtils.test.ts} +3 -3
- package/src/components/DataTable/utils/{__tests__/rowUtils.test.ts → rowUtils.test.ts} +3 -3
- package/src/components/DataTable/utils/{__tests__/selectFieldUtils.test.ts → selectFieldUtils.test.ts} +66 -3
- package/src/components/DataTable/utils/selectFieldUtils.ts +97 -60
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
- package/src/components/DateTimeField/DateTimeField.test.tsx +1 -1
- package/src/components/Dialog/Dialog.test-utils.ts +49 -0
- package/src/components/Dialog/Dialog.test.tsx +896 -89
- package/src/components/Dialog/Dialog.tsx +174 -882
- package/src/components/Dialog/dialogLock.test.ts +238 -0
- package/src/components/Dialog/dialogLock.ts +98 -0
- package/src/components/Dialog/index.ts +2 -0
- package/src/components/Dialog/useDialogDimensions.test.ts +163 -0
- package/src/components/Dialog/useDialogDimensions.ts +140 -0
- package/src/components/Dialog/useDialogLifecycle.test.ts +358 -0
- package/src/components/Dialog/useDialogLifecycle.ts +135 -0
- package/src/components/Dialog/useDialogPersistence.test.ts +381 -0
- package/src/components/Dialog/useDialogPersistence.ts +357 -0
- package/src/components/FileDisplay/FileDisplay.test.tsx +40 -40
- package/src/components/FileDisplay/FileDisplay.tsx +24 -656
- package/src/components/FileDisplay/FileDisplayContent.test.tsx +395 -0
- package/src/components/FileDisplay/FileDisplayContent.tsx +242 -0
- package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.test.tsx +74 -0
- package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.tsx +38 -0
- package/src/components/FileDisplay/FileDisplayEmptyView.test.tsx +33 -0
- package/src/components/FileDisplay/FileDisplayEmptyView.tsx +33 -0
- package/src/components/FileDisplay/FileDisplayErrorView.test.tsx +71 -0
- package/src/components/FileDisplay/FileDisplayErrorView.tsx +50 -0
- package/src/components/FileDisplay/FileDisplayLoadingFallbackView.test.tsx +22 -0
- package/src/components/FileDisplay/FileDisplayLoadingFallbackView.tsx +22 -0
- package/src/components/FileDisplay/FileDisplayLoadingView.test.tsx +21 -0
- package/src/components/FileDisplay/FileDisplayLoadingView.tsx +23 -0
- package/src/components/FileDisplay/FileDisplayMultipleFilesView.test.tsx +101 -0
- package/src/components/FileDisplay/FileDisplayMultipleFilesView.tsx +109 -0
- package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.test.tsx +58 -0
- package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.tsx +48 -0
- package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.test.tsx +111 -0
- package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.tsx +270 -0
- package/src/components/FileDisplay/FileDisplaySingleImageView.test.tsx +78 -0
- package/src/components/FileDisplay/FileDisplaySingleImageView.tsx +67 -0
- package/src/components/FileDisplay/fallbackUtils.test.ts +50 -0
- package/src/components/FileDisplay/fallbackUtils.ts +44 -0
- package/src/components/FileDisplay/fetchFileDisplayData.ts +24 -0
- package/src/components/FileDisplay/fetchFileDisplayData.unit.test.ts +183 -0
- package/src/components/FileDisplay/fileDisplayUtils.test.ts +58 -0
- package/src/components/FileDisplay/fileDisplayUtils.ts +24 -0
- package/src/{hooks/__tests__ → components/FileDisplay}/useFileDisplay.test.ts +40 -42
- package/src/components/FileDisplay/useFileDisplay.ts +515 -0
- package/src/{hooks/__tests__ → components/FileDisplay}/useFileDisplay.unit.test.ts +406 -77
- package/src/components/FileDisplay/useFileDisplayData.ts +126 -0
- package/src/{hooks/public → components/FileDisplay}/usePublicFileDisplay.test.ts +94 -88
- package/src/components/FileDisplay/usePublicFileDisplay.ts +579 -0
- package/src/components/FileUpload/FileUpload.test.tsx +16 -10
- package/src/components/FileUpload/FileUpload.tsx +107 -525
- package/src/components/FileUpload/FileUploadDropZone.tsx +112 -0
- package/src/components/FileUpload/FileUploadProgressItem.tsx +86 -0
- package/src/components/FileUpload/FileUploadProgressList.tsx +40 -0
- package/src/components/FileUpload/useFileUploadManager.test.ts +308 -0
- package/src/components/FileUpload/useFileUploadManager.ts +454 -0
- package/src/components/FileUpload/useResolvedAppId.test.ts +102 -0
- package/src/components/FileUpload/useResolvedAppId.ts +77 -0
- package/src/components/Footer/Footer.test.tsx +6 -292
- package/src/components/Footer/Footer.tsx +8 -125
- package/src/components/Form/Form.test.tsx +44 -27
- package/src/components/Form/Form.tsx +64 -287
- package/src/components/Form/useFormPersistence.ts +257 -0
- package/src/components/Header/Header.test.tsx +17 -18
- package/src/components/Header/Header.tsx +10 -1
- package/src/components/Input/Input.tsx +1 -1
- package/src/components/Label/Label.test.tsx +1 -1
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +1 -1
- package/src/components/NavigationMenu/HierarchicalNavItem.tsx +104 -0
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +1029 -26
- package/src/components/NavigationMenu/NavigationMenu.tsx +61 -361
- package/src/components/NavigationMenu/index.ts +6 -1
- package/src/components/NavigationMenu/navigationPermissionHelper.ts +188 -0
- package/src/components/NavigationMenu/{__tests__/useNavigationFiltering.test.ts → useNavigationFiltering.test.ts} +68 -53
- package/src/components/NavigationMenu/useNavigationFiltering.ts +197 -296
- package/src/components/NavigationMenu/useNavigationScope.ts +125 -0
- package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +77 -62
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +3 -3
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +16 -19
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +529 -5
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +280 -756
- package/src/components/PaceAppLayout/useFilteredNavItems.ts +304 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutConfig.ts +142 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutGate.tsx +150 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutPermissions.ts +162 -0
- package/src/components/PaceAppLayout/usePaceAppLayoutScope.ts +79 -0
- package/src/components/PaceAppLayout/useRoleBasedRouteAccess.ts +157 -0
- package/src/components/PaceAppLayout/useSuperAdminFallback.ts +58 -0
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +31 -25
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +31 -122
- package/src/components/PaceLoginPage/useLoginAppAccess.ts +153 -0
- package/src/components/Progress/Progress.tsx +1 -2
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +29 -235
- package/src/components/ProtectedRoute/useProtectedRouteState.ts +128 -0
- package/src/components/ProtectedRoute/useVisibilityRedirectGrace.ts +89 -0
- package/src/components/PublicLayout/PublicLayout.test.tsx +217 -36
- package/src/components/PublicLayout/PublicPageLayout.tsx +132 -73
- package/src/components/PublicLayout/PublicPageProvider.tsx +5 -1
- package/src/components/Select/Select.test.tsx +1 -1
- package/src/components/Select/Select.tsx +28 -18
- package/src/components/Select/{__tests__/context.test.tsx → context.test.tsx} +3 -3
- package/src/components/Select/{utils/__tests__/text.test.tsx → text.test.tsx} +2 -2
- package/src/components/Select/{utils/text.ts → text.ts} +1 -1
- package/src/components/Select/{hooks/__tests__/useSelectEvents.test.ts → useSelectEvents.test.ts} +5 -5
- package/src/components/Select/{hooks/useSelectEvents.ts → useSelectEvents.ts} +2 -2
- package/src/components/Select/{hooks/__tests__/useSelectSearch.test.tsx → useSelectSearch.test.tsx} +7 -7
- package/src/components/Select/{hooks/useSelectSearch.ts → useSelectSearch.ts} +2 -2
- package/src/components/Select/{hooks/__tests__/useSelectState.test.ts → useSelectState.test.ts} +16 -2
- package/src/components/Select/{hooks/useSelectState.ts → useSelectState.ts} +3 -3
- package/src/components/Table/Table.test.tsx +348 -0
- package/src/components/Tabs/Tabs.test.tsx +270 -0
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Toast/Toast.test.tsx +420 -0
- package/src/components/{__tests__/index.test.ts → index.test.ts} +2 -2
- package/src/constants/{__tests__/performance.test.ts → performance.test.ts} +2 -2
- package/src/hooks/{__tests__/ServiceHooks.test.tsx → ServiceHooks.test.tsx} +8 -8
- package/src/hooks/{__tests__/hooks.integration.test.tsx → hooks.integration.test.tsx} +11 -11
- package/src/hooks/index.ts +7 -4
- package/src/hooks/{__tests__/index.unit.test.ts → index.unit.test.ts} +2 -2
- package/src/hooks/public/usePublicEvent.test.ts +1 -1
- package/src/hooks/public/usePublicEventLogo.test.ts +1 -1
- package/src/hooks/public/usePublicRouteParams.test.ts +1 -1
- package/src/hooks/services/useAuth.ts +9 -7
- package/src/hooks/useAddressAutocomplete.test.ts +22 -22
- package/src/hooks/useAddressAutocomplete.ts +90 -75
- package/src/hooks/{__tests__/useAppConfig.unit.test.ts → useAppConfig.unit.test.ts} +328 -22
- package/src/hooks/{__tests__/useComponentPerformance.unit.test.tsx → useComponentPerformance.unit.test.tsx} +27 -41
- package/src/hooks/useDataTablePerformance.ts +100 -120
- package/src/hooks/{__tests__/useDataTablePerformance.unit.test.ts → useDataTablePerformance.unit.test.ts} +5 -5
- package/src/hooks/{__tests__/useDataTableState.test.ts → useDataTableState.test.ts} +2 -2
- package/src/hooks/{__tests__/useDebounce.unit.test.ts → useDebounce.unit.test.ts} +2 -2
- package/src/hooks/useEventTheme.test.ts +4 -1
- package/src/hooks/useEventTheme.ts +49 -21
- package/src/hooks/useEvents.ts +41 -1
- package/src/hooks/{__tests__/useEvents.unit.test.ts → useEvents.unit.test.ts} +5 -5
- package/src/hooks/useFileReference.test.ts +44 -41
- package/src/hooks/useFileReference.ts +182 -173
- package/src/hooks/useFileUrl.ts +1 -1
- package/src/hooks/{__tests__/useFileUrl.unit.test.ts → useFileUrl.unit.test.ts} +26 -36
- package/src/hooks/{__tests__/useFileUrlCache.test.ts → useFileUrlCache.test.ts} +8 -8
- package/src/hooks/useFileUrlCache.ts +1 -1
- package/src/hooks/{__tests__/useFocusManagement.unit.test.ts → useFocusManagement.unit.test.ts} +2 -2
- package/src/hooks/{__tests__/useFocusTrap.unit.test.tsx → useFocusTrap.unit.test.tsx} +2 -2
- package/src/hooks/{__tests__/useFormDialog.test.ts → useFormDialog.test.ts} +2 -2
- package/src/hooks/useInactivityTracker.ts +138 -131
- package/src/hooks/{__tests__/useInactivityTracker.unit.test.ts → useInactivityTracker.unit.test.ts} +3 -3
- package/src/hooks/{__tests__/useIsMobile.unit.test.ts → useIsMobile.unit.test.ts} +2 -2
- package/src/hooks/useIsPrint.ts +62 -0
- package/src/hooks/useIsPrint.unit.test.ts +545 -0
- package/src/hooks/{__tests__/useKeyboardShortcuts.unit.test.ts → useKeyboardShortcuts.unit.test.ts} +2 -2
- package/src/hooks/{__tests__/useOrganisationPermissions.unit.test.tsx → useOrganisationPermissions.unit.test.tsx} +4 -4
- package/src/hooks/useOrganisationSecurity.test.ts +3 -3
- package/src/hooks/useOrganisationSecurity.ts +190 -201
- package/src/hooks/{__tests__/useOrganisationSecurity.unit.test.tsx → useOrganisationSecurity.unit.test.tsx} +61 -63
- package/src/hooks/{__tests__/useOrganisations.unit.test.ts → useOrganisations.unit.test.ts} +5 -5
- package/src/hooks/{__tests__/usePerformanceMonitor.unit.test.ts → usePerformanceMonitor.unit.test.ts} +13 -14
- package/src/hooks/{__tests__/usePermissionCache.test.ts → usePermissionCache.test.ts} +26 -27
- package/src/hooks/usePermissionCache.ts +276 -271
- package/src/hooks/{__tests__/usePreventTabReload.test.ts → usePreventTabReload.test.ts} +2 -2
- package/src/hooks/{__tests__/usePublicEvent.simple.test.ts → usePublicEvent.simple.test.ts} +4 -4
- package/src/hooks/{__tests__/usePublicEvent.test.ts → usePublicEvent.test.ts} +4 -4
- package/src/hooks/{__tests__/usePublicEvent.unit.test.ts → usePublicEvent.unit.test.ts} +4 -4
- package/src/hooks/{__tests__/usePublicFileDisplay.test.ts → usePublicFileDisplay.test.ts} +12 -12
- package/src/hooks/{__tests__/usePublicRouteParams.unit.test.ts → usePublicRouteParams.unit.test.ts} +3 -3
- package/src/hooks/{__tests__/useQueryCache.test.ts → useQueryCache.test.ts} +2 -2
- package/src/hooks/useQueryCache.ts +0 -2
- package/src/hooks/{__tests__/useRBAC.unit.test.ts → useRBAC.unit.test.ts} +55 -38
- package/src/hooks/{__tests__/useSessionDraft.test.ts → useSessionDraft.test.ts} +2 -2
- package/src/hooks/{__tests__/useSessionRestoration.unit.test.tsx → useSessionRestoration.unit.test.tsx} +10 -19
- package/src/hooks/useStorage.ts +21 -16
- package/src/hooks/{__tests__/useStorage.unit.test.ts → useStorage.unit.test.ts} +38 -75
- package/src/hooks/{__tests__/useToast.test.ts → useToast.test.ts} +2 -2
- package/src/hooks/{__tests__/useToast.unit.test.tsx → useToast.unit.test.tsx} +2 -2
- package/src/hooks/{__tests__/useZodForm.unit.test.tsx → useZodForm.unit.test.tsx} +2 -2
- package/src/icons/{__tests__/index.test.ts → index.test.ts} +2 -2
- package/src/icons/index.ts +2 -0
- package/src/{__tests__/index.test.ts → index.test.ts} +3 -7
- package/src/index.ts +15 -7
- package/src/providers/{__tests__/AuthProvider.test.tsx → AuthProvider.test.tsx} +3 -3
- package/src/providers/{__tests__/EventProvider.test.tsx → EventProvider.test.tsx} +3 -3
- package/src/providers/InactivityProvider.test-helper.tsx +40 -0
- package/src/providers/{__tests__/InactivityProvider.test.tsx → InactivityProvider.test.tsx} +14 -21
- package/src/providers/{__tests__/ProviderLifecycle.test.tsx → ProviderLifecycle.test.tsx} +4 -4
- package/src/providers/{__tests__/UnifiedAuthProvider.test.tsx → UnifiedAuthProvider.test.tsx} +1 -1
- package/src/providers/{__tests__/index.test.ts → index.test.ts} +2 -2
- package/src/providers/services/{__tests__/AuthServiceProvider.integration.test.tsx → AuthServiceProvider.integration.test.tsx} +4 -4
- package/src/providers/services/{__tests__/AuthServiceProvider.test.tsx → AuthServiceProvider.test.tsx} +7 -7
- package/src/providers/services/{__tests__/EventServiceProvider.test.tsx → EventServiceProvider.test.tsx} +7 -7
- package/src/providers/services/{__tests__/InactivityServiceProvider.test.tsx → InactivityServiceProvider.test.tsx} +5 -5
- package/src/providers/services/{__tests__/OrganisationServiceProvider.test.tsx → OrganisationServiceProvider.test.tsx} +6 -6
- package/src/providers/services/UnifiedAuthContext.ts +30 -27
- package/src/providers/services/{__tests__/UnifiedAuthProvider.advanced.test.tsx → UnifiedAuthProvider.advanced.test.tsx} +8 -9
- package/src/providers/services/{__tests__/UnifiedAuthProvider.appId.test.tsx → UnifiedAuthProvider.appId.test.tsx} +25 -25
- package/src/providers/services/{__tests__/UnifiedAuthProvider.integration.test.tsx → UnifiedAuthProvider.integration.test.tsx} +14 -11
- package/src/providers/services/UnifiedAuthProvider.tsx +115 -360
- package/src/providers/services/{__tests__/contexts.test.tsx → contexts.test.tsx} +6 -6
- package/src/providers/services/{__tests__/useUnifiedAuth.test.tsx → useUnifiedAuth.test.tsx} +6 -6
- package/src/providers/services/useUnifiedAuthContextValue.ts +279 -0
- package/src/providers/useInactivity.test-helper.ts +27 -0
- package/src/rbac/{__tests__/adapters.comprehensive.test.tsx → adapters.comprehensive.test.tsx} +24 -24
- package/src/rbac/adapters.test.tsx +22 -22
- package/src/rbac/adapters.tsx +29 -29
- package/src/rbac/api.test.ts +973 -42
- package/src/rbac/api.ts +228 -253
- package/src/rbac/{__tests__/audit-batched.test.ts → audit-batched.test.ts} +6 -6
- package/src/rbac/audit.ts +4 -1
- package/src/rbac/{__tests__/auth-rbac-security.integration.test.tsx → auth-rbac-security.integration.test.tsx} +1 -1
- package/src/rbac/{__tests__/auth-rbac.e2e.test.tsx → auth-rbac.e2e.test.tsx} +27 -34
- package/src/rbac/cache-invalidation.test.ts +715 -0
- package/src/rbac/components/{__tests__/AccessDenied.test.tsx → AccessDenied.test.tsx} +3 -3
- package/src/rbac/components/{__tests__/NavigationGuard.test.tsx → NavigationGuard.test.tsx} +13 -11
- package/src/{__tests__/rbac/PagePermissionGuard.test.tsx → rbac/components/PagePermissionGuard.guard.test.tsx} +33 -19
- package/src/rbac/components/{__tests__/PagePermissionGuard.performance.test.tsx → PagePermissionGuard.performance.test.tsx} +30 -9
- package/src/rbac/components/{__tests__/PagePermissionGuard.race-condition.test.tsx → PagePermissionGuard.race-condition.test.tsx} +7 -7
- package/src/rbac/components/{__tests__/PagePermissionGuard.test.tsx → PagePermissionGuard.test.tsx} +10 -10
- package/src/rbac/components/PagePermissionGuard.tsx +177 -372
- package/src/rbac/components/{__tests__/PagePermissionGuard.verification.test.tsx → PagePermissionGuard.verification.test.tsx} +7 -7
- package/src/rbac/config.ts +58 -18
- package/src/rbac/{__tests__/engine.comprehensive.test.ts → engine.comprehensive.test.ts} +3 -3
- package/src/rbac/engine.test.ts +494 -0
- package/src/rbac/errors.ts +89 -55
- package/src/rbac/hooks/permissions/runPermissionCheck.ts +77 -0
- package/src/rbac/hooks/permissions/{__tests__/useAccessLevel.test.ts → useAccessLevel.test.ts} +40 -40
- package/src/rbac/hooks/permissions/useAccessLevel.ts +16 -6
- package/src/rbac/hooks/permissions/{__tests__/useCan.test.ts → useCan.test.ts} +41 -41
- package/src/rbac/hooks/permissions/useCan.ts +170 -252
- package/src/rbac/hooks/permissions/{__tests__/useMultiplePermissions.test.ts → useMultiplePermissions.test.ts} +49 -49
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +6 -2
- package/src/rbac/hooks/permissions/{__tests__/usePermissions.test.ts → usePermissions.test.ts} +10 -12
- package/src/rbac/hooks/permissions/usePermissions.ts +36 -65
- package/src/rbac/hooks/useCan.test.ts +42 -42
- package/src/rbac/hooks/usePageAccessLogging.ts +160 -0
- package/src/rbac/hooks/usePageGuardScope.ts +117 -0
- package/src/rbac/hooks/usePagePermissionCheck.ts +67 -0
- package/src/rbac/hooks/{__tests__/usePermissions.integration.test.ts → usePermissions.integration.test.ts} +9 -9
- package/src/{__tests__/hooks/usePermissions.test.ts → rbac/hooks/usePermissions.stability.test.ts} +18 -18
- package/src/rbac/hooks/usePermissions.test.ts +54 -54
- package/src/rbac/hooks/useRBAC.test.ts +313 -217
- package/src/rbac/hooks/useRBAC.ts +145 -81
- package/src/rbac/hooks/useResourcePermissions.test.ts +25 -25
- package/src/rbac/hooks/useResourcePermissions.ts +68 -134
- package/src/rbac/hooks/useResourcePermissionsSuperAdmin.ts +67 -0
- package/src/rbac/hooks/useRoleManagement.test.ts +27 -112
- package/src/rbac/hooks/useRoleManagement.ts +153 -585
- package/src/rbac/hooks/{__tests__/useSecureSupabase.test.ts → useSecureSupabase.test.ts} +17 -17
- package/src/rbac/hooks/useSecureSupabase.ts +10 -2
- package/src/rbac/hooks/useSuperAdminCheck.ts +80 -0
- package/src/rbac/{__tests__/performance.test.ts → performance.test.ts} +1 -1
- package/src/rbac/{__tests__/rbac-core.test.tsx → rbac-core.test.tsx} +3 -3
- package/src/rbac/{__tests__/rbac-engine-core-logic.test.ts → rbac-engine-core-logic.test.ts} +2 -2
- package/src/rbac/{__tests__/rbac-engine-simplified.test.ts → rbac-engine-simplified.test.ts} +3 -3
- package/src/rbac/{__tests__/rbac-functions.test.ts → rbac-functions.test.ts} +57 -0
- package/src/rbac/{__tests__/rbac-role-isolation.test.ts → rbac-role-isolation.test.ts} +2 -2
- package/src/rbac/request-deduplication.test.ts +14 -9
- package/src/rbac/request-deduplication.ts +5 -4
- package/src/rbac/{__tests__/scenarios.user-role.test.tsx → scenarios.user-role.test.tsx} +23 -23
- package/src/rbac/secureClient.test.ts +514 -83
- package/src/rbac/secureClient.ts +8 -2
- package/src/rbac/security.test.ts +323 -0
- package/src/rbac/types/roleManagement.ts +66 -0
- package/src/rbac/utils/{__tests__/clientSecurity.test.ts → clientSecurity.test.ts} +4 -4
- package/src/rbac/utils/{__tests__/contextValidator.test.ts → contextValidator.test.ts} +4 -4
- package/src/rbac/utils/contextValidator.ts +5 -1
- package/src/rbac/utils/{__tests__/deep-equal.test.ts → deep-equal.test.ts} +1 -1
- package/src/rbac/utils/{__tests__/eventContext.test.ts → eventContext.test.ts} +36 -21
- package/src/rbac/utils/eventContext.ts +37 -33
- package/src/rbac/utils/fetchPermissionMap.ts +13 -0
- package/src/rbac/utils/permissionMapHelpers.ts +34 -0
- package/src/rbac/utils/roleManagementRpc.ts +303 -0
- package/src/services/{__tests__/AuthService.edge-cases.test.ts → AuthService.edge-cases.test.ts} +19 -19
- package/src/services/{__tests__/AuthService.restoreSession.test.ts → AuthService.restoreSession.test.ts} +2 -2
- package/src/services/{__tests__/AuthService.test.ts → AuthService.test.ts} +89 -55
- package/src/services/AuthService.ts +184 -205
- package/src/services/{__tests__/BaseService.edge-cases.test.ts → BaseService.edge-cases.test.ts} +3 -3
- package/src/services/{__tests__/BaseService.test.ts → BaseService.test.ts} +2 -2
- package/src/services/{__tests__/EventService.edge-cases.test.ts → EventService.edge-cases.test.ts} +27 -24
- package/src/services/{__tests__/EventService.eventColours.test.ts → EventService.eventColours.test.ts} +1 -1
- package/src/services/{__tests__/EventService.test.ts → EventService.test.ts} +256 -24
- package/src/services/EventService.ts +242 -312
- package/src/services/{__tests__/InactivityService.edge-cases.test.ts → InactivityService.edge-cases.test.ts} +3 -3
- package/src/services/{__tests__/InactivityService.lifecycle.test.ts → InactivityService.lifecycle.test.ts} +2 -2
- package/src/services/{__tests__/InactivityService.test.ts → InactivityService.test.ts} +179 -4
- package/src/services/InactivityService.ts +172 -213
- package/src/services/{__tests__/OrganisationService.edge-cases.test.ts → OrganisationService.edge-cases.test.ts} +5 -5
- package/src/services/{__tests__/OrganisationService.pagination.test.ts → OrganisationService.pagination.test.ts} +4 -4
- package/src/services/{__tests__/OrganisationService.test.ts → OrganisationService.test.ts} +410 -7
- package/src/services/OrganisationService.ts +184 -238
- package/src/services/base/BaseService.test.ts +1 -1
- package/src/services/interfaces/{__tests__/IAuthService.test.ts → IAuthService.test.ts} +21 -27
- package/src/services/interfaces/IAuthService.ts +10 -9
- package/src/services/interfaces/{__tests__/IEventService.test.ts → IEventService.test.ts} +4 -4
- package/src/services/interfaces/{__tests__/IInactivityService.test.ts → IInactivityService.test.ts} +3 -3
- package/src/services/interfaces/{__tests__/IOrganisationService.test.ts → IOrganisationService.test.ts} +3 -3
- package/src/styles/core.css +243 -12
- package/src/theming/{__tests__/parseEventColours.test.ts → parseEventColours.test.ts} +1 -1
- package/src/theming/{__tests__/runtime.test.ts → runtime.test.ts} +8 -17
- package/src/theming/runtime.ts +71 -2
- package/src/types/api-result.ts +53 -0
- package/src/types/{__tests__/core.test.ts → core.test.ts} +2 -2
- package/src/types/{__tests__/database-generated.test.ts → database-generated.test.ts} +3 -3
- package/src/types/database.generated.ts +45 -10
- package/src/types/event.ts +38 -18
- package/src/types/{__tests__/file-reference.test.ts → file-reference.test.ts} +13 -13
- package/src/types/file-reference.ts +37 -12
- package/src/types/{__tests__/guards.test.ts → guards.test.ts} +2 -2
- package/src/types/{__tests__/index.test.ts → index.test.ts} +2 -2
- package/src/types/index.ts +3 -0
- package/src/types/{__tests__/organisation.roles.test.ts → organisation.roles.test.ts} +1 -1
- package/src/types/{__tests__/organisation.test.ts → organisation.test.ts} +3 -31
- package/src/types/organisation.ts +15 -15
- package/src/types/supabase.ts +13 -4
- package/src/types/{__tests__/theme.test.ts → theme.test.ts} +1 -1
- package/src/types/{__tests__/type-validation.test.ts → type-validation.test.ts} +1 -1
- package/src/types/{__tests__/validation.test.ts → validation.test.ts} +2 -2
- package/src/utils/app/appIdResolver.test.ts +98 -71
- package/src/utils/app/appIdResolver.ts +31 -20
- package/src/utils/{__tests__/appConfig.unit.test.ts → appConfig.unit.test.ts} +1 -1
- package/src/utils/{__tests__/audit.unit.test.ts → audit.unit.test.ts} +1 -1
- package/src/utils/{__tests__/auth-utils.unit.test.ts → auth-utils.unit.test.ts} +16 -17
- package/src/utils/{__tests__/bundleAnalysis.unit.test.ts → bundleAnalysis.unit.test.ts} +35 -35
- package/src/utils/{__tests__/cn.unit.test.ts → cn.unit.test.ts} +1 -1
- package/src/utils/context/organisationContext.test.ts +105 -91
- package/src/utils/context/organisationContext.ts +29 -40
- package/src/utils/core/{__tests__/cn.test.ts → cn.test.ts} +3 -3
- package/src/utils/core/{__tests__/debugLogger.test.ts → debugLogger.test.ts} +2 -2
- package/src/utils/core/{__tests__/logger.test.ts → logger.test.ts} +2 -2
- package/src/utils/core/mergeRefs.ts +24 -0
- package/src/utils/{__tests__/debugLogger.test.ts → debugLogger.test.ts} +1 -1
- package/src/utils/{__tests__/deviceFingerprint.unit.test.ts → deviceFingerprint.unit.test.ts} +1 -1
- package/src/utils/dynamic/createLazyComponent.tsx +9 -1
- package/src/utils/dynamic/{__tests__/dynamicUtils.test.ts → dynamicUtils.test.ts} +2 -2
- package/src/utils/dynamic/{__tests__/lazyLoad.test.tsx → lazyLoad.test.tsx} +2 -2
- package/src/utils/{__tests__/dynamicUtils.unit.test.ts → dynamicUtils.unit.test.ts} +1 -1
- package/src/utils/file-reference/{__tests__/file-reference.test.ts → file-reference.test.ts} +214 -289
- package/src/utils/file-reference/index.ts +330 -347
- package/src/utils/{__tests__/formatDate.unit.test.ts → formatDate.unit.test.ts} +2 -2
- package/src/utils/formatting/formatDateTimeTimezone.test.ts +1 -1
- package/src/utils/formatting/formatNumber.test.ts +1 -1
- package/src/utils/{__tests__/formatting.unit.test.ts → formatting.unit.test.ts} +1 -1
- package/src/utils/google-places/googlePlacesUtils.test.ts +70 -48
- package/src/utils/google-places/googlePlacesUtils.ts +67 -99
- package/src/utils/google-places/loadGoogleMapsScript.test.ts +25 -22
- package/src/utils/google-places/loadGoogleMapsScript.ts +138 -117
- package/src/utils/{__tests__/index.unit.test.ts → index.unit.test.ts} +1 -1
- package/src/utils/{__tests__/lazyLoad.unit.test.tsx → lazyLoad.unit.test.tsx} +13 -14
- package/src/utils/location/location.test.ts +1 -1
- package/src/utils/{__tests__/logger.unit.test.ts → logger.unit.test.ts} +1 -1
- package/src/utils/{__tests__/organisationContext.unit.test.ts → organisationContext.unit.test.ts} +37 -48
- package/src/utils/performance/{__tests__/bundleAnalysis.test.ts → bundleAnalysis.test.ts} +2 -2
- package/src/utils/performance/{__tests__/performanceBenchmark.test.ts → performanceBenchmark.test.ts} +2 -2
- package/src/utils/performance/{__tests__/performanceBudgets.test.ts → performanceBudgets.test.ts} +2 -2
- package/src/utils/{__tests__/performanceBenchmark.test.ts → performanceBenchmark.test.ts} +2 -2
- package/src/utils/{__tests__/performanceBudgets.unit.test.ts → performanceBudgets.unit.test.ts} +2 -2
- package/src/utils/{__tests__/permissionTypes.unit.test.ts → permissionTypes.unit.test.ts} +1 -1
- package/src/utils/{__tests__/permissionUtils.unit.test.ts → permissionUtils.unit.test.ts} +1 -1
- package/src/utils/permissions/{__tests__/permissionTypes.test.ts → permissionTypes.test.ts} +2 -2
- package/src/utils/persistence/{__tests__/keyDerivation.test.ts → keyDerivation.test.ts} +2 -2
- package/src/utils/persistence/{__tests__/sensitiveFieldDetection.test.ts → sensitiveFieldDetection.test.ts} +2 -2
- package/src/utils/{__tests__/request-deduplication.test.ts → request-deduplication.test.ts} +2 -2
- package/src/utils/{__tests__/sanitization.unit.test.ts → sanitization.unit.test.ts} +1 -1
- package/src/utils/{__tests__/schemaUtils.unit.test.ts → schemaUtils.unit.test.ts} +1 -1
- package/src/utils/{__tests__/secureDataAccess.unit.test.ts → secureDataAccess.unit.test.ts} +2 -2
- package/src/utils/{__tests__/secureErrors.unit.test.ts → secureErrors.unit.test.ts} +4 -4
- package/src/utils/{__tests__/secureStorage.unit.test.ts → secureStorage.unit.test.ts} +1 -1
- package/src/utils/security/auth-utils.ts +34 -23
- package/src/utils/security/secureDataAccess.ts +241 -281
- package/src/utils/security/secureErrors.test.ts +1 -1
- package/src/utils/security/secureStorage.test.ts +1 -1
- package/src/utils/security/security.test.ts +25 -17
- package/src/utils/security/security.ts +15 -18
- package/src/utils/security/securityMonitor.test.ts +1 -1
- package/src/utils/{__tests__/security.unit.test.ts → security.unit.test.ts} +21 -15
- package/src/utils/{__tests__/securityMonitor.unit.test.ts → securityMonitor.unit.test.ts} +1 -1
- package/src/utils/{__tests__/sessionTracking.unit.test.ts → sessionTracking.unit.test.ts} +12 -12
- package/src/utils/storage/{__tests__/config.unit.test.ts → config.unit.test.ts} +2 -2
- package/src/utils/storage/helpers.test.ts +88 -102
- package/src/utils/storage/helpers.ts +173 -251
- package/src/utils/storage/{__tests__/index.unit.test.ts → index.unit.test.ts} +3 -3
- package/src/utils/storage/types.ts +7 -0
- package/src/utils/supabase/createBaseClient.test.ts +1 -1
- package/src/utils/timezone/timezone.test.ts +1 -1
- package/src/utils/{__tests__/timezone.test.ts → timezone.test.ts} +2 -2
- package/src/utils/validation/{__tests__/common.test.ts → common.test.ts} +2 -2
- package/src/utils/validation/{__tests__/csrf.test.ts → csrf.test.ts} +56 -28
- package/src/utils/validation/csrf.ts +42 -41
- package/src/utils/validation/{__tests__/htmlSanitization.unit.test.ts → htmlSanitization.unit.test.ts} +2 -2
- package/src/utils/validation/{__tests__/passwordSchema.test.ts → passwordSchema.test.ts} +2 -2
- package/src/utils/validation/{__tests__/schema.test.ts → schema.test.ts} +2 -2
- package/src/utils/validation/{__tests__/sqlInjectionProtection.test.ts → sqlInjectionProtection.test.ts} +2 -2
- package/src/utils/validation/{__tests__/user.test.ts → user.test.ts} +2 -2
- package/src/utils/validation/{__tests__/validation.test.ts → validation.test.ts} +2 -2
- package/src/utils/validation/{__tests__/validationUtils.test.ts → validationUtils.test.ts} +2 -2
- package/src/utils/{__tests__/validation.unit.test.ts → validation.unit.test.ts} +1 -1
- package/src/utils/{__tests__/validationUtils.unit.test.ts → validationUtils.unit.test.ts} +5 -2
- package/dist/UnifiedAuthProvider-BBD2PS3Q.js +0 -7
- package/dist/chunk-KPYQWGFQ.js +0 -183
- package/dist/types-D05dCGma.d.ts +0 -521
- package/scripts/eslint-audit.cjs +0 -222
- package/scripts/generate-docs.js +0 -157
- package/scripts/install-cursor-rules.cjs +0 -255
- package/scripts/install-eslint-config.cjs +0 -349
- package/scripts/setup-build-cache.js +0 -73
- package/scripts/validate-pre-publish.js +0 -145
- package/src/__tests__/integration/UserProfile.test.tsx +0 -124
- package/src/__tests__/public-recipe-view.test.ts +0 -228
- package/src/__tests__/rls-policies.test.ts +0 -472
- package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -876
- package/src/components/DataTable/components/DataTableLayout.tsx +0 -584
- package/src/components/DataTable/components/UnifiedTableBody.tsx +0 -395
- package/src/components/DataTable/components/__tests__/DataTableLayout.test.tsx +0 -467
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +0 -358
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +0 -957
- package/src/components/DataTable/core/ActionManager.ts +0 -235
- package/src/components/DataTable/core/ColumnManager.ts +0 -204
- package/src/components/DataTable/core/DataManager.ts +0 -190
- package/src/components/DataTable/core/LocalDataAdapter.ts +0 -274
- package/src/components/DataTable/core/PluginRegistry.ts +0 -229
- package/src/components/DataTable/core/StateManager.ts +0 -312
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +0 -235
- package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +0 -141
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +0 -178
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +0 -133
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +0 -142
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +0 -158
- package/src/components/DataTable/core/interfaces.ts +0 -338
- package/src/components/DataTable/types.ts +0 -764
- package/src/hooks/public/usePublicFileDisplay.ts +0 -534
- package/src/hooks/useFileDisplay.ts +0 -748
- package/src/providers/OrganisationProvider.test.tsx +0 -40
- package/src/providers/OrganisationProvider.tsx +0 -92
- package/src/providers/__tests__/InactivityProvider.test-helper.tsx +0 -65
- package/src/providers/__tests__/OrganisationProvider.test.tsx +0 -616
- package/src/providers/__tests__/OrganisationProvider.wrapper.test.tsx +0 -591
- package/src/rbac/__tests__/cache-invalidation.test.ts +0 -393
- /package/src/components/DataTable/{components/__tests__ → ui}/COVERAGE_NOTE.md +0 -0
- /package/src/components/DataTable/utils/{__tests__/COVERAGE_NOTE.md → COVERAGE_NOTE.md} +0 -0
- /package/src/hooks/{__tests__/useApiFetch.unit.test.ts → useApiFetch.unit.test.ts} +0 -0
- /package/src/providers/{__tests__/README.md → README.md} +0 -0
- /package/src/rbac/{__tests__/index.test.ts → index.test.ts} +0 -0
- /package/src/rbac/{__tests__/rbac-integration.test.ts → rbac-integration.test.ts} +0 -0
- /package/src/types/{__tests__/README.md → README.md} +0 -0
|
@@ -146,7 +146,7 @@ Documented in [RBAC API Reference](../rbac/api-reference.md):
|
|
|
146
146
|
**Data Access (RBAC-protected):**
|
|
147
147
|
- `data_user_organisations_get` - Get all organisations for a user
|
|
148
148
|
- `data_user_organisation_roles_get` - Get user roles in organisations
|
|
149
|
-
- `
|
|
149
|
+
- `data_rbac_roles_list` - List all roles (global, organisation, event-app) for a user. **Explicit parameters are the source of truth:** the function uses only `p_user_id`, `p_organisation_id`, `p_event_id`, `p_app_id`; it does **not** use `x-organisation-id` or request/session org. RLS on `rbac_organisation_roles` and `rbac_event_app_roles` uses caller identity (JWT) via `app.current_user_id` set by the RPC. **Note:** This RPC returns roles for **one** user (the caller when `p_user_id` is null, or the given `p_user_id`). It does **not** return `user_id` and does **not** support "list all users in org X". For that, see "User list for one organisation" below.
|
|
150
150
|
- `data_user_events_get` - Get events accessible to a user
|
|
151
151
|
- `data_cake_meals_get` - Get cake meals for an event (application-specific, RBAC-protected)
|
|
152
152
|
|
|
@@ -168,6 +168,16 @@ Documented in [RBAC API Reference](../rbac/api-reference.md):
|
|
|
168
168
|
|
|
169
169
|
**Note**: For public event access, use `usePublicEvent()` hook from pace-core, which handles direct table queries internally.
|
|
170
170
|
|
|
171
|
+
### User list for one organisation
|
|
172
|
+
|
|
173
|
+
Apps that need to show **all users (or user IDs) in a given organisation** have two options:
|
|
174
|
+
|
|
175
|
+
1. **Direct query (recommended):** Query the `rbac_organisation_roles` table with a filter on `organisation_id`. Use the secure client from `useSecureSupabase()`. When the "current org" is derived from the URL (e.g. `/users?org=scouts-victoria`), ensure the secure client has that organisation context for the request (e.g. keep `selectedOrganisation` in sync with the URL, or use a client created with that org via `withContext({ organisationId: urlOrgId })`). The caller must have access to that org (or be a super admin). Select distinct `user_id` (and optionally `role`, etc.) as needed.
|
|
176
|
+
|
|
177
|
+
2. **Alternative:** If pace-core adds a dedicated RPC that returns `(user_id, role, ...)` for a given `p_organisation_id`, use that and pass the org ID explicitly; such an RPC would use only explicit parameters and caller auth/RLS.
|
|
178
|
+
|
|
179
|
+
**Not supported:** Calling `data_rbac_roles_list` with only `p_organisation_id` does **not** return "all users in the org". It returns the **caller's** roles in that org (when `p_user_id` is null), and the return type has no `user_id` column.
|
|
180
|
+
|
|
171
181
|
## Removed Legacy RPC Functions
|
|
172
182
|
|
|
173
183
|
The following RPC functions have been **removed** in v0.6.x. All consuming apps have been migrated to modern alternatives.
|
|
@@ -233,8 +243,7 @@ These functions are used internally by pace-core and should **NOT** be called di
|
|
|
233
243
|
- ~~`get_organisation_context`~~ - **REMOVED** - No longer needed
|
|
234
244
|
- ~~`get_page_scope_type`~~ - **REMOVED** - Replaced with direct table queries
|
|
235
245
|
|
|
236
|
-
**
|
|
237
|
-
- `grant_event_app_role` - Used by `useRoleManagement` hook (use hook instead)
|
|
246
|
+
**Event-app role grants:** Use `rbac_role_grant` with `p_role_type: 'event_app'` and `p_context_id: '<event_id>:<app_id>'`. The `useRoleManagement().grantEventAppRole` hook calls this RPC.
|
|
238
247
|
|
|
239
248
|
**Note**: The removed functions have been replaced with direct table queries or are no longer needed. Organisation context is automatically handled by the secure Supabase client from `useSecureSupabase()` hook.
|
|
240
249
|
|
|
@@ -236,6 +236,14 @@ SELECT rbac_role_grant(
|
|
|
236
236
|
|
|
237
237
|
For complete documentation on role management functions, see **[Role Management Functions](../rbac/role-management-functions.md)**.
|
|
238
238
|
|
|
239
|
+
### Required migrations for role management
|
|
240
|
+
|
|
241
|
+
Granting roles (including event-app roles) requires the **`rbac_role_grant`** RPC to exist in the database. The Supabase project must have the migration that creates or updates this function applied.
|
|
242
|
+
|
|
243
|
+
- **Migration:** `20260109112708_fix_rbac_role_grant_reactivate_inactive_roles.sql` (or a later migration that defines `public.rbac_role_grant`).
|
|
244
|
+
- **Symptom:** If `POST …/rest/v1/rpc/rbac_role_grant` returns **404**, the function is missing — apply pending Supabase migrations to the project.
|
|
245
|
+
- Consuming apps (e.g. pace-admin) that use `useRoleManagement().grantEventAppRole` call this RPC; ensure the project’s migrations are applied before using role grant features.
|
|
246
|
+
|
|
239
247
|
## RBAC Compliance & Recent Changes
|
|
240
248
|
|
|
241
249
|
### Database-Driven Permissions
|
|
@@ -18,26 +18,21 @@ npm install @jmruthers/pace-core
|
|
|
18
18
|
|
|
19
19
|
### Step 2: Install Cursor Rules
|
|
20
20
|
|
|
21
|
-
Run the
|
|
21
|
+
Run the combined setup script from your app root:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
|
|
24
|
+
npm run setup
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
This will install:
|
|
28
|
+
- Cursor rules for AI-assisted enforcement
|
|
29
|
+
- ESLint configuration for real-time linting
|
|
30
|
+
- Standards documentation to `docs/standards/`
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
{
|
|
31
|
-
"scripts": {
|
|
32
|
-
"setup:cursor-rules": "node node_modules/@jmruthers/pace-core/scripts/install-cursor-rules.cjs"
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Then run:
|
|
32
|
+
Or to force update existing configs:
|
|
38
33
|
|
|
39
34
|
```bash
|
|
40
|
-
npm run setup
|
|
35
|
+
npm run setup -- --force
|
|
41
36
|
```
|
|
42
37
|
|
|
43
38
|
The script will:
|
|
@@ -131,18 +126,20 @@ Content with examples and guidelines.
|
|
|
131
126
|
|
|
132
127
|
### Compliance Check
|
|
133
128
|
|
|
134
|
-
For
|
|
129
|
+
For full validation including the pace-core audit:
|
|
135
130
|
|
|
136
131
|
```bash
|
|
137
|
-
|
|
132
|
+
npm run validate
|
|
138
133
|
```
|
|
139
134
|
|
|
135
|
+
Review `audit/<timestamp>-pace-core-audit.md` for pace-core compliance and other standards.
|
|
136
|
+
|
|
140
137
|
## Updating Rules
|
|
141
138
|
|
|
142
|
-
When pace-core is updated, run the
|
|
139
|
+
When pace-core is updated, run the setup script again:
|
|
143
140
|
|
|
144
141
|
```bash
|
|
145
|
-
npm run setup
|
|
142
|
+
npm run setup
|
|
146
143
|
```
|
|
147
144
|
|
|
148
145
|
The script will:
|
|
@@ -155,7 +152,7 @@ The script will:
|
|
|
155
152
|
To force update all rules (even when versions match):
|
|
156
153
|
|
|
157
154
|
```bash
|
|
158
|
-
|
|
155
|
+
npm run setup -- --force
|
|
159
156
|
```
|
|
160
157
|
|
|
161
158
|
**Note**: Normally, pace-core rules are automatically updated when they change. The `--force` flag forces an update even when versions match (useful if content changed but version metadata wasn't updated).
|
|
@@ -210,7 +207,7 @@ Each app maintains its own `.cursor/rules/` directory.
|
|
|
210
207
|
1. **Initial Setup:**
|
|
211
208
|
```bash
|
|
212
209
|
npm install @jmruthers/pace-core
|
|
213
|
-
npm run setup
|
|
210
|
+
npm run setup
|
|
214
211
|
```
|
|
215
212
|
|
|
216
213
|
2. **Daily Development:**
|
|
@@ -225,7 +222,7 @@ Each app maintains its own `.cursor/rules/` directory.
|
|
|
225
222
|
4. **After pace-core Updates:**
|
|
226
223
|
```bash
|
|
227
224
|
npm update @jmruthers/pace-core
|
|
228
|
-
npm run setup
|
|
225
|
+
npm run setup
|
|
229
226
|
```
|
|
230
227
|
|
|
231
228
|
## Related Documentation
|
|
@@ -48,7 +48,7 @@ reviewedBy: dependency-clarity-audit
|
|
|
48
48
|
- Validation runs automatically before publishing via `prepublishOnly` hook
|
|
49
49
|
|
|
50
50
|
**For consuming apps:**
|
|
51
|
-
- Use the
|
|
51
|
+
- Use the pace-core Audit step in `npm run validate` to check your dependencies
|
|
52
52
|
- The audit tool reads the current `package.json` from the installed pace-core package
|
|
53
53
|
- Version requirements shown by the audit tool come directly from `package.json`
|
|
54
54
|
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# pace-core Setup Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how to set up pace-core in your consuming app with a single command.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
After installing `@jmruthers/pace-core`, run:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm run setup
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This single command will:
|
|
14
|
+
- ✅ Set up ESLint configuration for real-time compliance checking
|
|
15
|
+
- ✅ Install Cursor rules for AI-assisted enforcement
|
|
16
|
+
- ✅ Copy standards documentation to `docs/standards/`
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
### Step 1: Install pace-core
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @jmruthers/pace-core
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Step 2: Add Setup Scripts to package.json
|
|
27
|
+
|
|
28
|
+
**Important:** Add the setup and validate scripts to your consuming app's `package.json`. Do NOT create local script files.
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"scripts": {
|
|
33
|
+
"setup": "node node_modules/@jmruthers/pace-core/scripts/setup.cjs",
|
|
34
|
+
"validate": "node node_modules/@jmruthers/pace-core/scripts/validate.cjs"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Note:** These scripts come from the `@jmruthers/pace-core` package, not from your local project. Make sure you're pointing to `node_modules/@jmruthers/pace-core/scripts/`.
|
|
40
|
+
|
|
41
|
+
### Step 3: Run Setup
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm run setup
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
That's it! All pace-core tools are now configured.
|
|
48
|
+
|
|
49
|
+
### Step 4: Run Validation (Optional)
|
|
50
|
+
|
|
51
|
+
After setup, you can run quick validation checks:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npm run validate
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
This runs (in order, when the corresponding script exists):
|
|
58
|
+
- **Type check** – summary in terminal
|
|
59
|
+
- **Lint** – summary in terminal, full output in `audit/<timestamp>-eslint-report.md`
|
|
60
|
+
- **Build** – summary in terminal
|
|
61
|
+
- **Tests** – summary in terminal (runs `test:coverage` if present, otherwise `test`; add `test:coverage` to generate `coverage/index.html`)
|
|
62
|
+
- **pace-core Audit** – standards audit; report in `audit/<timestamp>-pace-core-audit.md`
|
|
63
|
+
|
|
64
|
+
Reports are written to the `audit/` directory. To get a coverage report during validate, add a `test:coverage` script to your `package.json` (e.g. with Vitest: `vitest run --coverage`).
|
|
65
|
+
|
|
66
|
+
## What Gets Set Up
|
|
67
|
+
|
|
68
|
+
### 1. ESLint Configuration
|
|
69
|
+
|
|
70
|
+
The setup script automatically:
|
|
71
|
+
- Finds your ESLint config file (supports `.js`, `.cjs`, `.mjs`, `.json`, `.yaml`, `.yml`)
|
|
72
|
+
- Adds pace-core ESLint rules to your config
|
|
73
|
+
- Creates a backup of your existing config
|
|
74
|
+
- Handles both ES modules and CommonJS formats
|
|
75
|
+
- Supports `tseslint.config()` wrapper
|
|
76
|
+
|
|
77
|
+
### 2. Cursor Rules
|
|
78
|
+
|
|
79
|
+
The setup script:
|
|
80
|
+
- Creates `.cursor/rules/` directory if it doesn't exist
|
|
81
|
+
- Copies all pace-core rules (00-09) to your project
|
|
82
|
+
- **Automatically updates** pace-core rules when they change
|
|
83
|
+
- Preserves your custom rules (50+)
|
|
84
|
+
- Skips files that are already up to date
|
|
85
|
+
|
|
86
|
+
### 3. Standards Documentation
|
|
87
|
+
|
|
88
|
+
The setup script:
|
|
89
|
+
- Copies `packages/core/docs/standards/` to `docs/standards/` in your app
|
|
90
|
+
- Provides offline access to all pace-core standards
|
|
91
|
+
- Updates when you run setup again
|
|
92
|
+
|
|
93
|
+
## Force Update
|
|
94
|
+
|
|
95
|
+
To force update all configurations (overwrites existing):
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npm run setup -- --force
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Use this when:
|
|
102
|
+
- You want to update to the latest pace-core rules
|
|
103
|
+
- Your ESLint config needs to be regenerated
|
|
104
|
+
- You want to refresh the standards documentation
|
|
105
|
+
|
|
106
|
+
## Manual Setup
|
|
107
|
+
|
|
108
|
+
The setup script handles all three tasks (ESLint, Cursor rules, and standards docs) in one command. There are no separate scripts for individual components - use `npm run setup` for everything.
|
|
109
|
+
|
|
110
|
+
## Verification
|
|
111
|
+
|
|
112
|
+
After running setup, verify everything is working:
|
|
113
|
+
|
|
114
|
+
### Run Validation
|
|
115
|
+
|
|
116
|
+
The easiest way to verify everything is working:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npm run validate
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
This runs all available checks (type-check, lint, tests, pace-core audit).
|
|
123
|
+
|
|
124
|
+
### Manual Verification
|
|
125
|
+
|
|
126
|
+
You can also check individual components:
|
|
127
|
+
|
|
128
|
+
**Check ESLint:**
|
|
129
|
+
```bash
|
|
130
|
+
npm run lint
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Check Cursor Rules:**
|
|
134
|
+
1. Restart Cursor
|
|
135
|
+
2. Open a file that matches the rule patterns
|
|
136
|
+
3. Rules should be automatically loaded
|
|
137
|
+
|
|
138
|
+
**Check Standards:**
|
|
139
|
+
```bash
|
|
140
|
+
ls docs/standards/
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
You should see all the standards markdown files.
|
|
144
|
+
|
|
145
|
+
## Troubleshooting
|
|
146
|
+
|
|
147
|
+
### Error: Cannot find module 'scripts/setup.cjs'
|
|
148
|
+
|
|
149
|
+
**Problem:** Your `package.json` has a `setup` script pointing to a local file that doesn't exist:
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"scripts": {
|
|
153
|
+
"setup": "node scripts/setup.cjs" // ❌ WRONG - This file doesn't exist in consuming apps
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Solution:** Update your `package.json` to use the script from the pace-core package:
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"scripts": {
|
|
162
|
+
"setup": "node node_modules/@jmruthers/pace-core/scripts/setup.cjs" // ✅ CORRECT
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Important:** The setup script comes from `@jmruthers/pace-core`, not from your local project. You should NOT create a local `scripts/setup.cjs` file.
|
|
168
|
+
|
|
169
|
+
### Setup Script Not Found
|
|
170
|
+
|
|
171
|
+
If you get an error that the script can't be found:
|
|
172
|
+
|
|
173
|
+
1. Verify pace-core is installed:
|
|
174
|
+
```bash
|
|
175
|
+
npm list @jmruthers/pace-core
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
2. Check the script path:
|
|
179
|
+
```bash
|
|
180
|
+
ls node_modules/@jmruthers/pace-core/scripts/setup.cjs
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
3. If the file doesn't exist, you may need to update pace-core:
|
|
184
|
+
```bash
|
|
185
|
+
npm update @jmruthers/pace-core
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
4. Make sure your `package.json` script points to `node_modules/@jmruthers/pace-core/scripts/setup.cjs`, not a local `scripts/setup.cjs`
|
|
189
|
+
|
|
190
|
+
### ESLint Config Issues
|
|
191
|
+
|
|
192
|
+
If ESLint setup fails:
|
|
193
|
+
|
|
194
|
+
1. Check your ESLint config file exists
|
|
195
|
+
2. Try with `--force` flag:
|
|
196
|
+
```bash
|
|
197
|
+
npm run setup -- --force
|
|
198
|
+
```
|
|
199
|
+
3. Check the backup file created (`.backup.{timestamp}`)
|
|
200
|
+
4. See [ESLint Setup Troubleshooting](../standards/1-pace-core-compliance-standards.md#eslint-setup-issues)
|
|
201
|
+
|
|
202
|
+
### Cursor Rules Not Loading
|
|
203
|
+
|
|
204
|
+
1. Verify rules are in `.cursor/rules/` directory
|
|
205
|
+
2. Check file extensions are `.mdc`
|
|
206
|
+
3. Restart Cursor
|
|
207
|
+
4. Check rule frontmatter is valid YAML
|
|
208
|
+
|
|
209
|
+
### Standards Not Copied
|
|
210
|
+
|
|
211
|
+
If standards aren't copied:
|
|
212
|
+
|
|
213
|
+
1. Check pace-core package has docs:
|
|
214
|
+
```bash
|
|
215
|
+
ls node_modules/@jmruthers/pace-core/docs/standards/
|
|
216
|
+
```
|
|
217
|
+
2. Try with `--force` flag:
|
|
218
|
+
```bash
|
|
219
|
+
npm run setup -- --force
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Next Steps
|
|
223
|
+
|
|
224
|
+
After setup:
|
|
225
|
+
|
|
226
|
+
1. **Restart Cursor** to load the new rules
|
|
227
|
+
2. **Run validation**: `npm run validate` (type-check, lint, build, tests, pace-core audit; reports in `audit/`)
|
|
228
|
+
3. **Review standards** in `docs/standards/` for complete documentation
|
|
229
|
+
|
|
230
|
+
## Related Documentation
|
|
231
|
+
|
|
232
|
+
- [Cursor Rules Guide](./cursor-rules.md) - Using Cursor rules effectively
|
|
233
|
+
- [Standards Documentation](../standards/README.md) - Complete standards reference
|
|
234
|
+
- [pace-core Compliance](../standards/1-pace-core-compliance-standards.md) - Compliance requirements
|
|
235
|
+
- [Local Development](./local-development.md) - Using pace-core locally
|
|
@@ -263,6 +263,22 @@ function App() {
|
|
|
263
263
|
|
|
264
264
|
**Important:** The `ProtectedRoute` component solves the common chicken-and-egg problem where apps check for `selectedEvent` before rendering, which blocks the event selector (typically in the `PaceAppLayout` header) from being visible. The component allows rendering when events exist but none is selected, enabling users to see and use the event selector dropdown.
|
|
265
265
|
|
|
266
|
+
### Critical: Auth routing pattern
|
|
267
|
+
|
|
268
|
+
To avoid "login succeeds but redirect doesn't happen" or the login form resetting after submit, follow this pattern:
|
|
269
|
+
|
|
270
|
+
- **MUST** use a single public `/login` route and wrap all other routes in **ProtectedRoute**. Do not wrap the whole app in a custom "auth gate" that redirects when `!isAuthenticated`.
|
|
271
|
+
- **MUST NOT** wrap `<Routes>` in a component that, when `!isAuthenticated`, renders `<Navigate to="/login" />` for non-login paths. That races with post-login context updates and can send the user back to the login page with a reset form.
|
|
272
|
+
- **SHOULD** avoid `BrowserRouter` `future: { v7_startTransition: true, v7_relativeSplatPath: true }` until compatibility with auth context updates is verified; use plain `<BrowserRouter>`.
|
|
273
|
+
|
|
274
|
+
See [Redirect not happening after login](#1-login-not-working) in Troubleshooting if you see this behaviour.
|
|
275
|
+
|
|
276
|
+
**Auth and routing checklist (new apps):**
|
|
277
|
+
- [ ] `/login` is a public route; all other routes are under `<Route element={<ProtectedRoute />}>` (or `requireEvent={false}` variant).
|
|
278
|
+
- [ ] No wrapper component that redirects to `/login` when `!isAuthenticated` for the whole app.
|
|
279
|
+
- [ ] `BrowserRouter` used without `future` flags (or login and logout verified if using them).
|
|
280
|
+
- [ ] Verify login and logout in the app after setup.
|
|
281
|
+
|
|
266
282
|
## Configuration Options
|
|
267
283
|
|
|
268
284
|
### UnifiedAuthProvider Props
|
|
@@ -801,6 +817,7 @@ function App() {
|
|
|
801
817
|
- [ ] User credentials are valid in Supabase
|
|
802
818
|
- [ ] Network connectivity working
|
|
803
819
|
- [ ] Browser not blocking cookies
|
|
820
|
+
- [ ] **Auth routing pattern**: You use a public `/login` route and wrap other routes in `ProtectedRoute`; you do not use a global auth gate that redirects to `/login` when `!isAuthenticated`. See [Critical: Auth routing pattern](#critical-auth-routing-pattern) above.
|
|
804
821
|
|
|
805
822
|
#### 2. Session Not Persisting
|
|
806
823
|
|
|
@@ -858,6 +875,16 @@ function AuthTest() {
|
|
|
858
875
|
}
|
|
859
876
|
```
|
|
860
877
|
|
|
878
|
+
#### 4. Logout does nothing / 403 on logout
|
|
879
|
+
|
|
880
|
+
**Symptoms:**
|
|
881
|
+
- Logout button does nothing; user stays on the app
|
|
882
|
+
- Network tab shows `POST .../auth/v1/logout` returning 403
|
|
883
|
+
|
|
884
|
+
**Cause:** Supabase sign-out with default (global) scope can return 403 in some environments (e.g. cookie domain, CORS). pace-core handles this by clearing local auth state and calling `signOut({ scope: 'local' })`, so the UI should still show the user as logged out and redirect to login.
|
|
885
|
+
|
|
886
|
+
**If logout still does nothing:** Check cookie domain and CORS for your Supabase project and app origin. The app should still clear local state; if it does not, ensure you are on a version of pace-core that includes the signOut error-handling fix.
|
|
887
|
+
|
|
861
888
|
### Detailed Solutions
|
|
862
889
|
|
|
863
890
|
#### Wrong Supabase Configuration
|
|
@@ -38,6 +38,10 @@ The PACE Core DataTable is an enterprise-grade data table component built on Tan
|
|
|
38
38
|
>
|
|
39
39
|
> The component uses pace-core's internal toast system to provide consistent user feedback. Your `onDeleteRow`, `onDeleteSelected`, `onImport`, and `onExport` handlers should focus on the data operations themselves - the UI feedback is handled for you.
|
|
40
40
|
|
|
41
|
+
### Bulk delete confirmation
|
|
42
|
+
|
|
43
|
+
When `deleteSelected` is enabled, a **confirmation dialog** is shown by pace-core before the app's `onDeleteSelected` is called. The dialog displays the number of selected rows and warns that the action cannot be undone. You do not need to show your own confirmation (e.g. `window.confirm`) for the same bulk-delete action. If your app has additional, domain-specific warnings (e.g. "this will also delete related diners and menus"), you may show those after the user has confirmed in the pace-core dialog.
|
|
44
|
+
|
|
41
45
|
### Audit Logging
|
|
42
46
|
|
|
43
47
|
> **ℹ️ Audit Logging**: The DataTable component **does NOT** automatically create audit entries for CRUD operations. Audit logging must be handled by either:
|
|
@@ -1985,6 +1989,47 @@ When `export: true` and `import: true` are enabled in features, the DataTable au
|
|
|
1985
1989
|
- Case-insensitive header matching
|
|
1986
1990
|
- Supports both display names and field names
|
|
1987
1991
|
|
|
1992
|
+
#### Import result contract (required for correct modal summary)
|
|
1993
|
+
|
|
1994
|
+
For the Import modal to show accurate success/failed counts, your `onImport` handler **must return** a result in the standard shape. The modal only recognises this contract; it does not accept app-specific or RPC-specific shapes.
|
|
1995
|
+
|
|
1996
|
+
**Standard shape** (exported as `ImportSummary` from `@jmruthers/pace-core`):
|
|
1997
|
+
|
|
1998
|
+
```ts
|
|
1999
|
+
interface ImportSummary {
|
|
2000
|
+
successCount: number; // number of rows imported successfully
|
|
2001
|
+
totalCount: number; // total rows in this chunk (or full import)
|
|
2002
|
+
failedCount: number; // number of rows that failed
|
|
2003
|
+
failedRows?: Array<{ row: number; reason: string }>; // optional details for failed rows
|
|
2004
|
+
}
|
|
2005
|
+
```
|
|
2006
|
+
|
|
2007
|
+
**Return type**: `onImport` may return `void`, `Promise<void>`, `ImportSummary`, or `Promise<ImportSummary>`. The layout passes your handler's return value through to the modal. If you return anything other than a valid `ImportSummary` (including returning nothing), the modal treats the chunk as fully failed and shows incorrect counts (e.g. 0 successful, all rows failed). For accurate counts and failure details, you **must** return `ImportSummary` per chunk.
|
|
2008
|
+
|
|
2009
|
+
**Guidance for consuming apps**:
|
|
2010
|
+
|
|
2011
|
+
1. **Return `ImportSummary` from your handler.** After your import logic runs (RPC, API, or local), map the result into `ImportSummary` and return it.
|
|
2012
|
+
2. **Chunking**: The DataTable calls `onImport` once per chunk. Return a summary **per chunk** (e.g. `successCount` and `totalCount` for that chunk). The modal merges chunk results automatically.
|
|
2013
|
+
3. **Mapping from RPC/app shapes**: If your RPC returns e.g. `{ imported: 48, failed: 0 }` or `{ importedDiners: 100, totalRowsProcessed: 100, skippedRows: [] }`, map it before returning:
|
|
2014
|
+
|
|
2015
|
+
```ts
|
|
2016
|
+
import type { ImportSummary } from '@jmruthers/pace-core';
|
|
2017
|
+
|
|
2018
|
+
onImport={async (chunk) => {
|
|
2019
|
+
const result = await myRpcOrImport(chunk); // your app-specific result
|
|
2020
|
+
return {
|
|
2021
|
+
successCount: result.imported ?? result.importedDiners ?? 0,
|
|
2022
|
+
totalCount: result.totalRowsProcessed ?? chunk.length,
|
|
2023
|
+
failedCount: result.failed ?? result.skippedRows?.length ?? 0,
|
|
2024
|
+
failedRows: result.skippedRows?.map(({ row, reason }) => ({ row, reason })),
|
|
2025
|
+
} satisfies ImportSummary;
|
|
2026
|
+
}}
|
|
2027
|
+
```
|
|
2028
|
+
|
|
2029
|
+
4. **Do not return** app-specific shapes (e.g. `importedUnits`, `importedDiners`, RPC table rows) and expect the modal to interpret them. Always map to `ImportSummary` at the boundary.
|
|
2030
|
+
5. **Populate `failedRows` from validation and RPC.** Include exact failure reasons from your validation (e.g. "Could not find meal for date X, type Y for the selected event") and from the database/RPC (e.g. per-row error messages). The modal displays these as-is so users can pinpoint issues. Do not replace or correct the summary after the fact; the only source of truth is what your handler returns per chunk.
|
|
2031
|
+
6. **Reject invalid rows in validation.** If some rows would be inserted but not visible (e.g. due to event or RLS), reject them in validation with a clear reason so they appear in `failedRows` instead of being inserted and then missing from the list.
|
|
2032
|
+
|
|
1988
2033
|
### Export/Import with Reference Fields
|
|
1989
2034
|
|
|
1990
2035
|
For columns that display related data (using `accessorFn` with `editAccessorKey`), the export includes both the display value and the ID value for seamless round-trip import/export.
|
|
@@ -2074,7 +2119,135 @@ The import automatically recognizes and maps:
|
|
|
2074
2119
|
/>
|
|
2075
2120
|
```
|
|
2076
2121
|
|
|
2077
|
-
> **📚 Import
|
|
2122
|
+
> **📚 Import result contract**: Ensure your `onImport` handler returns [ImportSummary](#import-result-contract-required-for-correct-modal-summary) so the modal shows correct success/failed counts. Map RPC or app-specific results to that shape at the boundary.
|
|
2123
|
+
|
|
2124
|
+
#### Using Bulk Import RPCs
|
|
2125
|
+
|
|
2126
|
+
For large imports (100+ rows), use bulk import RPC functions for better performance. CAKE app provides bulk import RPCs that use `SECURITY DEFINER` and automatically retrieve the authenticated user via `auth.uid()`.
|
|
2127
|
+
|
|
2128
|
+
**Benefits:**
|
|
2129
|
+
- No session timeout issues during long imports (user authentication never expires mid-call)
|
|
2130
|
+
- Simplified client code (no need to manage user session state)
|
|
2131
|
+
- Better performance (single upfront permission check instead of per-row RLS, 60-70% faster)
|
|
2132
|
+
- User-friendly error messages
|
|
2133
|
+
|
|
2134
|
+
**Example: Bulk Import Mealplans**
|
|
2135
|
+
|
|
2136
|
+
```tsx
|
|
2137
|
+
import { useSecureSupabase } from '@jmruthers/pace-core/rbac';
|
|
2138
|
+
import type { ImportSummary } from '@jmruthers/pace-core';
|
|
2139
|
+
|
|
2140
|
+
function MealplansTable() {
|
|
2141
|
+
const supabase = useSecureSupabase();
|
|
2142
|
+
const { selectedOrganisation } = useOrganisations();
|
|
2143
|
+
const { selectedEvent } = useEvents();
|
|
2144
|
+
|
|
2145
|
+
const handleImport = async (importedData: any[]): Promise<ImportSummary> => {
|
|
2146
|
+
// No need to check user session - auth.uid() handles it automatically
|
|
2147
|
+
const { data, error } = await supabase.rpc('app_cake_mealplans_bulk_import', {
|
|
2148
|
+
p_mealplans_data: importedData,
|
|
2149
|
+
p_organisation_id: selectedOrganisation.id,
|
|
2150
|
+
p_event_id: selectedEvent?.id // Optional
|
|
2151
|
+
});
|
|
2152
|
+
|
|
2153
|
+
if (error) {
|
|
2154
|
+
// Error messages are user-friendly and specific
|
|
2155
|
+
toast.error(error.message);
|
|
2156
|
+
return {
|
|
2157
|
+
successCount: 0,
|
|
2158
|
+
totalCount: importedData.length,
|
|
2159
|
+
failedCount: importedData.length,
|
|
2160
|
+
};
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
const result = data[0];
|
|
2164
|
+
return {
|
|
2165
|
+
successCount: result.imported,
|
|
2166
|
+
totalCount: importedData.length,
|
|
2167
|
+
failedCount: result.failed,
|
|
2168
|
+
failedRows: result.errors ? JSON.parse(result.errors as string) : [],
|
|
2169
|
+
};
|
|
2170
|
+
};
|
|
2171
|
+
|
|
2172
|
+
return (
|
|
2173
|
+
<DataTable
|
|
2174
|
+
data={mealplans}
|
|
2175
|
+
columns={columns}
|
|
2176
|
+
features={{ import: true }}
|
|
2177
|
+
onImport={handleImport}
|
|
2178
|
+
rbac={{ pageName: 'units' }} // Mealplans managed through units
|
|
2179
|
+
/>
|
|
2180
|
+
);
|
|
2181
|
+
}
|
|
2182
|
+
```
|
|
2183
|
+
|
|
2184
|
+
**Available Bulk Import RPCs:**
|
|
2185
|
+
|
|
2186
|
+
| RPC Function | Purpose | Permission Required |
|
|
2187
|
+
|-------------|---------|---------------------|
|
|
2188
|
+
| `app_cake_mealplans_bulk_import` | Bulk import mealplans | `create:page.units` |
|
|
2189
|
+
| `app_cake_units_bulk_import` | Bulk import units | `create:page.units` |
|
|
2190
|
+
| `app_cake_diners_bulk_import` | Bulk import diners | `create:page.units` |
|
|
2191
|
+
| `app_cake_meals_bulk_import` | Bulk import meals | `create:page.meals` |
|
|
2192
|
+
| `app_cake_mealplan_bulk_delete` | Bulk delete mealplans for a unit | `delete:page.units` |
|
|
2193
|
+
|
|
2194
|
+
**RPC Parameters (all bulk import functions):**
|
|
2195
|
+
|
|
2196
|
+
- `p_[resource]_data` (required): JSONB array of records to import
|
|
2197
|
+
- `p_organisation_id` (required): Organisation context UUID
|
|
2198
|
+
- `p_event_id` (optional): Event context for additional validation
|
|
2199
|
+
|
|
2200
|
+
**Note:** You do **not** need to pass `p_user_id` - authentication is handled automatically via the JWT token in the request. The RPC will:
|
|
2201
|
+
1. Verify user is authenticated
|
|
2202
|
+
2. Check user has access to the organisation
|
|
2203
|
+
3. Verify user has the required permission
|
|
2204
|
+
4. Perform the bulk import if all checks pass
|
|
2205
|
+
|
|
2206
|
+
This eliminates session timeout issues and simplifies client code.
|
|
2207
|
+
|
|
2208
|
+
##### Menus import: why some rows don't appear in the list
|
|
2209
|
+
|
|
2210
|
+
The menus list is driven by `data_cake_mealplans_list`, which **filters by event**: it only returns mealplans whose meal's `meal_event_id` matches the **selected event**. If your import handler resolves (Meal Date, Meal Type) to a `meal_id` from a **different event** (e.g. same org, same date/type in another event), those rows are inserted successfully but **never shown** in the list, so the UI shows fewer rows than the import count.
|
|
2211
|
+
|
|
2212
|
+
**Required:** When building the payload for `app_cake_mealplans_bulk_import`, resolve `meal_id` using **the selected event**: e.g. look up meal by `(event_id, meal_date, meal_type)` (or equivalent), not by `(meal_date, meal_type)` alone. That way every imported row uses a meal for the current event and will appear in the list.
|
|
2213
|
+
|
|
2214
|
+
**To identify which rows are "missing" (inserted but not visible):**
|
|
2215
|
+
|
|
2216
|
+
1. **CSV diagnosis:** Run `node scripts/diagnose-menus-import.js "<path-to-menus.csv>"` to confirm row count and check for duplicate (Unit Number, Meal Date, Meal Type, Dish Code) keys.
|
|
2217
|
+
2. **DB diagnosis:** In Supabase SQL Editor, run the query in `scripts/sql/mealplans_not_visible_for_event.sql` after replacing `YOUR_EVENT_ID` and the unit_ids array. It returns mealplans for those units whose meal is not in the selected event (the difference between import count and list count).
|
|
2218
|
+
|
|
2219
|
+
**Troubleshooting: rows reported as failed (e.g. "Could not find meal" or "Unit not found")**
|
|
2220
|
+
|
|
2221
|
+
The import only uses **units, meals and dishes that belong to the event currently selected** in the page header. If the failed-rows table shows reasons like "Could not find meal for date X, type Y for the selected event" or "Unit N not found for the selected event", then:
|
|
2222
|
+
|
|
2223
|
+
1. **Confirm the event** – Ensure the correct event is selected in the header before starting the import. The same unit number (e.g. 115) or meal (same date and type) can exist under different events; the import only sees data for the selected event.
|
|
2224
|
+
2. **Match CSV to that event** – The CSV Unit Number must match `cake_unit.unit_number` for a unit that has `unit_event_id` = selected event. Meals and dishes are matched by `meal_event_id` / `dish_event_id` = selected event. If the CSV was exported from another event, re-export for the selected event or switch event to match the CSV.
|
|
2225
|
+
3. **Meal date and type** – Meal is matched by date (parsed from the CSV Meal Date column, e.g. DD/MM/YYYY → YYYY-MM-DD), meal type name (case-insensitive, from Meal Type column), and event. Ensure the meal exists for that exact date and type for the selected event.
|
|
2226
|
+
4. **Dish code** – Dish is matched by code (Dish Code column) and event. Check for typos or extra spaces; the code must exist for the selected event.
|
|
2227
|
+
|
|
2228
|
+
#### Advanced Import Configuration
|
|
2229
|
+
|
|
2230
|
+
The DataTable import feature supports configuration through the `importModalConfig` prop to customize modal text only. The summary shown in the modal is the merge of the `ImportSummary` values returned by your `onImport` handler per chunk; do not correct or replace it after the fact.
|
|
2231
|
+
|
|
2232
|
+
##### Available Configuration Options
|
|
2233
|
+
|
|
2234
|
+
```tsx
|
|
2235
|
+
interface ImportModalConfig {
|
|
2236
|
+
title?: string;
|
|
2237
|
+
description?: string;
|
|
2238
|
+
uploadText?: string;
|
|
2239
|
+
selectFileButtonText?: string;
|
|
2240
|
+
importButtonText?: string;
|
|
2241
|
+
importButtonProcessingText?: string;
|
|
2242
|
+
cancelButtonText?: string;
|
|
2243
|
+
previewHeaderText?: string;
|
|
2244
|
+
totalRowsText?: string; // Use {count} as placeholder
|
|
2245
|
+
/** When true, send the entire file in one chunk. Required for handlers that delete-then-insert per unit/entity (e.g. menus), so later chunks do not overwrite earlier ones. */
|
|
2246
|
+
singleChunk?: boolean;
|
|
2247
|
+
}
|
|
2248
|
+
```
|
|
2249
|
+
|
|
2250
|
+
**Menus import:** Use `singleChunk: true` for menus (mealplans) import. The handler deletes all mealplans for each unit then inserts the chunk's rows; with multiple chunks, later chunks would delete and replace earlier chunks' data for the same unit, so the reported count would be wrong and many rows would be missing. With `singleChunk: true`, the whole file is sent in one call and the summary matches the actual result.
|
|
2078
2251
|
|
|
2079
2252
|
### Custom Export
|
|
2080
2253
|
|
|
@@ -2460,7 +2633,7 @@ function UserForm({ user, onSubmit, onCancel }) {
|
|
|
2460
2633
|
<button
|
|
2461
2634
|
type="submit"
|
|
2462
2635
|
disabled={isSubmitting}
|
|
2463
|
-
className="px-4 py-2 bg-main-600 text-
|
|
2636
|
+
className="px-4 py-2 bg-main-600 text-main-50 rounded hover:bg-main-700 disabled:opacity-50"
|
|
2464
2637
|
>
|
|
2465
2638
|
{isSubmitting ? 'Saving...' : 'Save'}
|
|
2466
2639
|
</button>
|
|
@@ -2515,7 +2688,7 @@ function UserForm({ user, onSubmit, onCancel }) {
|
|
|
2515
2688
|
|
|
2516
2689
|
#### 7. Delete selected rows not working
|
|
2517
2690
|
- **Check feature configuration**: Ensure `features={{ selection: true, deletion: true, deleteSelected: true }}`
|
|
2518
|
-
- **Provide onDeleteSelected callback**: Implement the callback to handle bulk deletion
|
|
2691
|
+
- **Provide onDeleteSelected callback**: Implement the callback to handle bulk deletion. A confirmation dialog is shown by pace-core before your handler is called; do not add a separate confirm step for the same action.
|
|
2519
2692
|
- **Verify getRowId function**: Ensure you provide a `getRowId` function that returns unique IDs
|
|
2520
2693
|
- **Check button visibility**: The delete button only appears when all three features are enabled and rows are selected
|
|
2521
2694
|
- **Debug selection state**: Add console logs to verify `onRowSelectionChange` is being called with correct data
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# ApiResult migration
|
|
2
|
+
|
|
3
|
+
Async API-style functions in `@jmruthers/pace-core` now return a consistent **`ApiResult<T>`** shape instead of throwing or returning raw values. This document points to the CHANGELOG and standards for the type and migration.
|
|
4
|
+
|
|
5
|
+
## Summary
|
|
6
|
+
|
|
7
|
+
- **Type**: `ApiResult<T> = { ok: true; data: T } | { ok: false; error: ApiError }`
|
|
8
|
+
- **Error type**: `ApiError = { code: string; message: string; details?: object }`
|
|
9
|
+
- **Helpers**: `ok(data)`, `err(error)`, `isOk(result)`, `isErr(result)` — exported from the package.
|
|
10
|
+
|
|
11
|
+
## Where to look
|
|
12
|
+
|
|
13
|
+
1. **CHANGELOG** — [packages/core/CHANGELOG.md](../../CHANGELOG.md) (Unreleased → Breaking Changes → “Async API-style functions now return ApiResult<T>”) for the list of affected surfaces and a short before/after.
|
|
14
|
+
2. **Standards** — [7-api-tech-stack-standards.md](../standards/7-api-tech-stack-standards.md) and [3-architecture-standards.md](../standards/3-architecture-standards.md) for the ApiResult contract and usage.
|
|
15
|
+
|
|
16
|
+
## Affected surfaces
|
|
17
|
+
|
|
18
|
+
- RBAC (e.g. `isPermitted`, `getAccessLevel`, audit, eventContext)
|
|
19
|
+
- Auth (auth-utils, `IAuthService` / `AuthService`)
|
|
20
|
+
- File-reference service and storage helpers (`extractFileMetadata`, `getSignedUrl`, `listFiles`, `downloadFile`, `generateFileUrlsBatch`, etc.)
|
|
21
|
+
- Context and app utilities (`organisationContext`, `appIdResolver`)
|
|
22
|
+
- Google Places and CSRF
|
|
23
|
+
- Security (`validateUserSession`, etc.)
|
|
24
|
+
|
|
25
|
+
At each call site, check `result.ok` and use `result.data` or `result.error` accordingly.
|