@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
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
11
11
|
- **DataTable: Automatic label display for select fields** - Select fields with `fieldType: 'select'` and `fieldOptions` now automatically display labels (e.g., "Mobile") instead of raw values (e.g., `1`) in read mode. This eliminates the need for custom cell renderers for common select field patterns. The feature supports simple options, grouped options, type coercion, and gracefully falls back to raw values when labels aren't found. Custom cell renderers are preserved if already defined.
|
|
12
12
|
|
|
13
13
|
### Breaking Changes
|
|
14
|
+
- **Async API-style functions now return `ApiResult<T>` (error handling)**: All async API-style functions in pace-core now return `Promise<ApiResult<T>>` instead of throwing or returning raw values. Affected surfaces: RBAC (`isPermitted`, `getAccessLevel`, etc.), auth (auth-utils, `IAuthService`/`AuthService`), file-reference service and storage helpers (`extractFileMetadata`, `getSignedUrl`, `listFiles`, `downloadFile`, `generateFileUrlsBatch`), context/app utilities (`organisationContext`, `appIdResolver`), Google Places and CSRF, and security (`validateUserSession`, etc.).
|
|
15
|
+
- **Action Required**: Check `result.ok` and use `result.data` or `result.error` at every call site.
|
|
16
|
+
- **Migration**:
|
|
17
|
+
```ts
|
|
18
|
+
// ❌ OLD: Direct value or throw
|
|
19
|
+
const data = await someApi();
|
|
20
|
+
if (!data) throw new Error('Failed');
|
|
21
|
+
use(data);
|
|
22
|
+
|
|
23
|
+
// ✅ NEW: ApiResult shape
|
|
24
|
+
const result = await someApi();
|
|
25
|
+
if (!result.ok) {
|
|
26
|
+
console.error(result.error.code, result.error.message);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
use(result.data);
|
|
30
|
+
```
|
|
31
|
+
- **Types**: Import `ApiResult`, `ApiError`, and helpers `ok`, `err`, `isOk`, `isErr` from `@jmruthers/pace-core`.
|
|
32
|
+
- See [API & Tech Stack Standard](./docs/standards/7-api-tech-stack-standards.md) and [Architecture Standard](./docs/standards/3-architecture-standards.md).
|
|
33
|
+
- See [ApiResult migration guide](./docs/migration/ApiResult-migration.md) for affected surfaces and migration steps.
|
|
34
|
+
|
|
14
35
|
- **@supabase/supabase-js is now an included dependency (security enforcement)**: Moved from peer dependency to included dependency to enforce security rules. Consuming apps can no longer import `createClient` directly.
|
|
15
36
|
- **Action Required**:
|
|
16
37
|
- Remove `@supabase/supabase-js` from your `package.json` if installed
|
|
@@ -154,22 +154,37 @@ function checkVersion(installed, required) {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
// Main audit function - returns data structure for programmatic use
|
|
157
|
-
|
|
157
|
+
// auditContext: { isPaceCorePackage?: boolean } - when true, skip audit (package does not install itself)
|
|
158
|
+
function runDependencyAudit(consumingAppPath = process.cwd(), auditContext = {}) {
|
|
158
159
|
const packageJsonPath = path.join(consumingAppPath, 'package.json');
|
|
159
|
-
|
|
160
|
+
const emptyIssues = { includedDeps: [], missingRequired: [], missingOptional: [], versionIssues: [], wrongLocation: [], missingDevDeps: [], devVersionIssues: [] };
|
|
161
|
+
|
|
160
162
|
if (!fs.existsSync(packageJsonPath)) {
|
|
161
163
|
return {
|
|
162
164
|
error: `package.json not found at ${packageJsonPath}`,
|
|
163
|
-
issues:
|
|
165
|
+
issues: emptyIssues
|
|
164
166
|
};
|
|
165
167
|
}
|
|
168
|
+
|
|
169
|
+
if (auditContext.isPaceCorePackage === true) {
|
|
170
|
+
try {
|
|
171
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
172
|
+
return {
|
|
173
|
+
projectName: pkg.name || '@jmruthers/pace-core',
|
|
174
|
+
paceCoreVersion: 'self',
|
|
175
|
+
issues: emptyIssues
|
|
176
|
+
};
|
|
177
|
+
} catch (e) {
|
|
178
|
+
return { projectName: 'unknown', paceCoreVersion: 'self', issues: emptyIssues };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
166
181
|
|
|
167
182
|
// Load pace-core package.json
|
|
168
183
|
const paceCorePath = findPaceCorePackageJson(consumingAppPath);
|
|
169
184
|
if (!paceCorePath) {
|
|
170
185
|
return {
|
|
171
186
|
error: 'Could not find pace-core package.json. Make sure @jmruthers/pace-core is installed in your project.',
|
|
172
|
-
issues:
|
|
187
|
+
issues: emptyIssues
|
|
173
188
|
};
|
|
174
189
|
}
|
|
175
190
|
|
|
@@ -223,16 +238,34 @@ function runDependencyAudit(consumingAppPath = process.cwd()) {
|
|
|
223
238
|
devVersionIssues: [],
|
|
224
239
|
};
|
|
225
240
|
|
|
226
|
-
//
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
241
|
+
// When auditing the pace-core repo root (monorepo), skip "included deps" check:
|
|
242
|
+
// the root package.json is the workspace root and shares the dependency tree with packages/core.
|
|
243
|
+
const packagesCorePath = path.join(consumingAppPath, 'packages', 'core', 'package.json');
|
|
244
|
+
const isPaceCoreRepoRoot = fs.existsSync(packagesCorePath);
|
|
245
|
+
let skipIncludedDepsCheck = false;
|
|
246
|
+
if (isPaceCoreRepoRoot) {
|
|
247
|
+
try {
|
|
248
|
+
const corePkg = JSON.parse(fs.readFileSync(packagesCorePath, 'utf8'));
|
|
249
|
+
if (corePkg.name === '@jmruthers/pace-core') {
|
|
250
|
+
skipIncludedDepsCheck = true;
|
|
251
|
+
}
|
|
252
|
+
} catch (e) {
|
|
253
|
+
// ignore
|
|
234
254
|
}
|
|
235
|
-
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Check for included dependencies (skip when auditing pace-core repo root)
|
|
258
|
+
if (!skipIncludedDepsCheck) {
|
|
259
|
+
INCLUDED_DEPS.forEach(dep => {
|
|
260
|
+
if (allDeps[dep]) {
|
|
261
|
+
issues.includedDeps.push({
|
|
262
|
+
package: dep,
|
|
263
|
+
installed: allDeps[dep],
|
|
264
|
+
location: consumingPkg.dependencies?.[dep] ? 'dependencies' : 'devDependencies',
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
236
269
|
|
|
237
270
|
// Check for required peer dependencies
|
|
238
271
|
REQUIRED_PEERS.forEach(dep => {
|
|
@@ -47,7 +47,8 @@ function checkProviderNesting(consumingAppPath) {
|
|
|
47
47
|
line: 0,
|
|
48
48
|
message: 'main.tsx file not found. Cannot validate provider nesting order.',
|
|
49
49
|
severity: 'error',
|
|
50
|
-
fix: 'Create src/main.tsx with proper provider nesting: QueryClientProvider → BrowserRouter → UnifiedAuthProvider
|
|
50
|
+
fix: 'Create src/main.tsx with proper provider nesting: QueryClientProvider → BrowserRouter → UnifiedAuthProvider',
|
|
51
|
+
standardSection: 'MUST: Provider Nesting Order',
|
|
51
52
|
});
|
|
52
53
|
return issues;
|
|
53
54
|
}
|
|
@@ -59,18 +60,22 @@ function checkProviderNesting(consumingAppPath) {
|
|
|
59
60
|
|
|
60
61
|
const relativePath = getRelativePath(mainFile, consumingAppPath);
|
|
61
62
|
|
|
62
|
-
// Required provider order: QueryClientProvider → BrowserRouter → UnifiedAuthProvider
|
|
63
|
+
// Required provider order: QueryClientProvider → BrowserRouter → UnifiedAuthProvider
|
|
64
|
+
// OrganisationServiceProvider is inside UnifiedAuthProvider; consuming apps must not wrap with it.
|
|
63
65
|
const requiredProviders = [
|
|
64
66
|
{ name: 'QueryClientProvider', import: '@tanstack/react-query' },
|
|
65
67
|
{ name: 'BrowserRouter', import: 'react-router-dom' },
|
|
66
68
|
{ name: 'UnifiedAuthProvider', import: '@jmruthers/pace-core' },
|
|
67
|
-
{ name: 'OrganisationProvider', import: '@jmruthers/pace-core' },
|
|
68
69
|
];
|
|
69
70
|
|
|
70
|
-
// Check if all providers are imported
|
|
71
|
+
// Check if all required providers are imported
|
|
71
72
|
const missingProviders = requiredProviders.filter(provider => {
|
|
72
|
-
const
|
|
73
|
-
|
|
73
|
+
const names = [provider.name].concat(provider.altName || []);
|
|
74
|
+
const hasImport = names.some(name => {
|
|
75
|
+
const importPattern = new RegExp(`import.*${name}.*from\\s+['"]${provider.import.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}['"]`);
|
|
76
|
+
return importPattern.test(content);
|
|
77
|
+
});
|
|
78
|
+
return !hasImport;
|
|
74
79
|
});
|
|
75
80
|
|
|
76
81
|
if (missingProviders.length > 0) {
|
|
@@ -81,6 +86,7 @@ function checkProviderNesting(consumingAppPath) {
|
|
|
81
86
|
message: `Missing required providers: ${missingProviders.map(p => p.name).join(', ')}`,
|
|
82
87
|
severity: 'error',
|
|
83
88
|
fix: `Import and use all required providers in the correct order: ${requiredProviders.map(p => p.name).join(' → ')}`,
|
|
89
|
+
standardSection: 'MUST: Provider Nesting Order',
|
|
84
90
|
});
|
|
85
91
|
return issues;
|
|
86
92
|
}
|
|
@@ -97,7 +103,8 @@ function checkProviderNesting(consumingAppPath) {
|
|
|
97
103
|
}
|
|
98
104
|
|
|
99
105
|
const providerName = match[1];
|
|
100
|
-
|
|
106
|
+
const isRequired = requiredProviders.some(p => p.name === providerName || (p.altName && p.altName === providerName));
|
|
107
|
+
if (isRequired) {
|
|
101
108
|
providers.push({
|
|
102
109
|
name: providerName,
|
|
103
110
|
index: match.index,
|
|
@@ -106,10 +113,13 @@ function checkProviderNesting(consumingAppPath) {
|
|
|
106
113
|
}
|
|
107
114
|
}
|
|
108
115
|
|
|
109
|
-
// Check order
|
|
116
|
+
// Check order (normalize altName to canonical name for comparison)
|
|
110
117
|
if (providers.length > 0) {
|
|
111
118
|
const expectedOrder = requiredProviders.map(p => p.name);
|
|
112
|
-
const actualOrder = providers.map(p =>
|
|
119
|
+
const actualOrder = providers.map(p => {
|
|
120
|
+
const def = requiredProviders.find(r => r.name === p.name || r.altName === p.name);
|
|
121
|
+
return def ? def.name : p.name;
|
|
122
|
+
});
|
|
113
123
|
|
|
114
124
|
// Check if order matches
|
|
115
125
|
let orderCorrect = true;
|
|
@@ -129,6 +139,7 @@ function checkProviderNesting(consumingAppPath) {
|
|
|
129
139
|
code: getCodeSnippet(content, providers[0].index, 0, 200),
|
|
130
140
|
severity: 'error',
|
|
131
141
|
fix: `Reorder providers to: ${expectedOrder.join(' → ')}`,
|
|
142
|
+
standardSection: 'MUST: Provider Nesting Order',
|
|
132
143
|
});
|
|
133
144
|
}
|
|
134
145
|
}
|
|
@@ -164,6 +175,7 @@ function checkCoreStylesImport(consumingAppPath) {
|
|
|
164
175
|
message: 'app.css file not found. Required for pace-core styling.',
|
|
165
176
|
severity: 'error',
|
|
166
177
|
fix: 'Create src/app.css with @import "@jmruthers/pace-core/styles/core.css";',
|
|
178
|
+
standardSection: 'Core styles import (see Styling standard)',
|
|
167
179
|
});
|
|
168
180
|
return issues;
|
|
169
181
|
}
|
|
@@ -190,6 +202,7 @@ function checkCoreStylesImport(consumingAppPath) {
|
|
|
190
202
|
message: `Missing required import: ${name}`,
|
|
191
203
|
severity: 'error',
|
|
192
204
|
fix: `Add ${name}; to app.css`,
|
|
205
|
+
standardSection: 'Core styles import (see Styling standard)',
|
|
193
206
|
});
|
|
194
207
|
}
|
|
195
208
|
});
|
|
@@ -204,6 +217,7 @@ function checkCoreStylesImport(consumingAppPath) {
|
|
|
204
217
|
message: 'Missing @source directives for Tailwind v4 content scanning',
|
|
205
218
|
severity: 'warning',
|
|
206
219
|
fix: 'Add @source directives: @source "./**/*.{js,ts,jsx,tsx}"; @source "../node_modules/@jmruthers/pace-core/src/**/*.{js,ts,jsx,tsx}";',
|
|
220
|
+
standardSection: 'Core styles import (see Styling standard)',
|
|
207
221
|
});
|
|
208
222
|
}
|
|
209
223
|
|
|
@@ -244,6 +258,7 @@ function checkRBACSetup(consumingAppPath) {
|
|
|
244
258
|
message: 'main.tsx file not found. setupRBAC() must be called in main.tsx before app rendering.',
|
|
245
259
|
severity: 'error',
|
|
246
260
|
fix: 'Create src/main.tsx and call setupRBAC(supabase) before rendering the app.',
|
|
261
|
+
standardSection: 'MUST: Setup RBAC Before Use',
|
|
247
262
|
});
|
|
248
263
|
return issues;
|
|
249
264
|
}
|
|
@@ -265,6 +280,7 @@ function checkRBACSetup(consumingAppPath) {
|
|
|
265
280
|
message: 'setupRBAC() call not found. Must be called in main.tsx before app rendering.',
|
|
266
281
|
severity: 'error',
|
|
267
282
|
fix: 'Add: import { setupRBAC } from \'@jmruthers/pace-core/rbac\'; setupRBAC(supabase);',
|
|
283
|
+
standardSection: 'MUST: Setup RBAC Before Use',
|
|
268
284
|
});
|
|
269
285
|
} else {
|
|
270
286
|
// Check if it's called before React rendering
|
|
@@ -280,6 +296,7 @@ function checkRBACSetup(consumingAppPath) {
|
|
|
280
296
|
code: getCodeSnippet(content, setupRBACIndex),
|
|
281
297
|
severity: 'error',
|
|
282
298
|
fix: 'Move setupRBAC() call before createRoot() or render() call.',
|
|
299
|
+
standardSection: 'MUST: Setup RBAC Before Use',
|
|
283
300
|
});
|
|
284
301
|
}
|
|
285
302
|
}
|
|
@@ -337,6 +354,7 @@ function checkViteAliases(consumingAppPath) {
|
|
|
337
354
|
code: getCodeSnippet(content, match.index),
|
|
338
355
|
severity: 'error',
|
|
339
356
|
fix: `Remove this alias and use @jmruthers/pace-core/${paceCoreExport} directly`,
|
|
357
|
+
standardSection: 'MUST: Vite Configuration',
|
|
340
358
|
});
|
|
341
359
|
}
|
|
342
360
|
}
|
|
@@ -413,6 +431,7 @@ function checkSecureSupabaseClient(consumingAppPath) {
|
|
|
413
431
|
code: getCodeSnippet(content, match.index),
|
|
414
432
|
severity: 'error',
|
|
415
433
|
fix: 'Move createClient() call to main.tsx or lib/supabase.ts. Use useSecureSupabase() hook for queries.',
|
|
434
|
+
standardSection: 'MUST: Use Secure Supabase Client',
|
|
416
435
|
});
|
|
417
436
|
}
|
|
418
437
|
}
|
|
@@ -436,7 +455,8 @@ function checkCursorRules(consumingAppPath) {
|
|
|
436
455
|
line: 0,
|
|
437
456
|
message: 'Cursor rules directory not found. Cursor rules provide AI-assisted enforcement.',
|
|
438
457
|
severity: 'warning',
|
|
439
|
-
fix: 'Run: npm run setup
|
|
458
|
+
fix: 'Run: npm run setup',
|
|
459
|
+
standardSection: 'Step 3: Setup Cursor Rules',
|
|
440
460
|
});
|
|
441
461
|
return issues;
|
|
442
462
|
}
|
|
@@ -459,13 +479,62 @@ function checkCursorRules(consumingAppPath) {
|
|
|
459
479
|
line: 0,
|
|
460
480
|
message: `Missing pace-core cursor rules: ${missingRules.join(', ')}`,
|
|
461
481
|
severity: 'warning',
|
|
462
|
-
fix: 'Run: npm run setup
|
|
482
|
+
fix: 'Run: npm run setup',
|
|
483
|
+
standardSection: 'Step 3: Setup Cursor Rules',
|
|
463
484
|
});
|
|
464
485
|
}
|
|
465
486
|
|
|
466
487
|
return issues;
|
|
467
488
|
}
|
|
468
489
|
|
|
490
|
+
/**
|
|
491
|
+
* Check for global auth gate anti-pattern (redirect to /login when !isAuthenticated in a wrapper).
|
|
492
|
+
* MUST use public /login route and ProtectedRoute per route; MUST NOT wrap Routes in a component
|
|
493
|
+
* that redirects unauthenticated users to /login (races with post-login context updates).
|
|
494
|
+
*/
|
|
495
|
+
function checkAuthRoutingPattern(consumingAppPath) {
|
|
496
|
+
const issues = [];
|
|
497
|
+
const srcDir = path.join(consumingAppPath, 'src');
|
|
498
|
+
if (!fs.existsSync(srcDir)) {
|
|
499
|
+
return issues;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
const sourceFiles = findSourceFiles(srcDir, ['.tsx', '.jsx']);
|
|
503
|
+
const hasNavigateToLogin = /<Navigate\s+[^>]*to\s*=\s*\{?['"`]\/login['"`]?\}?/;
|
|
504
|
+
const hasAuthCheck = /(isAuthenticated|useUnifiedAuth\s*\(|useAuth\s*\()/;
|
|
505
|
+
const hasRedirectWhenUnauthenticated = /(!\s*isAuthenticated|isAuthenticated\s*===\s*false|!\s*user\b)/;
|
|
506
|
+
|
|
507
|
+
sourceFiles.forEach(filePath => {
|
|
508
|
+
const content = readFileSafe(filePath);
|
|
509
|
+
if (!content) return;
|
|
510
|
+
|
|
511
|
+
if (!hasNavigateToLogin.test(content)) return;
|
|
512
|
+
if (!hasAuthCheck.test(content)) return;
|
|
513
|
+
if (!hasRedirectWhenUnauthenticated.test(content)) return;
|
|
514
|
+
|
|
515
|
+
const normalizedPath = path.normalize(filePath);
|
|
516
|
+
if (normalizedPath.includes('ProtectedRoute') || normalizedPath.includes('packages' + path.sep + 'core')) return;
|
|
517
|
+
|
|
518
|
+
const relativePath = getRelativePath(filePath, consumingAppPath);
|
|
519
|
+
const navigateMatch = content.match(hasNavigateToLogin);
|
|
520
|
+
const line = navigateMatch ? getLineNumber(content, content.indexOf(navigateMatch[0])) : 1;
|
|
521
|
+
|
|
522
|
+
issues.push({
|
|
523
|
+
type: 'authRouting',
|
|
524
|
+
file: relativePath,
|
|
525
|
+
line,
|
|
526
|
+
message: 'Possible global auth gate: redirect to /login when not authenticated. This pattern can cause "login succeeds but redirect doesn\'t happen" or form reset.',
|
|
527
|
+
code: navigateMatch ? getCodeSnippet(content, content.indexOf(navigateMatch[0]), 0, 80) : undefined,
|
|
528
|
+
severity: 'error',
|
|
529
|
+
fix: 'Use a public /login route and wrap other routes in <Route element={<ProtectedRoute />}> (from @jmruthers/pace-core). Do not wrap <Routes> in a component that redirects when !isAuthenticated.',
|
|
530
|
+
standardSection: 'MUST: Auth routing',
|
|
531
|
+
details: 'See Authentication implementation guide: Critical: Auth routing pattern and troubleshooting "Login succeeds but redirect doesn\'t happen".',
|
|
532
|
+
});
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
return issues;
|
|
536
|
+
}
|
|
537
|
+
|
|
469
538
|
/**
|
|
470
539
|
* Check ESLint config setup
|
|
471
540
|
*/
|
|
@@ -490,7 +559,8 @@ function checkESLintConfig(consumingAppPath) {
|
|
|
490
559
|
line: 0,
|
|
491
560
|
message: 'ESLint config file not found. ESLint provides real-time compliance checking.',
|
|
492
561
|
severity: 'warning',
|
|
493
|
-
fix: 'Run: npm run setup
|
|
562
|
+
fix: 'Run: npm run setup',
|
|
563
|
+
standardSection: 'Step 2: Setup ESLint',
|
|
494
564
|
});
|
|
495
565
|
return issues;
|
|
496
566
|
}
|
|
@@ -514,7 +584,8 @@ function checkESLintConfig(consumingAppPath) {
|
|
|
514
584
|
line: 1,
|
|
515
585
|
message: 'ESLint config does not include pace-core config. pace-core ESLint rules provide real-time compliance checking.',
|
|
516
586
|
severity: 'warning',
|
|
517
|
-
fix: 'Run: npm run setup
|
|
587
|
+
fix: 'Run: npm run setup or manually add: import paceCoreConfig from \'@jmruthers/pace-core/eslint-config\';',
|
|
588
|
+
standardSection: 'Step 2: Setup ESLint',
|
|
518
589
|
});
|
|
519
590
|
}
|
|
520
591
|
|
|
@@ -524,20 +595,24 @@ function checkESLintConfig(consumingAppPath) {
|
|
|
524
595
|
/**
|
|
525
596
|
* Run audit for Standard 1: pace-core Compliance
|
|
526
597
|
* @param {string} consumingAppPath - Path to consuming app
|
|
598
|
+
* @param {{ isPaceCorePackage?: boolean }} [auditContext] - When isPaceCorePackage, skip app-only checks (main.tsx, app.css, rbacSetup, cursorRules, eslintConfig)
|
|
527
599
|
* @returns {object} - Audit results with issues array
|
|
528
600
|
*/
|
|
529
|
-
function runStandard1Audit(consumingAppPath) {
|
|
601
|
+
function runStandard1Audit(consumingAppPath, auditContext = {}) {
|
|
530
602
|
const issues = [];
|
|
531
|
-
|
|
603
|
+
const isPaceCorePackage = auditContext.isPaceCorePackage === true;
|
|
604
|
+
|
|
532
605
|
try {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
606
|
+
if (!isPaceCorePackage) {
|
|
607
|
+
issues.push(...checkProviderNesting(consumingAppPath));
|
|
608
|
+
issues.push(...checkCoreStylesImport(consumingAppPath));
|
|
609
|
+
issues.push(...checkRBACSetup(consumingAppPath));
|
|
610
|
+
issues.push(...checkCursorRules(consumingAppPath));
|
|
611
|
+
issues.push(...checkESLintConfig(consumingAppPath));
|
|
612
|
+
}
|
|
537
613
|
issues.push(...checkViteAliases(consumingAppPath));
|
|
538
614
|
issues.push(...checkSecureSupabaseClient(consumingAppPath));
|
|
539
|
-
issues.push(...
|
|
540
|
-
issues.push(...checkESLintConfig(consumingAppPath));
|
|
615
|
+
issues.push(...checkAuthRoutingPattern(consumingAppPath));
|
|
541
616
|
} catch (error) {
|
|
542
617
|
return {
|
|
543
618
|
standard: '01-pace-core-compliance',
|
|
@@ -41,6 +41,7 @@ function checkDirectoryStructure(consumingAppPath) {
|
|
|
41
41
|
message: `Required directory missing: ${dirPath} (${description})`,
|
|
42
42
|
severity: 'error',
|
|
43
43
|
fix: `Create ${dirPath}/ directory`,
|
|
44
|
+
standardSection: 'Standard Directory Structure',
|
|
44
45
|
});
|
|
45
46
|
}
|
|
46
47
|
});
|
|
@@ -72,6 +73,7 @@ function checkConfigFiles(consumingAppPath) {
|
|
|
72
73
|
message: `Required configuration file missing: ${name} (${description})`,
|
|
73
74
|
severity: 'error',
|
|
74
75
|
fix: `Create ${name} file`,
|
|
76
|
+
standardSection: 'Configuration Files',
|
|
75
77
|
});
|
|
76
78
|
}
|
|
77
79
|
});
|
|
@@ -119,6 +121,7 @@ function checkImportPaths(consumingAppPath) {
|
|
|
119
121
|
message: 'tsconfig.json missing paths configuration. Consider adding path aliases for cleaner imports.',
|
|
120
122
|
severity: 'info',
|
|
121
123
|
fix: 'Add paths configuration: { "compilerOptions": { "paths": { "@/*": ["./src/*"] } } }',
|
|
124
|
+
standardSection: 'Import Path Configuration',
|
|
122
125
|
});
|
|
123
126
|
}
|
|
124
127
|
|
|
@@ -190,6 +193,7 @@ function checkTestColocation(consumingAppPath) {
|
|
|
190
193
|
message: `Test file is in a test directory but should be colocated with source file. Move to ${parentDir}`,
|
|
191
194
|
severity: 'warning',
|
|
192
195
|
fix: `Move test file to ${parentDir} to colocate with source file`,
|
|
196
|
+
standardSection: 'Testing Structure (Test Colocation)',
|
|
193
197
|
});
|
|
194
198
|
}
|
|
195
199
|
}
|
|
@@ -220,6 +224,7 @@ function checkFeatureBasedOrganization(consumingAppPath) {
|
|
|
220
224
|
message: 'Domain-based organization (src/domains/) is not allowed. Use feature-based organization instead (src/components/[feature]/, src/hooks/[feature]/, etc.)',
|
|
221
225
|
severity: 'error',
|
|
222
226
|
fix: 'Reorganize to feature-based structure: move components from src/domains/[domain]/components/ to src/components/[domain]/, hooks to src/hooks/[domain]/, etc.',
|
|
227
|
+
standardSection: 'Component Organization / File Organization Standard',
|
|
223
228
|
});
|
|
224
229
|
}
|
|
225
230
|
|
|
@@ -252,6 +257,7 @@ function checkFeatureBasedOrganization(consumingAppPath) {
|
|
|
252
257
|
message: `Components organized by type (${foundTypeBased.join(', ')}) instead of feature. Use pace-core components for UI primitives and organize app components by feature.`,
|
|
253
258
|
severity: 'error',
|
|
254
259
|
fix: `Reorganize components by feature. Use pace-core for ${foundTypeBased.join(', ')} components. Move feature-specific components to src/components/[feature]/`,
|
|
260
|
+
standardSection: 'Component Organization / File Organization Standard',
|
|
255
261
|
});
|
|
256
262
|
}
|
|
257
263
|
}
|
|
@@ -275,17 +281,21 @@ function checkSupabaseStructure(consumingAppPath) {
|
|
|
275
281
|
/**
|
|
276
282
|
* Run audit for Standard 2: Project Structure
|
|
277
283
|
* @param {string} consumingAppPath - Path to consuming app
|
|
284
|
+
* @param {{ isPaceCorePackage?: boolean }} [auditContext] - When isPaceCorePackage, skip organizationPattern (library organizes by type by design)
|
|
278
285
|
* @returns {object} - Audit results with issues array
|
|
279
286
|
*/
|
|
280
|
-
function runStandard2Audit(consumingAppPath) {
|
|
287
|
+
function runStandard2Audit(consumingAppPath, auditContext = {}) {
|
|
281
288
|
const issues = [];
|
|
282
|
-
|
|
289
|
+
const isPaceCorePackage = auditContext.isPaceCorePackage === true;
|
|
290
|
+
|
|
283
291
|
try {
|
|
284
292
|
issues.push(...checkDirectoryStructure(consumingAppPath));
|
|
285
293
|
issues.push(...checkConfigFiles(consumingAppPath));
|
|
286
294
|
issues.push(...checkImportPaths(consumingAppPath));
|
|
287
295
|
issues.push(...checkTestColocation(consumingAppPath));
|
|
288
|
-
|
|
296
|
+
if (!isPaceCorePackage) {
|
|
297
|
+
issues.push(...checkFeatureBasedOrganization(consumingAppPath));
|
|
298
|
+
}
|
|
289
299
|
issues.push(...checkSupabaseStructure(consumingAppPath));
|
|
290
300
|
} catch (error) {
|
|
291
301
|
return {
|
|
@@ -23,8 +23,8 @@ function isTestFile(filePath) {
|
|
|
23
23
|
const fileNameLower = fileName.toLowerCase();
|
|
24
24
|
const filePathLower = filePath.toLowerCase();
|
|
25
25
|
|
|
26
|
-
// Standard test file patterns
|
|
27
|
-
if (filePath.includes('.test.') || filePath.includes('.spec.')) {
|
|
26
|
+
// Standard test file patterns and test-utils
|
|
27
|
+
if (filePath.includes('.test.') || filePath.includes('.spec.') || filePath.includes('test-utils')) {
|
|
28
28
|
return true;
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -99,7 +99,7 @@ function checkComponentBoundaries(consumingAppPath) {
|
|
|
99
99
|
return isComponentDir && isComponentFile;
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
-
// For data fetching checks,
|
|
102
|
+
// For data fetching checks, include .tsx and .ts under pages/components but exclude hook files
|
|
103
103
|
const filesForDataFetchingCheck = findSourceFiles(srcDir).filter(file => {
|
|
104
104
|
// Skip all test files
|
|
105
105
|
if (isTestFile(file)) {
|
|
@@ -110,6 +110,13 @@ function checkComponentBoundaries(consumingAppPath) {
|
|
|
110
110
|
const isComponentDir = dir.includes('/components/') || dir.includes('/pages/');
|
|
111
111
|
const isComponentFile = file.endsWith('.tsx') || file.endsWith('.ts');
|
|
112
112
|
|
|
113
|
+
// Exclude hooks: files under hooks/ or whose basename starts with 'use'
|
|
114
|
+
const basename = path.basename(file, path.extname(file));
|
|
115
|
+
const isHookFile = dir.includes('/hooks/') || basename.startsWith('use');
|
|
116
|
+
if (isHookFile) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
|
|
113
120
|
return isComponentDir && isComponentFile;
|
|
114
121
|
});
|
|
115
122
|
|
|
@@ -149,6 +156,7 @@ function checkComponentBoundaries(consumingAppPath) {
|
|
|
149
156
|
code: getCodeSnippet(content, index),
|
|
150
157
|
severity: 'warning',
|
|
151
158
|
fix: 'Extract data fetching logic to a custom hook (e.g., useEventData)',
|
|
159
|
+
standardSection: 'Component Design Principles / SOLID (Single Responsibility)',
|
|
152
160
|
});
|
|
153
161
|
}
|
|
154
162
|
}
|
|
@@ -239,6 +247,7 @@ function checkComponentBoundaries(consumingAppPath) {
|
|
|
239
247
|
message: 'Complex business logic detected in component. Consider extracting to a hook or utility function.',
|
|
240
248
|
severity: 'info',
|
|
241
249
|
fix: 'Extract business logic to a custom hook or utility function',
|
|
250
|
+
standardSection: 'Component Design Principles (UI Primitives Only, Stateless When Possible)',
|
|
242
251
|
});
|
|
243
252
|
}
|
|
244
253
|
}
|
|
@@ -247,6 +256,68 @@ function checkComponentBoundaries(consumingAppPath) {
|
|
|
247
256
|
return issues;
|
|
248
257
|
}
|
|
249
258
|
|
|
259
|
+
/** Thresholds for ISP heuristic (see Standard 3).
|
|
260
|
+
* Line limits and named-export limit are enforced by ESLint only; this audit does not check them. */
|
|
261
|
+
const INTERFACE_MEMBER_LIMIT = 30;
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* ISP heuristic: flag interfaces/types with many members.
|
|
265
|
+
* Best-effort only; uses simple brace matching. See standard "Limitations".
|
|
266
|
+
*/
|
|
267
|
+
function checkLargeInterfaceHeuristic(consumingAppPath) {
|
|
268
|
+
const issues = [];
|
|
269
|
+
const srcDir = path.join(consumingAppPath, 'src');
|
|
270
|
+
if (!require('fs').existsSync(srcDir)) {
|
|
271
|
+
return issues;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const sourceFiles = findSourceFiles(srcDir).filter(file =>
|
|
275
|
+
!isTestFile(file) &&
|
|
276
|
+
(file.endsWith('.ts') || file.endsWith('.tsx')) &&
|
|
277
|
+
!file.includes('.generated.')
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
sourceFiles.forEach(filePath => {
|
|
281
|
+
const content = readFileSafe(filePath);
|
|
282
|
+
if (!content) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const re = /\b(?:interface|type)\s+\w+\s*(?:=\s*)?\{/g;
|
|
287
|
+
let m;
|
|
288
|
+
while ((m = re.exec(content)) !== null) {
|
|
289
|
+
const start = m.index + m[0].length - 1;
|
|
290
|
+
let depth = 1;
|
|
291
|
+
let i = start + 1;
|
|
292
|
+
for (; i < content.length; i++) {
|
|
293
|
+
if (content[i] === '{') {
|
|
294
|
+
depth++;
|
|
295
|
+
} else if (content[i] === '}') {
|
|
296
|
+
depth--;
|
|
297
|
+
if (depth === 0) {
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
const block = content.substring(start, i + 1);
|
|
303
|
+
const memberCount = (block.match(/\w+\s*[?:]?\s*:/g) || []).length + (block.match(/\w+\s*\(/g) || []).length;
|
|
304
|
+
if (memberCount > INTERFACE_MEMBER_LIMIT) {
|
|
305
|
+
issues.push({
|
|
306
|
+
type: 'componentBoundary',
|
|
307
|
+
file: getRelativePath(filePath, consumingAppPath),
|
|
308
|
+
line: getLineNumber(content, m.index),
|
|
309
|
+
message: `Interface/type has ${memberCount} members (threshold ${INTERFACE_MEMBER_LIMIT}). Consider interface segregation; focused interfaces.`,
|
|
310
|
+
severity: 'info',
|
|
311
|
+
fix: 'Split into smaller, focused interfaces; see Standard 3 SOLID (ISP heuristic).',
|
|
312
|
+
standardSection: 'How we check SOLID (ISP heuristic)',
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
return issues;
|
|
319
|
+
}
|
|
320
|
+
|
|
250
321
|
/**
|
|
251
322
|
* Check ApiResult shape usage (cross-file validation)
|
|
252
323
|
*/
|
|
@@ -313,6 +384,7 @@ function checkApiResultUsage(consumingAppPath) {
|
|
|
313
384
|
code: getCodeSnippet(content, functionIndex),
|
|
314
385
|
severity: 'info',
|
|
315
386
|
fix: 'Use ApiResult<T> type: type ApiResult<T> = { ok: true; data: T } | { ok: false; error: ApiError }',
|
|
387
|
+
standardSection: 'API Design Principles (Type-Safe Results)',
|
|
316
388
|
});
|
|
317
389
|
}
|
|
318
390
|
});
|
|
@@ -324,13 +396,15 @@ function checkApiResultUsage(consumingAppPath) {
|
|
|
324
396
|
/**
|
|
325
397
|
* Run audit for Standard 3: Architecture
|
|
326
398
|
* @param {string} consumingAppPath - Path to consuming app
|
|
399
|
+
* @param {{ isPaceCorePackage?: boolean }} [auditContext] - Optional context (interface member limit already relaxed for all)
|
|
327
400
|
* @returns {object} - Audit results with issues array
|
|
328
401
|
*/
|
|
329
|
-
function runStandard3Audit(consumingAppPath) {
|
|
402
|
+
function runStandard3Audit(consumingAppPath, auditContext = {}) {
|
|
330
403
|
const issues = [];
|
|
331
404
|
|
|
332
405
|
try {
|
|
333
406
|
issues.push(...checkComponentBoundaries(consumingAppPath));
|
|
407
|
+
issues.push(...checkLargeInterfaceHeuristic(consumingAppPath));
|
|
334
408
|
issues.push(...checkApiResultUsage(consumingAppPath));
|
|
335
409
|
} catch (error) {
|
|
336
410
|
return {
|
|
@@ -31,6 +31,7 @@ function checkTypeScriptConfig(consumingAppPath) {
|
|
|
31
31
|
message: 'tsconfig.json not found. TypeScript strict mode must be enabled.',
|
|
32
32
|
severity: 'error',
|
|
33
33
|
fix: 'Create tsconfig.json with "strict": true in compilerOptions.',
|
|
34
|
+
standardSection: 'TypeScript Rules (Avoid Implicit any / tsconfig)',
|
|
34
35
|
});
|
|
35
36
|
return issues;
|
|
36
37
|
}
|
|
@@ -63,9 +64,10 @@ function checkTypeScriptConfig(consumingAppPath) {
|
|
|
63
64
|
message: 'TypeScript strict mode not enabled. Must set "strict": true in compilerOptions.',
|
|
64
65
|
severity: 'error',
|
|
65
66
|
fix: 'Set "strict": true in tsconfig.json compilerOptions.',
|
|
67
|
+
standardSection: 'TypeScript Rules (tsconfig strict mode)',
|
|
66
68
|
});
|
|
67
69
|
}
|
|
68
|
-
|
|
70
|
+
|
|
69
71
|
// Check for noImplicitAny
|
|
70
72
|
if (compilerOptions.noImplicitAny !== true && compilerOptions.strict !== true) {
|
|
71
73
|
issues.push({
|
|
@@ -75,6 +77,7 @@ function checkTypeScriptConfig(consumingAppPath) {
|
|
|
75
77
|
message: 'noImplicitAny not enabled. Should set "noImplicitAny": true in compilerOptions (or enable strict mode).',
|
|
76
78
|
severity: 'error',
|
|
77
79
|
fix: 'Set "noImplicitAny": true in tsconfig.json compilerOptions (or enable strict mode).',
|
|
80
|
+
standardSection: 'TypeScript Rules (Avoid Implicit any)',
|
|
78
81
|
});
|
|
79
82
|
}
|
|
80
83
|
|
|
@@ -113,6 +116,7 @@ function checkTestCoverageConfig(consumingAppPath) {
|
|
|
113
116
|
message: 'vitest.config.ts missing coverage configuration. Consider adding coverage thresholds.',
|
|
114
117
|
severity: 'info',
|
|
115
118
|
fix: 'Add coverage configuration: coverage: { provider: "v8", reporter: ["text", "json", "html"] }',
|
|
119
|
+
standardSection: 'Test coverage config (see Testing standard)',
|
|
116
120
|
});
|
|
117
121
|
}
|
|
118
122
|
}
|
|
@@ -176,6 +180,7 @@ function checkConsoleLogging(consumingAppPath) {
|
|
|
176
180
|
message: `Excessive ${name} usage detected (${validMatches.length} instances). Consider removing debug logs or using a proper logging library.`,
|
|
177
181
|
severity: 'warning',
|
|
178
182
|
fix: `Remove or replace ${name} statements. Use a logging library or remove debug logs before production.`,
|
|
183
|
+
standardSection: 'Forbidden Patterns / code hygiene',
|
|
179
184
|
});
|
|
180
185
|
}
|
|
181
186
|
});
|
|
@@ -197,6 +202,7 @@ function checkConsoleLogging(consumingAppPath) {
|
|
|
197
202
|
message: `Debug console logging detected (${validDebugMatches.length} instances). Debug logs should be removed or disabled in production.`,
|
|
198
203
|
severity: 'warning',
|
|
199
204
|
fix: 'Remove debug console.log statements or use environment-based logging that can be disabled in production.',
|
|
205
|
+
standardSection: 'Forbidden Patterns / code hygiene',
|
|
200
206
|
});
|
|
201
207
|
}
|
|
202
208
|
});
|
|
@@ -207,9 +213,10 @@ function checkConsoleLogging(consumingAppPath) {
|
|
|
207
213
|
/**
|
|
208
214
|
* Run audit for Standard 4: Code Quality
|
|
209
215
|
* @param {string} consumingAppPath - Path to consuming app
|
|
216
|
+
* @param {{ isPaceCorePackage?: boolean }} [auditContext] - Optional context (unused)
|
|
210
217
|
* @returns {object} - Audit results with issues array
|
|
211
218
|
*/
|
|
212
|
-
function runStandard4Audit(consumingAppPath) {
|
|
219
|
+
function runStandard4Audit(consumingAppPath, auditContext = {}) {
|
|
213
220
|
const issues = [];
|
|
214
221
|
|
|
215
222
|
try {
|