@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
|
@@ -67,13 +67,13 @@ describe('formatDate', () => {
|
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
it('returns empty string for null input', () => {
|
|
70
|
-
// @ts-
|
|
70
|
+
// @ts-expect-error - Testing invalid input (null)
|
|
71
71
|
const result = formatDate(null);
|
|
72
72
|
expect(result).toBe('');
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
it('returns empty string for undefined input', () => {
|
|
76
|
-
// @ts-
|
|
76
|
+
// @ts-expect-error - Testing invalid input (undefined)
|
|
77
77
|
const result = formatDate(undefined);
|
|
78
78
|
expect(result).toBe('');
|
|
79
79
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file Google Places API Utilities Tests
|
|
3
3
|
* @package @jmruthers/pace-core
|
|
4
|
-
* @module Utils/GooglePlaces
|
|
4
|
+
* @module Utils/GooglePlaces
|
|
5
5
|
* @since 0.1.0
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -47,7 +47,7 @@ vi.mock('./loadGoogleMapsScript', () => {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
return {
|
|
50
|
-
loadGoogleMapsScript: vi.fn().mockResolvedValue(undefined),
|
|
50
|
+
loadGoogleMapsScript: vi.fn().mockResolvedValue({ ok: true, data: undefined }),
|
|
51
51
|
isGoogleMapsLoaded: vi.fn(() => {
|
|
52
52
|
const win = typeof window !== 'undefined' ? window : (global as any).window;
|
|
53
53
|
return !!(win?.google?.maps?.places);
|
|
@@ -154,24 +154,29 @@ describe('Google Places API Utilities', () => {
|
|
|
154
154
|
|
|
155
155
|
const result = await fetchPlaceAutocomplete('123 Main', mockApiKey);
|
|
156
156
|
|
|
157
|
-
expect(result).
|
|
158
|
-
expect(result
|
|
159
|
-
expect(result[0].
|
|
157
|
+
expect(result.ok).toBe(true);
|
|
158
|
+
expect(result.data).toHaveLength(1);
|
|
159
|
+
expect(result.data[0].place_id).toBe('ChIJ123');
|
|
160
|
+
expect(result.data[0].description).toBe('123 Main St, Melbourne VIC, Australia');
|
|
160
161
|
expect(mockAutocompleteService.getPlacePredictions).toHaveBeenCalled();
|
|
161
162
|
});
|
|
162
163
|
|
|
163
|
-
it('returns empty array for empty query', async () => {
|
|
164
|
+
it('returns ok with empty array for empty query', async () => {
|
|
164
165
|
const result = await fetchPlaceAutocomplete('', mockApiKey);
|
|
165
|
-
expect(result).
|
|
166
|
+
expect(result.ok).toBe(true);
|
|
167
|
+
expect(result.data).toEqual([]);
|
|
166
168
|
});
|
|
167
169
|
|
|
168
|
-
it('returns empty array for whitespace-only query', async () => {
|
|
170
|
+
it('returns ok with empty array for whitespace-only query', async () => {
|
|
169
171
|
const result = await fetchPlaceAutocomplete(' ', mockApiKey);
|
|
170
|
-
expect(result).
|
|
172
|
+
expect(result.ok).toBe(true);
|
|
173
|
+
expect(result.data).toEqual([]);
|
|
171
174
|
});
|
|
172
175
|
|
|
173
|
-
it('
|
|
174
|
-
await
|
|
176
|
+
it('returns err when API key is missing', async () => {
|
|
177
|
+
const result = await fetchPlaceAutocomplete('123 Main', '');
|
|
178
|
+
expect(result.ok).toBe(false);
|
|
179
|
+
expect(result.error.message).toContain('API key is required');
|
|
175
180
|
});
|
|
176
181
|
|
|
177
182
|
it('handles ZERO_RESULTS status', { timeout: 5000 }, async () => {
|
|
@@ -180,7 +185,8 @@ describe('Google Places API Utilities', () => {
|
|
|
180
185
|
});
|
|
181
186
|
|
|
182
187
|
const result = await fetchPlaceAutocomplete('nonexistent', mockApiKey);
|
|
183
|
-
expect(result).
|
|
188
|
+
expect(result.ok).toBe(true);
|
|
189
|
+
expect(result.data).toEqual([]);
|
|
184
190
|
});
|
|
185
191
|
|
|
186
192
|
it('handles REQUEST_DENIED status', { timeout: 5000 }, async () => {
|
|
@@ -188,7 +194,9 @@ describe('Google Places API Utilities', () => {
|
|
|
188
194
|
callback(null, 'REQUEST_DENIED');
|
|
189
195
|
});
|
|
190
196
|
|
|
191
|
-
await
|
|
197
|
+
const result = await fetchPlaceAutocomplete('123 Main', mockApiKey);
|
|
198
|
+
expect(result.ok).toBe(false);
|
|
199
|
+
expect(result.error.message).toContain('REQUEST_DENIED');
|
|
192
200
|
});
|
|
193
201
|
|
|
194
202
|
it('handles errors', { timeout: 5000 }, async () => {
|
|
@@ -196,7 +204,9 @@ describe('Google Places API Utilities', () => {
|
|
|
196
204
|
callback(null, 'INVALID_REQUEST');
|
|
197
205
|
});
|
|
198
206
|
|
|
199
|
-
await
|
|
207
|
+
const result = await fetchPlaceAutocomplete('123 Main', mockApiKey);
|
|
208
|
+
expect(result.ok).toBe(false);
|
|
209
|
+
expect(result.error.message).toContain('INVALID_REQUEST');
|
|
200
210
|
});
|
|
201
211
|
|
|
202
212
|
it('includes optional parameters in request', { timeout: 5000 }, async () => {
|
|
@@ -244,7 +254,8 @@ describe('Google Places API Utilities', () => {
|
|
|
244
254
|
const result = await fetchPlaceAutocomplete('Main', mockApiKey);
|
|
245
255
|
|
|
246
256
|
expect(fetchMock).toHaveBeenCalledWith({ input: 'Main' });
|
|
247
|
-
expect(result).
|
|
257
|
+
expect(result.ok).toBe(true);
|
|
258
|
+
expect(result.data).toEqual([
|
|
248
259
|
{
|
|
249
260
|
description: 'Main St',
|
|
250
261
|
place_id: 'place-new',
|
|
@@ -261,9 +272,9 @@ describe('Google Places API Utilities', () => {
|
|
|
261
272
|
(window as any).google.maps.places.AutocompleteSuggestion = mockAutocompleteSuggestion as any;
|
|
262
273
|
mockAutocompleteSuggestion.fetchAutocompleteSuggestions.mockRejectedValue(new Error('network down'));
|
|
263
274
|
|
|
264
|
-
await
|
|
265
|
-
|
|
266
|
-
);
|
|
275
|
+
const result = await fetchPlaceAutocomplete('Main', mockApiKey);
|
|
276
|
+
expect(result.ok).toBe(false);
|
|
277
|
+
expect(result.error.message).toContain('network down');
|
|
267
278
|
});
|
|
268
279
|
|
|
269
280
|
it('builds a new API request with location bias and region codes', async () => {
|
|
@@ -290,22 +301,24 @@ describe('Google Places API Utilities', () => {
|
|
|
290
301
|
});
|
|
291
302
|
});
|
|
292
303
|
|
|
293
|
-
it('returns empty array when new API suggestions are empty', async () => {
|
|
304
|
+
it('returns ok with empty array when new API suggestions are empty', async () => {
|
|
294
305
|
(window as any).google.maps.places.AutocompleteSuggestion = mockAutocompleteSuggestion as any;
|
|
295
306
|
mockAutocompleteSuggestion.fetchAutocompleteSuggestions.mockResolvedValue({ suggestions: [] });
|
|
296
307
|
|
|
297
308
|
const result = await fetchPlaceAutocomplete('Main', mockApiKey);
|
|
298
309
|
|
|
299
|
-
expect(result).
|
|
310
|
+
expect(result.ok).toBe(true);
|
|
311
|
+
expect(result.data).toEqual([]);
|
|
300
312
|
});
|
|
301
313
|
|
|
302
|
-
it('
|
|
314
|
+
it('returns err when Google Places library is unavailable', async () => {
|
|
303
315
|
const originalPlaces = (window as any).google.maps.places;
|
|
304
316
|
(window as any).google.maps.places = undefined;
|
|
317
|
+
vi.mocked(loadGoogleMapsScript).mockResolvedValueOnce({ ok: true, data: undefined });
|
|
305
318
|
|
|
306
|
-
await
|
|
307
|
-
|
|
308
|
-
);
|
|
319
|
+
const result = await fetchPlaceAutocomplete('123 Main', mockApiKey);
|
|
320
|
+
expect(result.ok).toBe(false);
|
|
321
|
+
expect(result.error.message).toContain('Places library not available');
|
|
309
322
|
|
|
310
323
|
(window as any).google.maps.places = originalPlaces;
|
|
311
324
|
});
|
|
@@ -315,7 +328,7 @@ describe('Google Places API Utilities', () => {
|
|
|
315
328
|
const mockedIsLoaded = vi.mocked(isGoogleMapsLoaded);
|
|
316
329
|
|
|
317
330
|
mockedIsLoaded.mockReturnValueOnce(false);
|
|
318
|
-
mockedLoadScript.mockResolvedValueOnce();
|
|
331
|
+
mockedLoadScript.mockResolvedValueOnce({ ok: true, data: undefined });
|
|
319
332
|
|
|
320
333
|
(window as any).google.maps.places.AutocompleteSuggestion = mockAutocompleteSuggestion as any;
|
|
321
334
|
mockAutocompleteSuggestion.fetchAutocompleteSuggestions.mockResolvedValue({ suggestions: [] });
|
|
@@ -351,7 +364,9 @@ describe('Google Places API Utilities', () => {
|
|
|
351
364
|
const [result1, result2] = await Promise.all([promise1, promise2]);
|
|
352
365
|
|
|
353
366
|
expect(mockAutocompleteService.getPlacePredictions).toHaveBeenCalledTimes(1);
|
|
354
|
-
expect(result1).
|
|
367
|
+
expect(result1.ok).toBe(true);
|
|
368
|
+
expect(result2.ok).toBe(true);
|
|
369
|
+
expect(result1.data).toEqual(result2.data);
|
|
355
370
|
|
|
356
371
|
vi.useRealTimers();
|
|
357
372
|
});
|
|
@@ -384,18 +399,23 @@ describe('Google Places API Utilities', () => {
|
|
|
384
399
|
|
|
385
400
|
const result = await fetchPlaceDetails('ChIJ123', mockApiKey);
|
|
386
401
|
|
|
387
|
-
expect(result.
|
|
388
|
-
expect(result.
|
|
389
|
-
expect(result.
|
|
402
|
+
expect(result.ok).toBe(true);
|
|
403
|
+
expect(result.data.place_id).toBe('ChIJ123');
|
|
404
|
+
expect(result.data.formatted_address).toBe('123 Main St, Melbourne VIC 3000, Australia');
|
|
405
|
+
expect(result.data.geometry?.location?.lat()).toBe(-37.8136);
|
|
390
406
|
expect(mockPlacesService.getDetails).toHaveBeenCalled();
|
|
391
407
|
});
|
|
392
408
|
|
|
393
|
-
it('
|
|
394
|
-
await
|
|
409
|
+
it('returns err when place_id is missing', async () => {
|
|
410
|
+
const result = await fetchPlaceDetails('', mockApiKey);
|
|
411
|
+
expect(result.ok).toBe(false);
|
|
412
|
+
expect(result.error.message).toContain('Place ID is required');
|
|
395
413
|
});
|
|
396
414
|
|
|
397
|
-
it('
|
|
398
|
-
await
|
|
415
|
+
it('returns err when API key is missing', async () => {
|
|
416
|
+
const result = await fetchPlaceDetails('ChIJ123', '');
|
|
417
|
+
expect(result.ok).toBe(false);
|
|
418
|
+
expect(result.error.message).toContain('API key is required');
|
|
399
419
|
});
|
|
400
420
|
|
|
401
421
|
it('handles NOT_FOUND status', { timeout: 5000 }, async () => {
|
|
@@ -403,17 +423,19 @@ describe('Google Places API Utilities', () => {
|
|
|
403
423
|
callback(null, 'NOT_FOUND');
|
|
404
424
|
});
|
|
405
425
|
|
|
406
|
-
await
|
|
426
|
+
const result = await fetchPlaceDetails('invalid', mockApiKey);
|
|
427
|
+
expect(result.ok).toBe(false);
|
|
428
|
+
expect(result.error.message).toContain('Place not found');
|
|
407
429
|
});
|
|
408
430
|
|
|
409
|
-
it('
|
|
431
|
+
it('returns err when Places Service returns an error status', { timeout: 5000 }, async () => {
|
|
410
432
|
mockPlacesService.getDetails.mockImplementation((request, callback) => {
|
|
411
433
|
callback(null, 'OVER_QUERY_LIMIT');
|
|
412
434
|
});
|
|
413
435
|
|
|
414
|
-
await
|
|
415
|
-
|
|
416
|
-
);
|
|
436
|
+
const result = await fetchPlaceDetails('ChIJ123', mockApiKey);
|
|
437
|
+
expect(result.ok).toBe(false);
|
|
438
|
+
expect(result.error.message).toContain('OVER_QUERY_LIMIT');
|
|
417
439
|
});
|
|
418
440
|
});
|
|
419
441
|
|
|
@@ -550,33 +572,33 @@ describe('Google Places API Utilities', () => {
|
|
|
550
572
|
|
|
551
573
|
const result = await getAddressByPlaceId('ChIJ123', mockApiKey);
|
|
552
574
|
|
|
553
|
-
expect(result).
|
|
554
|
-
expect(result
|
|
555
|
-
expect(result?.
|
|
575
|
+
expect(result.ok).toBe(true);
|
|
576
|
+
expect(result.data).not.toBeNull();
|
|
577
|
+
expect(result.data?.place_id).toBe('ChIJ123');
|
|
578
|
+
expect(result.data?.full_address).toBe('123 Main St, Melbourne VIC 3000, Australia');
|
|
556
579
|
});
|
|
557
580
|
|
|
558
|
-
it('returns
|
|
581
|
+
it('returns err on error', { timeout: 5000 }, async () => {
|
|
559
582
|
mockPlacesService.getDetails.mockImplementation((request, callback) => {
|
|
560
583
|
callback(null, 'NOT_FOUND');
|
|
561
584
|
});
|
|
562
585
|
|
|
563
586
|
const result = await getAddressByPlaceId('ChIJ123', mockApiKey);
|
|
564
|
-
expect(result).
|
|
587
|
+
expect(result.ok).toBe(false);
|
|
588
|
+
expect(result.error.message).toContain('Place not found');
|
|
565
589
|
});
|
|
566
590
|
|
|
567
|
-
it('returns
|
|
568
|
-
// Clear any cached requests first
|
|
591
|
+
it('returns err when fetchPlaceDetails returns err', { timeout: 10000 }, async () => {
|
|
569
592
|
clearInFlightRequests();
|
|
570
593
|
|
|
571
|
-
// Mock the PlacesService to throw an error
|
|
572
594
|
mockPlacesService.getDetails.mockImplementation((request, callback) => {
|
|
573
|
-
// Simulate an error by calling callback with error status
|
|
574
595
|
callback(null, 'INVALID_REQUEST');
|
|
575
596
|
});
|
|
576
597
|
|
|
577
598
|
const result = await googlePlacesUtils.getAddressByPlaceId('ChIJ123', mockApiKey);
|
|
578
599
|
|
|
579
|
-
expect(result).
|
|
600
|
+
expect(result.ok).toBe(false);
|
|
601
|
+
expect(result.error.message).toContain('INVALID_REQUEST');
|
|
580
602
|
});
|
|
581
603
|
});
|
|
582
604
|
});
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import { getOrCreateRequest } from '../request-deduplication';
|
|
19
|
+
import { ok, err, type ApiResult, type ApiError } from '../../types/api-result';
|
|
19
20
|
import { createLogger } from '../core/logger';
|
|
20
21
|
import { loadGoogleMapsScript, isGoogleMapsLoaded } from './loadGoogleMapsScript';
|
|
21
22
|
import type {
|
|
@@ -26,6 +27,14 @@ import type {
|
|
|
26
27
|
|
|
27
28
|
const log = createLogger('google-places');
|
|
28
29
|
|
|
30
|
+
function toApiError(error: unknown): ApiError {
|
|
31
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
32
|
+
const code = error instanceof Error && (error as Error & { code?: string }).code
|
|
33
|
+
? (error as Error & { code: string }).code
|
|
34
|
+
: 'GOOGLE_PLACES_ERROR';
|
|
35
|
+
return { code, message };
|
|
36
|
+
}
|
|
37
|
+
|
|
29
38
|
// Google Maps types are defined in loadGoogleMapsScript.ts
|
|
30
39
|
|
|
31
40
|
/**
|
|
@@ -34,33 +43,36 @@ const log = createLogger('google-places');
|
|
|
34
43
|
* @param query - Search query string
|
|
35
44
|
* @param apiKey - Google Places API key
|
|
36
45
|
* @param options - Optional autocomplete options
|
|
37
|
-
* @returns Promise resolving to array of predictions
|
|
46
|
+
* @returns Promise resolving to ApiResult with array of predictions
|
|
38
47
|
*
|
|
39
48
|
* @example
|
|
40
49
|
* ```ts
|
|
41
|
-
* const
|
|
50
|
+
* const result = await fetchPlaceAutocomplete(
|
|
42
51
|
* '123 Main St',
|
|
43
52
|
* 'your-api-key',
|
|
44
53
|
* { components: 'country:au' }
|
|
45
54
|
* );
|
|
55
|
+
* if (result.ok) console.log(result.data);
|
|
46
56
|
* ```
|
|
47
57
|
*/
|
|
48
58
|
export async function fetchPlaceAutocomplete(
|
|
49
59
|
query: string,
|
|
50
60
|
apiKey: string,
|
|
51
61
|
options?: AutocompleteOptions
|
|
52
|
-
): Promise<GooglePlaceAutocompletePrediction[]
|
|
62
|
+
): Promise<ApiResult<GooglePlaceAutocompletePrediction[]>> {
|
|
53
63
|
if (!query.trim()) {
|
|
54
|
-
return [];
|
|
64
|
+
return ok([]);
|
|
55
65
|
}
|
|
56
66
|
|
|
57
67
|
if (!apiKey) {
|
|
58
|
-
|
|
68
|
+
return err({ code: 'VALIDATION_ERROR', message: 'Google Places API key is required' });
|
|
59
69
|
}
|
|
60
70
|
|
|
61
|
-
// Ensure Google Maps script is loaded
|
|
62
71
|
if (!isGoogleMapsLoaded()) {
|
|
63
|
-
await loadGoogleMapsScript(apiKey, 'places');
|
|
72
|
+
const loadResult = await loadGoogleMapsScript(apiKey, 'places');
|
|
73
|
+
if (!loadResult.ok) {
|
|
74
|
+
return err(loadResult.error);
|
|
75
|
+
}
|
|
64
76
|
}
|
|
65
77
|
|
|
66
78
|
const requestKey = `google-places-autocomplete:${query}:${JSON.stringify(options || {})}`;
|
|
@@ -125,11 +137,11 @@ export async function fetchPlaceAutocomplete(
|
|
|
125
137
|
}
|
|
126
138
|
|
|
127
139
|
// Call new API
|
|
128
|
-
return new Promise<GooglePlaceAutocompletePrediction[]
|
|
140
|
+
return new Promise<ApiResult<GooglePlaceAutocompletePrediction[]>>((resolve) => {
|
|
129
141
|
window.google!.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(request)
|
|
130
142
|
.then((response) => {
|
|
131
143
|
if (response.suggestions && response.suggestions.length > 0) {
|
|
132
|
-
const
|
|
144
|
+
const data: GooglePlaceAutocompletePrediction[] = response.suggestions
|
|
133
145
|
.filter(s => s.placePrediction)
|
|
134
146
|
.map((s) => ({
|
|
135
147
|
description: s.placePrediction!.text.text,
|
|
@@ -139,16 +151,16 @@ export async function fetchPlaceAutocomplete(
|
|
|
139
151
|
secondary_text: s.placePrediction!.structuredFormat?.secondaryText?.text || '',
|
|
140
152
|
},
|
|
141
153
|
}));
|
|
142
|
-
log.debug(`Received ${
|
|
143
|
-
resolve(
|
|
154
|
+
log.debug(`Received ${data.length} predictions (new API)`);
|
|
155
|
+
resolve(ok(data));
|
|
144
156
|
} else {
|
|
145
157
|
log.debug('No results found (new API)');
|
|
146
|
-
resolve([]);
|
|
158
|
+
resolve(ok([]));
|
|
147
159
|
}
|
|
148
160
|
})
|
|
149
161
|
.catch((error) => {
|
|
150
162
|
log.error('Autocomplete fetch failed (new API):', error);
|
|
151
|
-
|
|
163
|
+
resolve(err({ code: 'AUTOCOMPLETE_ERROR', message: error.message || 'Unknown error' }));
|
|
152
164
|
});
|
|
153
165
|
});
|
|
154
166
|
}
|
|
@@ -206,12 +218,11 @@ export async function fetchPlaceAutocomplete(
|
|
|
206
218
|
}
|
|
207
219
|
|
|
208
220
|
// Call AutocompleteService
|
|
209
|
-
return new Promise<GooglePlaceAutocompletePrediction[]
|
|
221
|
+
return new Promise<ApiResult<GooglePlaceAutocompletePrediction[]>>((resolve) => {
|
|
210
222
|
autocompleteService.getPlacePredictions(request, (predictions, status) => {
|
|
211
223
|
if (status === 'OK' && predictions) {
|
|
212
224
|
log.debug(`Received ${predictions.length} predictions`);
|
|
213
|
-
|
|
214
|
-
const result: GooglePlaceAutocompletePrediction[] = predictions.map((pred) => ({
|
|
225
|
+
const data: GooglePlaceAutocompletePrediction[] = predictions.map((pred) => ({
|
|
215
226
|
description: pred.description,
|
|
216
227
|
place_id: pred.place_id,
|
|
217
228
|
structured_formatting: {
|
|
@@ -219,44 +230,26 @@ export async function fetchPlaceAutocomplete(
|
|
|
219
230
|
secondary_text: pred.structured_formatting.secondary_text,
|
|
220
231
|
},
|
|
221
232
|
}));
|
|
222
|
-
resolve(
|
|
233
|
+
resolve(ok(data));
|
|
223
234
|
} else if (status === 'ZERO_RESULTS') {
|
|
224
235
|
log.debug('No results found');
|
|
225
|
-
resolve([]);
|
|
236
|
+
resolve(ok([]));
|
|
226
237
|
} else {
|
|
227
238
|
const errorMsg = `Google Places API error: ${status}`;
|
|
228
239
|
log.error('Autocomplete fetch failed:', errorMsg);
|
|
229
|
-
|
|
240
|
+
resolve(err({ code: 'AUTOCOMPLETE_ERROR', message: errorMsg }));
|
|
230
241
|
}
|
|
231
242
|
});
|
|
232
243
|
});
|
|
233
|
-
} catch (
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
throw error;
|
|
237
|
-
}
|
|
238
|
-
log.error('Autocomplete fetch failed: Unknown error');
|
|
239
|
-
throw new Error('Failed to fetch autocomplete predictions');
|
|
244
|
+
} catch (e) {
|
|
245
|
+
log.error('Autocomplete fetch failed:', e);
|
|
246
|
+
return err(toApiError(e));
|
|
240
247
|
}
|
|
241
248
|
});
|
|
242
249
|
}
|
|
243
250
|
|
|
244
|
-
/**
|
|
245
|
-
|
|
246
|
-
*
|
|
247
|
-
* @param placeId - Google Place ID
|
|
248
|
-
* @param apiKey - Google Places API key
|
|
249
|
-
* @returns Promise resolving to place details
|
|
250
|
-
*
|
|
251
|
-
* @example
|
|
252
|
-
* ```ts
|
|
253
|
-
* const place = await fetchPlaceDetails('ChIJ...', 'your-api-key');
|
|
254
|
-
* ```
|
|
255
|
-
*/
|
|
256
|
-
export async function fetchPlaceDetails(
|
|
257
|
-
placeId: string,
|
|
258
|
-
apiKey: string
|
|
259
|
-
): Promise<{
|
|
251
|
+
/** Place details shape from Google Places API */
|
|
252
|
+
type PlaceDetails = {
|
|
260
253
|
place_id: string;
|
|
261
254
|
formatted_address?: string;
|
|
262
255
|
address_components?: Array<{
|
|
@@ -270,18 +263,29 @@ export async function fetchPlaceDetails(
|
|
|
270
263
|
lng: () => number;
|
|
271
264
|
};
|
|
272
265
|
};
|
|
273
|
-
}
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Fetch place details from Google Places API.
|
|
270
|
+
* @returns Promise resolving to ApiResult with place details
|
|
271
|
+
*/
|
|
272
|
+
export async function fetchPlaceDetails(
|
|
273
|
+
placeId: string,
|
|
274
|
+
apiKey: string
|
|
275
|
+
): Promise<ApiResult<PlaceDetails>> {
|
|
274
276
|
if (!placeId) {
|
|
275
|
-
|
|
277
|
+
return err({ code: 'VALIDATION_ERROR', message: 'Place ID is required' });
|
|
276
278
|
}
|
|
277
279
|
|
|
278
280
|
if (!apiKey) {
|
|
279
|
-
|
|
281
|
+
return err({ code: 'VALIDATION_ERROR', message: 'Google Places API key is required' });
|
|
280
282
|
}
|
|
281
283
|
|
|
282
|
-
// Ensure Google Maps script is loaded
|
|
283
284
|
if (!isGoogleMapsLoaded()) {
|
|
284
|
-
await loadGoogleMapsScript(apiKey, 'places');
|
|
285
|
+
const loadResult = await loadGoogleMapsScript(apiKey, 'places');
|
|
286
|
+
if (!loadResult.ok) {
|
|
287
|
+
return err(loadResult.error);
|
|
288
|
+
}
|
|
285
289
|
}
|
|
286
290
|
|
|
287
291
|
const requestKey = `google-places-details:${placeId}`;
|
|
@@ -291,29 +295,13 @@ export async function fetchPlaceDetails(
|
|
|
291
295
|
log.debug(`Fetching place details for place_id: ${placeId}`);
|
|
292
296
|
|
|
293
297
|
if (!window.google?.maps?.places) {
|
|
294
|
-
|
|
298
|
+
return err({ code: 'PLACES_UNAVAILABLE', message: 'Google Maps Places library not available' });
|
|
295
299
|
}
|
|
296
300
|
|
|
297
|
-
// Create a dummy element for PlacesService (it needs an element but we don't use it)
|
|
298
301
|
const dummyElement = document.createElement('div');
|
|
299
302
|
const placesService = new window.google.maps.places.PlacesService(dummyElement);
|
|
300
303
|
|
|
301
|
-
|
|
302
|
-
return new Promise<{
|
|
303
|
-
place_id: string;
|
|
304
|
-
formatted_address?: string;
|
|
305
|
-
address_components?: Array<{
|
|
306
|
-
long_name: string;
|
|
307
|
-
short_name: string;
|
|
308
|
-
types: string[];
|
|
309
|
-
}>;
|
|
310
|
-
geometry?: {
|
|
311
|
-
location?: {
|
|
312
|
-
lat: () => number;
|
|
313
|
-
lng: () => number;
|
|
314
|
-
};
|
|
315
|
-
};
|
|
316
|
-
}>((resolve, reject) => {
|
|
304
|
+
return new Promise<ApiResult<PlaceDetails>>((resolve) => {
|
|
317
305
|
placesService.getDetails(
|
|
318
306
|
{
|
|
319
307
|
placeId: placeId,
|
|
@@ -322,39 +310,21 @@ export async function fetchPlaceDetails(
|
|
|
322
310
|
(place, status) => {
|
|
323
311
|
if (status === 'OK' && place) {
|
|
324
312
|
log.debug('Place details fetched successfully');
|
|
325
|
-
resolve(place as
|
|
326
|
-
place_id: string;
|
|
327
|
-
formatted_address?: string;
|
|
328
|
-
address_components?: Array<{
|
|
329
|
-
long_name: string;
|
|
330
|
-
short_name: string;
|
|
331
|
-
types: string[];
|
|
332
|
-
}>;
|
|
333
|
-
geometry?: {
|
|
334
|
-
location?: {
|
|
335
|
-
lat: () => number;
|
|
336
|
-
lng: () => number;
|
|
337
|
-
};
|
|
338
|
-
};
|
|
339
|
-
});
|
|
313
|
+
resolve(ok(place as PlaceDetails));
|
|
340
314
|
} else if (status === 'NOT_FOUND') {
|
|
341
315
|
log.error('Place not found:', placeId);
|
|
342
|
-
|
|
316
|
+
resolve(err({ code: 'NOT_FOUND', message: 'Place not found' }));
|
|
343
317
|
} else {
|
|
344
318
|
const errorMsg = `Failed to fetch place details: ${status}`;
|
|
345
319
|
log.error('Place details fetch failed:', errorMsg);
|
|
346
|
-
|
|
320
|
+
resolve(err({ code: 'PLACE_DETAILS_ERROR', message: errorMsg }));
|
|
347
321
|
}
|
|
348
322
|
}
|
|
349
323
|
);
|
|
350
324
|
});
|
|
351
|
-
} catch (
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
throw error;
|
|
355
|
-
}
|
|
356
|
-
log.error('Place details fetch failed: Unknown error');
|
|
357
|
-
throw new Error('Failed to fetch place details');
|
|
325
|
+
} catch (e) {
|
|
326
|
+
log.error('Place details fetch failed:', e);
|
|
327
|
+
return err(toApiError(e));
|
|
358
328
|
}
|
|
359
329
|
});
|
|
360
330
|
}
|
|
@@ -465,24 +435,22 @@ export function createAddressFromPlaceResult(
|
|
|
465
435
|
*
|
|
466
436
|
* @param placeId - Google Place ID
|
|
467
437
|
* @param apiKey - Google Places API key
|
|
468
|
-
* @returns Promise resolving to parsed address
|
|
438
|
+
* @returns Promise resolving to ApiResult with parsed address
|
|
469
439
|
*
|
|
470
440
|
* @example
|
|
471
441
|
* ```ts
|
|
472
|
-
* const
|
|
473
|
-
*
|
|
442
|
+
* const result = await getAddressByPlaceId('ChIJ...', 'your-api-key');
|
|
443
|
+
* if (result.ok) console.log(result.data);
|
|
474
444
|
* ```
|
|
475
445
|
*/
|
|
476
446
|
export async function getAddressByPlaceId(
|
|
477
447
|
placeId: string,
|
|
478
448
|
apiKey: string
|
|
479
|
-
): Promise<ParsedAddress | null
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
return
|
|
483
|
-
} catch (error) {
|
|
484
|
-
log.error('Failed to get address by place_id:', error);
|
|
485
|
-
return null;
|
|
449
|
+
): Promise<ApiResult<ParsedAddress | null>> {
|
|
450
|
+
const placeResult = await fetchPlaceDetails(placeId, apiKey);
|
|
451
|
+
if (!placeResult.ok) {
|
|
452
|
+
return placeResult;
|
|
486
453
|
}
|
|
454
|
+
return ok(createAddressFromPlaceResult(placeResult.data));
|
|
487
455
|
}
|
|
488
456
|
|