@jmruthers/pace-core 0.6.4 → 0.6.6
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 +104 -0
- package/README.md +5 -403
- package/core-usage-manifest.json +93 -0
- package/cursor-rules/00-pace-core-compliance.mdc +128 -26
- package/cursor-rules/01-standards-compliance.mdc +49 -8
- package/cursor-rules/02-project-structure.mdc +6 -0
- package/cursor-rules/03-solid-principles.mdc +2 -0
- package/cursor-rules/04-testing-standards.mdc +2 -0
- package/cursor-rules/05-bug-reports-and-features.mdc +2 -0
- package/cursor-rules/06-code-quality.mdc +2 -0
- package/cursor-rules/07-tech-stack-compliance.mdc +2 -0
- package/cursor-rules/08-markup-quality.mdc +52 -27
- package/cursor-rules/09-rbac-compliance.mdc +462 -0
- package/cursor-rules/10-error-handling-patterns.mdc +179 -0
- package/cursor-rules/11-performance-optimization.mdc +169 -0
- package/cursor-rules/12-ci-cd-integration.mdc +150 -0
- package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
- package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-2N_tqbfq.d.ts} +1 -1
- package/dist/DataTable-LRJL4IRV.js +15 -0
- package/dist/{PublicPageProvider-DEMpysFR.d.ts → PublicPageProvider-BBH6Vqg7.d.ts} +72 -139
- package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
- package/dist/api-Y4MQWOFW.js +4 -0
- package/dist/audit-MYQXYZFU.js +3 -0
- package/dist/{chunk-J36DSWQK.js → chunk-2HGJFNAH.js} +8 -28
- package/dist/{chunk-OEWDTMG7.js → chunk-3O3WHILE.js} +38 -121
- package/dist/{chunk-M43Y4SSO.js → chunk-3QC3KRHK.js} +1 -14
- package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
- package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
- package/dist/chunk-4T7OBVTU.js +62 -0
- package/dist/{chunk-E66EQZE6.js → chunk-6GLLNA6U.js} +3 -9
- package/dist/{chunk-ZSAAAMVR.js → chunk-6QYDGKQY.js} +1 -4
- package/dist/{chunk-NN6WWZ5U.js → chunk-7TYHROIV.js} +579 -563
- package/dist/{chunk-M7MPQISP.js → chunk-A55DK444.js} +9 -16
- package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
- package/dist/{chunk-L4OXEN46.js → chunk-BVP2BCJF.js} +2 -16
- package/dist/chunk-C7NSAPTL.js +1 -0
- package/dist/{chunk-YKRAFF5K.js → chunk-FENMYN2U.js} +73 -149
- package/dist/{chunk-AVMLPIM7.js → chunk-FTCRZOG2.js} +284 -432
- package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
- package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
- package/dist/{chunk-I6DAQMWX.js → chunk-LAZMKTTF.js} +930 -891
- package/dist/{chunk-5EC5MEWX.js → chunk-MAGBIDNS.js} +77 -222
- package/dist/chunk-MBADTM7L.js +64 -0
- package/dist/chunk-OHIK3MIO.js +994 -0
- package/dist/{chunk-6SOIHG6Z.js → chunk-S7DKJPLT.js} +115 -44
- package/dist/{chunk-FMUCXFII.js → chunk-SD6WQY43.js} +1 -5
- package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
- package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
- package/dist/{chunk-FFQEQTNW.js → chunk-UIYSCEV7.js} +134 -45
- package/dist/{chunk-3LPHPB62.js → chunk-ZFYPMX46.js} +271 -87
- package/dist/{chunk-7JPAB3T5.js → chunk-ZS5VO5JB.js} +1989 -1283
- package/dist/components.d.ts +6 -6
- package/dist/components.js +57 -267
- package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
- package/dist/eslint-rules/index.cjs +22 -0
- package/dist/eslint-rules/rules/compliance.cjs +348 -0
- package/dist/eslint-rules/rules/components.cjs +113 -0
- package/dist/eslint-rules/rules/imports.cjs +102 -0
- package/dist/eslint-rules/rules/rbac.cjs +790 -0
- package/dist/eslint-rules/utils/helpers.cjs +42 -0
- package/dist/eslint-rules/utils/manifest-loader.cjs +75 -0
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +62 -270
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +1 -0
- package/dist/index.d.ts +36 -26
- package/dist/index.js +87 -690
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +8 -35
- package/dist/rbac/eslint-rules.d.ts +46 -44
- package/dist/rbac/eslint-rules.js +7 -4
- package/dist/rbac/index.d.ts +124 -594
- package/dist/rbac/index.js +14 -207
- package/dist/styles/index.js +2 -12
- package/dist/theming/runtime.js +3 -19
- package/dist/{timezone-CHhWg6b4.d.ts → timezone-BZe_eUxx.d.ts} +175 -1
- package/dist/{types-CkbwOr4Y.d.ts → types-B-K_5VnO.d.ts} +4 -0
- package/dist/types-t9H8qKRw.d.ts +55 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +7 -94
- package/dist/{usePublicRouteParams-i3qtoBgg.d.ts → usePublicRouteParams-COZ28Mvq.d.ts} +9 -9
- package/dist/utils.d.ts +24 -117
- package/dist/utils.js +54 -392
- package/docs/README.md +16 -6
- package/docs/api/README.md +4 -402
- package/docs/api/modules.md +454 -930
- package/docs/api-reference/components.md +3 -1
- package/docs/api-reference/deprecated.md +31 -6
- package/docs/api-reference/rpc-functions.md +78 -3
- package/docs/best-practices/accessibility.md +6 -3
- package/docs/getting-started/cursor-rules.md +3 -23
- package/docs/getting-started/dependencies.md +650 -0
- package/docs/getting-started/installation-guide.md +20 -7
- package/docs/getting-started/quick-start.md +23 -12
- package/docs/implementation-guides/permission-enforcement.md +4 -0
- package/docs/rbac/MIGRATION_GUIDE.md +819 -0
- package/docs/rbac/RBAC_CONTRACT.md +724 -0
- package/docs/rbac/README.md +12 -3
- package/docs/rbac/edge-functions-guide.md +376 -0
- package/docs/rbac/secure-client-protection.md +0 -34
- package/docs/standards/00-pace-core-compliance.md +967 -0
- package/docs/standards/01-standards-compliance.md +188 -0
- package/docs/standards/02-project-structure.md +985 -0
- package/docs/standards/03-solid-principles.md +39 -0
- package/docs/standards/04-testing-standards.md +36 -0
- package/docs/standards/05-bug-reports-and-features.md +27 -0
- package/docs/standards/{04-code-style-standard.md → 06-code-quality.md} +2 -0
- package/docs/standards/07-tech-stack-compliance.md +30 -0
- package/docs/standards/08-markup-quality.md +345 -0
- package/docs/standards/{07-rbac-and-rls-standard.md → 09-rbac-compliance.md} +149 -54
- package/docs/standards/10-error-handling-patterns.md +401 -0
- package/docs/standards/11-performance-optimization.md +348 -0
- package/docs/standards/12-ci-cd-integration.md +370 -0
- package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +192 -0
- package/docs/standards/README.md +62 -33
- package/docs/troubleshooting/organisation-context-setup.md +42 -19
- package/eslint-config-pace-core.cjs +20 -4
- package/package.json +31 -21
- package/scripts/audit/audit-compliance.cjs +1295 -0
- package/scripts/audit/audit-components.cjs +260 -0
- package/scripts/audit/audit-dependencies.cjs +395 -0
- package/scripts/audit/audit-rbac.cjs +954 -0
- package/scripts/audit/audit-standards.cjs +1268 -0
- package/scripts/audit/index.cjs +1898 -194
- package/scripts/install-cursor-rules.cjs +259 -8
- package/scripts/validate-master.js +1 -1
- package/src/__tests__/fixtures/supabase.ts +1 -1
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +1 -1
- package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +1 -1
- package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +1 -1
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +3 -3
- package/src/__tests__/helpers/component-test-utils.tsx +1 -1
- package/src/__tests__/helpers/supabaseMock.ts +2 -2
- package/src/__tests__/public-recipe-view.test.ts +38 -9
- package/src/components/Button/Button.tsx +5 -1
- package/src/components/ContextSelector/ContextSelector.tsx +42 -39
- package/src/components/DataTable/__tests__/keyboard.test.tsx +15 -2
- package/src/components/DataTable/components/DataTableBody.tsx +55 -31
- package/src/components/DataTable/components/DataTableCore.tsx +186 -13
- package/src/components/DataTable/components/DataTableLayout.tsx +30 -5
- package/src/components/DataTable/components/EditFields.tsx +23 -3
- package/src/components/DataTable/components/EditableRow.tsx +7 -2
- package/src/components/DataTable/components/ImportModal.tsx +4 -6
- package/src/components/DataTable/components/RowComponent.tsx +12 -0
- package/src/components/DataTable/components/ViewRowModal.tsx +4 -4
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +455 -96
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +122 -58
- package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
- package/src/components/DataTable/core/DataTableContext.tsx +1 -1
- package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +51 -47
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +24 -21
- package/src/components/DataTable/hooks/useDataTableState.ts +125 -9
- package/src/components/DataTable/hooks/useTableColumns.ts +40 -2
- package/src/components/DataTable/hooks/useTableHandlers.ts +11 -0
- package/src/components/DataTable/types.ts +5 -0
- package/src/components/DateTimeField/DateTimeField.tsx +20 -20
- package/src/components/DateTimeField/README.md +5 -2
- package/src/components/Dialog/Dialog.test.tsx +361 -318
- package/src/components/Dialog/Dialog.tsx +1154 -323
- package/src/components/Dialog/index.ts +3 -3
- package/src/components/FileDisplay/FileDisplay.test.tsx +45 -2
- package/src/components/FileDisplay/FileDisplay.tsx +28 -22
- package/src/components/Form/Form.test.tsx +9 -10
- package/src/components/Form/Form.tsx +369 -9
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +28 -28
- package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +40 -54
- package/src/components/LoginForm/LoginForm.tsx +2 -2
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
- package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
- package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +30 -41
- package/src/components/PaceAppLayout/README.md +10 -9
- package/src/components/PaceAppLayout/test-setup.tsx +40 -31
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +61 -0
- package/src/components/PasswordChange/PasswordChangeForm.tsx +20 -13
- package/src/components/PublicLayout/PublicLayout.test.tsx +7 -3
- package/src/components/PublicLayout/PublicPageLayout.tsx +5 -8
- package/src/components/Select/Select.tsx +23 -21
- package/src/components/Select/types.ts +1 -1
- package/src/components/UserMenu/UserMenu.test.tsx +38 -6
- package/src/components/UserMenu/UserMenu.tsx +39 -34
- package/src/components/index.ts +3 -4
- package/src/eslint-rules/index.cjs +22 -0
- package/src/eslint-rules/rules/compliance.cjs +348 -0
- package/src/eslint-rules/rules/components.cjs +113 -0
- package/src/eslint-rules/rules/imports.cjs +102 -0
- package/src/eslint-rules/rules/rbac.cjs +790 -0
- package/src/eslint-rules/utils/helpers.cjs +42 -0
- package/src/eslint-rules/utils/manifest-loader.cjs +75 -0
- package/src/hooks/__tests__/hooks.integration.test.tsx +6 -8
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +149 -67
- package/src/hooks/__tests__/usePublicEvent.test.ts +149 -79
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +158 -109
- package/src/hooks/__tests__/useSessionDraft.test.ts +163 -0
- package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +10 -5
- package/src/hooks/public/usePublicEvent.ts +62 -190
- package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
- package/src/hooks/public/usePublicEventLogo.ts +19 -9
- package/src/hooks/useAppConfig.ts +26 -24
- package/src/hooks/useEventTheme.test.ts +211 -233
- package/src/hooks/useEventTheme.ts +19 -28
- package/src/hooks/useEvents.ts +11 -7
- package/src/hooks/useKeyboardShortcuts.ts +1 -1
- package/src/hooks/useOrganisationPermissions.ts +9 -11
- package/src/hooks/useOrganisations.ts +13 -7
- package/src/hooks/useQueryCache.ts +0 -1
- package/src/hooks/useSessionDraft.ts +380 -0
- package/src/hooks/useSessionRestoration.ts +3 -1
- package/src/icons/index.ts +27 -0
- package/src/index.ts +16 -1
- package/src/providers/OrganisationProvider.tsx +23 -14
- package/src/providers/services/EventServiceProvider.tsx +1 -24
- package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -0
- package/src/rbac/README.md +20 -20
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +7 -457
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +33 -7
- package/src/rbac/adapters.tsx +7 -295
- package/src/rbac/api.test.ts +44 -56
- package/src/rbac/api.ts +10 -17
- package/src/rbac/cache-invalidation.ts +0 -1
- package/src/rbac/compliance/index.ts +10 -0
- package/src/rbac/compliance/pattern-detector.ts +553 -0
- package/src/rbac/compliance/runtime-compliance.ts +22 -0
- package/src/rbac/components/AccessDenied.tsx +150 -0
- package/src/rbac/components/NavigationGuard.tsx +12 -20
- package/src/rbac/components/PagePermissionGuard.tsx +4 -24
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +21 -8
- package/src/rbac/components/index.ts +3 -41
- package/src/rbac/eslint-rules.js +1 -1
- package/src/rbac/hooks/index.ts +0 -3
- package/src/rbac/hooks/permissions/index.ts +0 -3
- package/src/rbac/hooks/permissions/useAccessLevel.ts +4 -8
- package/src/rbac/hooks/usePermissions.ts +0 -3
- package/src/rbac/hooks/useRBAC.test.ts +21 -3
- package/src/rbac/hooks/useRBAC.ts +4 -3
- package/src/rbac/hooks/useResolvedScope.test.ts +57 -47
- package/src/rbac/hooks/useResolvedScope.ts +58 -140
- package/src/rbac/hooks/useResourcePermissions.test.ts +241 -60
- package/src/rbac/hooks/useResourcePermissions.ts +182 -63
- package/src/rbac/hooks/useRoleManagement.test.ts +65 -22
- package/src/rbac/hooks/useRoleManagement.ts +147 -19
- package/src/rbac/hooks/useSecureSupabase.ts +4 -8
- package/src/rbac/index.ts +7 -9
- package/src/rbac/permissions.ts +17 -17
- package/src/rbac/utils/contextValidator.ts +45 -7
- package/src/services/AuthService.ts +132 -23
- package/src/services/EventService.ts +4 -97
- package/src/services/InactivityService.ts +155 -58
- package/src/services/OrganisationService.ts +7 -44
- package/src/services/__tests__/OrganisationService.test.ts +26 -8
- package/src/services/base/BaseService.ts +0 -3
- package/src/styles/core.css +4 -0
- package/src/types/database.generated.ts +4733 -3809
- package/src/utils/__tests__/organisationContext.unit.test.ts +9 -10
- package/src/utils/context/organisationContext.test.ts +13 -28
- package/src/utils/context/organisationContext.ts +21 -52
- package/src/utils/dynamic/dynamicUtils.ts +1 -1
- package/src/utils/file-reference/index.ts +39 -15
- package/src/utils/formatting/formatDateTime.test.ts +3 -2
- package/src/utils/formatting/formatTime.test.ts +3 -2
- package/src/utils/google-places/loadGoogleMapsScript.ts +29 -4
- package/src/utils/index.ts +4 -1
- package/src/utils/persistence/__tests__/keyDerivation.test.ts +135 -0
- package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +123 -0
- package/src/utils/persistence/keyDerivation.ts +304 -0
- package/src/utils/persistence/sensitiveFieldDetection.ts +212 -0
- package/src/utils/security/secureStorage.ts +5 -5
- package/src/utils/storage/helpers.ts +3 -3
- package/src/utils/supabase/createBaseClient.ts +147 -0
- package/src/utils/timezone/timezone.test.ts +1 -2
- package/src/utils/timezone/timezone.ts +1 -1
- package/src/utils/validation/csrf.ts +4 -4
- package/cursor-rules/CHANGELOG.md +0 -119
- package/cursor-rules/README.md +0 -192
- package/dist/DataTable-E7YQZD7D.js +0 -175
- package/dist/DataTable-E7YQZD7D.js.map +0 -1
- package/dist/UnifiedAuthProvider-QPXO24B4.js +0 -18
- package/dist/UnifiedAuthProvider-QPXO24B4.js.map +0 -1
- package/dist/api-6LVZTHDS.js +0 -52
- package/dist/api-6LVZTHDS.js.map +0 -1
- package/dist/audit-V53FV5AG.js +0 -17
- package/dist/audit-V53FV5AG.js.map +0 -1
- package/dist/chunk-36LVWXB2.js +0 -227
- package/dist/chunk-36LVWXB2.js.map +0 -1
- package/dist/chunk-3LPHPB62.js.map +0 -1
- package/dist/chunk-5DRSZLL2.js.map +0 -1
- package/dist/chunk-5EC5MEWX.js.map +0 -1
- package/dist/chunk-63FOKYGO.js.map +0 -1
- package/dist/chunk-6SOIHG6Z.js.map +0 -1
- package/dist/chunk-7JPAB3T5.js.map +0 -1
- package/dist/chunk-ATKZM7RX.js +0 -2053
- package/dist/chunk-ATKZM7RX.js.map +0 -1
- package/dist/chunk-AVMLPIM7.js.map +0 -1
- package/dist/chunk-DGUM43GV.js.map +0 -1
- package/dist/chunk-E66EQZE6.js.map +0 -1
- package/dist/chunk-FFQEQTNW.js.map +0 -1
- package/dist/chunk-FMUCXFII.js.map +0 -1
- package/dist/chunk-G37KK66H.js.map +0 -1
- package/dist/chunk-I6DAQMWX.js.map +0 -1
- package/dist/chunk-J36DSWQK.js.map +0 -1
- package/dist/chunk-KQCRWDSA.js +0 -1
- package/dist/chunk-KQCRWDSA.js.map +0 -1
- package/dist/chunk-L4OXEN46.js.map +0 -1
- package/dist/chunk-LMC26NLJ.js +0 -84
- package/dist/chunk-LMC26NLJ.js.map +0 -1
- package/dist/chunk-M43Y4SSO.js.map +0 -1
- package/dist/chunk-M7MPQISP.js.map +0 -1
- package/dist/chunk-NN6WWZ5U.js.map +0 -1
- package/dist/chunk-OEWDTMG7.js.map +0 -1
- package/dist/chunk-PWLANIRT.js.map +0 -1
- package/dist/chunk-QXHPKYJV.js.map +0 -1
- package/dist/chunk-VBXEHIUJ.js.map +0 -1
- package/dist/chunk-YKRAFF5K.js.map +0 -1
- package/dist/chunk-ZSAAAMVR.js.map +0 -1
- package/dist/components.js.map +0 -1
- package/dist/contextValidator-OOPCLPZW.js +0 -9
- package/dist/contextValidator-OOPCLPZW.js.map +0 -1
- package/dist/eslint-rules/pace-core-compliance.cjs +0 -510
- package/dist/hooks.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/providers.js.map +0 -1
- package/dist/rbac/eslint-rules.js.map +0 -1
- package/dist/rbac/index.js.map +0 -1
- package/dist/styles/index.js.map +0 -1
- package/dist/theming/runtime.js.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils.js.map +0 -1
- package/docs/standards/01-architecture-standard.md +0 -44
- package/docs/standards/02-api-and-rpc-standard.md +0 -39
- package/docs/standards/03-component-standard.md +0 -32
- package/docs/standards/05-security-standard.md +0 -44
- package/docs/standards/06-testing-and-docs-standard.md +0 -29
- package/docs/standards/pace-core-compliance.md +0 -432
- package/scripts/audit/core/checks/accessibility.cjs +0 -197
- package/scripts/audit/core/checks/api-usage.cjs +0 -191
- package/scripts/audit/core/checks/bundle.cjs +0 -142
- package/scripts/audit/core/checks/compliance.cjs +0 -2706
- package/scripts/audit/core/checks/config.cjs +0 -54
- package/scripts/audit/core/checks/coverage.cjs +0 -84
- package/scripts/audit/core/checks/dependencies.cjs +0 -994
- package/scripts/audit/core/checks/documentation.cjs +0 -268
- package/scripts/audit/core/checks/environment.cjs +0 -116
- package/scripts/audit/core/checks/error-handling.cjs +0 -340
- package/scripts/audit/core/checks/forms.cjs +0 -172
- package/scripts/audit/core/checks/heuristics.cjs +0 -68
- package/scripts/audit/core/checks/hooks.cjs +0 -334
- package/scripts/audit/core/checks/imports.cjs +0 -244
- package/scripts/audit/core/checks/performance.cjs +0 -325
- package/scripts/audit/core/checks/routes.cjs +0 -117
- package/scripts/audit/core/checks/state.cjs +0 -130
- package/scripts/audit/core/checks/structure.cjs +0 -65
- package/scripts/audit/core/checks/style.cjs +0 -584
- package/scripts/audit/core/checks/testing.cjs +0 -122
- package/scripts/audit/core/checks/typescript.cjs +0 -61
- package/scripts/audit/core/scanner.cjs +0 -199
- package/scripts/audit/core/utils.cjs +0 -137
- package/scripts/audit/reporters/console.cjs +0 -151
- package/scripts/audit/reporters/json.cjs +0 -54
- package/scripts/audit/reporters/markdown.cjs +0 -124
- package/scripts/audit-consuming-app.cjs +0 -86
- package/src/eslint-rules/pace-core-compliance.cjs +0 -510
- package/src/eslint-rules/pace-core-compliance.js +0 -638
- package/src/rbac/components/EnhancedNavigationMenu.test.tsx +0 -555
- package/src/rbac/components/EnhancedNavigationMenu.tsx +0 -293
- package/src/rbac/components/NavigationProvider.test.tsx +0 -481
- package/src/rbac/components/NavigationProvider.tsx +0 -345
- package/src/rbac/components/PagePermissionProvider.test.tsx +0 -476
- package/src/rbac/components/PagePermissionProvider.tsx +0 -279
- package/src/rbac/components/PermissionEnforcer.tsx +0 -312
- package/src/rbac/components/RoleBasedRouter.tsx +0 -440
- package/src/rbac/components/SecureDataProvider.test.tsx +0 -543
- package/src/rbac/components/SecureDataProvider.tsx +0 -339
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -620
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -726
- package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -661
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +0 -881
- package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +0 -783
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +0 -645
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -659
- package/src/rbac/hooks/permissions/useCachedPermissions.ts +0 -79
- package/src/rbac/hooks/permissions/useHasAllPermissions.ts +0 -90
- package/src/rbac/hooks/permissions/useHasAnyPermission.ts +0 -90
|
@@ -14,22 +14,23 @@ vi.mock('../../components/PublicLayout/PublicPageProvider', () => ({
|
|
|
14
14
|
}))
|
|
15
15
|
}));
|
|
16
16
|
|
|
17
|
-
// Mock Supabase client
|
|
17
|
+
// Mock Supabase client with proper query builder chain
|
|
18
|
+
// usePublicEvent uses: .from('core_events').select(...).eq(...).eq(...).not(...).limit(1).single()
|
|
19
|
+
const createMockQueryBuilder = (mockData: any = null, mockError: any = null) => {
|
|
20
|
+
const builder: any = {
|
|
21
|
+
select: vi.fn().mockReturnThis(),
|
|
22
|
+
eq: vi.fn().mockReturnThis(),
|
|
23
|
+
not: vi.fn().mockReturnThis(),
|
|
24
|
+
limit: vi.fn().mockReturnThis(),
|
|
25
|
+
single: vi.fn().mockResolvedValue({ data: mockData, error: mockError }),
|
|
26
|
+
maybeSingle: vi.fn().mockResolvedValue({ data: mockData, error: mockError })
|
|
27
|
+
};
|
|
28
|
+
return builder;
|
|
29
|
+
};
|
|
30
|
+
|
|
18
31
|
const mockSupabaseClient = {
|
|
19
|
-
rpc: vi.fn(),
|
|
20
|
-
from: vi.fn(() => (
|
|
21
|
-
select: vi.fn(() => ({
|
|
22
|
-
eq: vi.fn(() => ({
|
|
23
|
-
eq: vi.fn(() => ({
|
|
24
|
-
not: vi.fn(() => ({
|
|
25
|
-
limit: vi.fn(() => ({
|
|
26
|
-
single: vi.fn()
|
|
27
|
-
}))
|
|
28
|
-
}))
|
|
29
|
-
}))
|
|
30
|
-
}))
|
|
31
|
-
}))
|
|
32
|
-
}))
|
|
32
|
+
rpc: vi.fn().mockResolvedValue({ data: null, error: null }),
|
|
33
|
+
from: vi.fn(() => createMockQueryBuilder())
|
|
33
34
|
};
|
|
34
35
|
|
|
35
36
|
// Helper to create table query mocks
|
|
@@ -131,16 +132,24 @@ describe('usePublicEvent', () => {
|
|
|
131
132
|
event_logo: null
|
|
132
133
|
};
|
|
133
134
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
// usePublicEvent makes TWO queries: core_events + core_file_references (logo)
|
|
136
|
+
const mockEventQueryBuilder = createMockQueryBuilder({
|
|
137
|
+
...mockEventData,
|
|
138
|
+
event_code: 'test-event',
|
|
139
|
+
is_visible: true,
|
|
140
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
141
|
+
updated_at: '2024-01-01T00:00:00Z'
|
|
137
142
|
});
|
|
143
|
+
const mockLogoQueryBuilder = createMockQueryBuilder(null, null); // No logo
|
|
144
|
+
mockSupabaseClient.from
|
|
145
|
+
.mockReturnValueOnce(mockEventQueryBuilder) // First call: core_events
|
|
146
|
+
.mockReturnValueOnce(mockLogoQueryBuilder); // Second call: core_file_references
|
|
138
147
|
|
|
139
148
|
const { result } = renderHook(() => usePublicEvent('test-event'));
|
|
140
149
|
|
|
141
150
|
await waitFor(() => {
|
|
142
151
|
expect(result.current.isLoading).toBe(false);
|
|
143
|
-
}, { interval: 10 });
|
|
152
|
+
}, { interval: 10, timeout: 2000 });
|
|
144
153
|
|
|
145
154
|
expect(result.current.event).toEqual({
|
|
146
155
|
id: '123',
|
|
@@ -161,19 +170,18 @@ describe('usePublicEvent', () => {
|
|
|
161
170
|
});
|
|
162
171
|
|
|
163
172
|
it('should handle event not found', async () => {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
});
|
|
173
|
+
// Mock query returning null (event not found)
|
|
174
|
+
const mockQueryBuilder = createMockQueryBuilder(null, { code: 'PGRST116', message: 'No rows found' });
|
|
175
|
+
mockSupabaseClient.from.mockReturnValue(mockQueryBuilder);
|
|
168
176
|
|
|
169
177
|
const { result } = renderHook(() => usePublicEvent('nonexistent-event'));
|
|
170
178
|
|
|
171
179
|
await waitFor(() => {
|
|
172
180
|
expect(result.current.isLoading).toBe(false);
|
|
173
|
-
}, { interval: 10 });
|
|
181
|
+
}, { interval: 10, timeout: 2000 });
|
|
174
182
|
|
|
175
183
|
expect(result.current.event).toBe(null);
|
|
176
|
-
expect(result.current.error).
|
|
184
|
+
expect(result.current.error?.message).toBe('Event not found');
|
|
177
185
|
});
|
|
178
186
|
|
|
179
187
|
it('should handle invalid event code', async () => {
|
|
@@ -210,22 +218,30 @@ describe('usePublicEvent', () => {
|
|
|
210
218
|
event_email: 'event@example.com'
|
|
211
219
|
};
|
|
212
220
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
221
|
+
// usePublicEvent makes TWO queries: core_events + core_file_references (logo)
|
|
222
|
+
const mockEventQueryBuilder = createMockQueryBuilder({
|
|
223
|
+
...mockEventData,
|
|
224
|
+
event_code: 'test-event',
|
|
225
|
+
is_visible: true,
|
|
226
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
227
|
+
updated_at: '2024-01-01T00:00:00Z'
|
|
216
228
|
});
|
|
229
|
+
const mockLogoQueryBuilder = createMockQueryBuilder(null, null);
|
|
230
|
+
mockSupabaseClient.from
|
|
231
|
+
.mockReturnValueOnce(mockEventQueryBuilder)
|
|
232
|
+
.mockReturnValueOnce(mockLogoQueryBuilder);
|
|
217
233
|
|
|
218
234
|
const { result, rerender } = renderHook(() => usePublicEvent('test-event'));
|
|
219
235
|
|
|
220
236
|
await waitFor(() => {
|
|
221
237
|
expect(result.current.isLoading).toBe(false);
|
|
222
|
-
}, { interval: 10 });
|
|
238
|
+
}, { interval: 10, timeout: 2000 });
|
|
223
239
|
|
|
224
|
-
// Rerender with same event code - should use cache
|
|
240
|
+
// Rerender with same event code - should use cache (no new queries)
|
|
225
241
|
rerender();
|
|
226
242
|
|
|
227
|
-
// Should not call
|
|
228
|
-
expect(mockSupabaseClient.
|
|
243
|
+
// Should not call query again (cached) - only initial fetch: 2 calls (event + logo)
|
|
244
|
+
expect(mockSupabaseClient.from).toHaveBeenCalledTimes(2);
|
|
229
245
|
});
|
|
230
246
|
|
|
231
247
|
it('should respect cache TTL', async () => {
|
|
@@ -248,28 +264,40 @@ describe('usePublicEvent', () => {
|
|
|
248
264
|
event_email: 'event@example.com'
|
|
249
265
|
};
|
|
250
266
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
267
|
+
// usePublicEvent makes TWO queries: core_events + core_file_references (logo)
|
|
268
|
+
const mockEventQueryBuilder = createMockQueryBuilder({
|
|
269
|
+
...mockEventData,
|
|
270
|
+
event_code: 'test-event',
|
|
271
|
+
is_visible: true,
|
|
272
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
273
|
+
updated_at: '2024-01-01T00:00:00Z'
|
|
254
274
|
});
|
|
275
|
+
const mockLogoQueryBuilder = createMockQueryBuilder(null, null); // No logo
|
|
276
|
+
// Need mocks for both hook instances: initial (2 calls) + after cache expires (2 calls) = 4 total
|
|
277
|
+
mockSupabaseClient.from
|
|
278
|
+
.mockReturnValueOnce(mockEventQueryBuilder) // First hook: event
|
|
279
|
+
.mockReturnValueOnce(mockLogoQueryBuilder) // First hook: logo
|
|
280
|
+
.mockReturnValueOnce(mockEventQueryBuilder) // Second hook (after cache expires): event
|
|
281
|
+
.mockReturnValueOnce(mockLogoQueryBuilder); // Second hook (after cache expires): logo
|
|
255
282
|
|
|
256
283
|
const { result } = renderHook(() => usePublicEvent('test-event', { cacheTtl: 100 }));
|
|
257
284
|
|
|
258
285
|
await waitFor(() => {
|
|
259
286
|
expect(result.current.isLoading).toBe(false);
|
|
260
|
-
}, { interval: 10 });
|
|
287
|
+
}, { interval: 10, timeout: 2000 });
|
|
261
288
|
|
|
262
289
|
// Wait for cache to expire
|
|
263
290
|
await new Promise(resolve => setTimeout(resolve, 150));
|
|
264
291
|
|
|
265
|
-
//
|
|
292
|
+
// New hook instance should fetch again (cache expired)
|
|
266
293
|
const { result: result2 } = renderHook(() => usePublicEvent('test-event', { cacheTtl: 100 }));
|
|
267
294
|
|
|
268
295
|
await waitFor(() => {
|
|
269
296
|
expect(result2.current.isLoading).toBe(false);
|
|
270
|
-
}, { interval: 10 });
|
|
297
|
+
}, { interval: 10, timeout: 2000 });
|
|
271
298
|
|
|
272
|
-
|
|
299
|
+
// Each fetch makes 2 calls (event + logo), so 2 fetches = 4 calls
|
|
300
|
+
expect(mockSupabaseClient.from).toHaveBeenCalledTimes(4);
|
|
273
301
|
});
|
|
274
302
|
|
|
275
303
|
it('should disable caching when requested', async () => {
|
|
@@ -297,14 +325,33 @@ describe('usePublicEvent', () => {
|
|
|
297
325
|
const { clearPublicEventCache } = await import('../public/usePublicEvent');
|
|
298
326
|
clearPublicEventCache();
|
|
299
327
|
|
|
300
|
-
//
|
|
328
|
+
// usePublicEvent makes TWO queries per fetch: core_events + core_file_references (logo)
|
|
301
329
|
let callCount = 0;
|
|
302
|
-
|
|
330
|
+
const mockEventQueryBuilder1 = createMockQueryBuilder({
|
|
331
|
+
...mockEventData,
|
|
332
|
+
event_code: 'test-event',
|
|
333
|
+
is_visible: true,
|
|
334
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
335
|
+
updated_at: '2024-01-01T00:00:00Z'
|
|
336
|
+
});
|
|
337
|
+
const mockLogoQueryBuilder1 = createMockQueryBuilder(null, null);
|
|
338
|
+
const mockEventQueryBuilder2 = createMockQueryBuilder({
|
|
339
|
+
...mockEventData,
|
|
340
|
+
event_code: 'test-event-2',
|
|
341
|
+
is_visible: true,
|
|
342
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
343
|
+
updated_at: '2024-01-01T00:00:00Z'
|
|
344
|
+
});
|
|
345
|
+
const mockLogoQueryBuilder2 = createMockQueryBuilder(null, null);
|
|
346
|
+
|
|
347
|
+
mockSupabaseClient.from.mockImplementation(() => {
|
|
303
348
|
callCount++;
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
349
|
+
// First fetch: event1 + logo1, Second fetch: event2 + logo2
|
|
350
|
+
if (callCount <= 2) {
|
|
351
|
+
return callCount === 1 ? mockEventQueryBuilder1 : mockLogoQueryBuilder1;
|
|
352
|
+
} else {
|
|
353
|
+
return callCount === 3 ? mockEventQueryBuilder2 : mockLogoQueryBuilder2;
|
|
354
|
+
}
|
|
308
355
|
});
|
|
309
356
|
|
|
310
357
|
const { result, rerender } = renderHook(
|
|
@@ -314,44 +361,39 @@ describe('usePublicEvent', () => {
|
|
|
314
361
|
|
|
315
362
|
await waitFor(() => {
|
|
316
363
|
expect(result.current.isLoading).toBe(false);
|
|
317
|
-
}, { interval: 10 });
|
|
364
|
+
}, { interval: 10, timeout: 2000 });
|
|
318
365
|
|
|
319
366
|
// Change the event code to force a new fetch
|
|
320
367
|
rerender({ eventCode: 'test-event-2' });
|
|
321
368
|
|
|
322
369
|
await waitFor(() => {
|
|
323
370
|
expect(result.current.isLoading).toBe(false);
|
|
324
|
-
}, { interval: 10 });
|
|
371
|
+
}, { interval: 10, timeout: 2000 });
|
|
325
372
|
|
|
326
|
-
|
|
373
|
+
// Each fetch makes 2 calls (event + logo), so 2 fetches = 4 calls
|
|
374
|
+
expect(callCount).toBe(4);
|
|
327
375
|
});
|
|
328
376
|
});
|
|
329
377
|
|
|
330
378
|
describe('Error Handling', () => {
|
|
331
|
-
it('should handle
|
|
332
|
-
//
|
|
379
|
+
it('should handle query errors', async () => {
|
|
380
|
+
// usePublicEvent uses table query, not RPC
|
|
333
381
|
const testError = { message: 'Database error', details: 'Test error details', hint: null, code: 'TEST_ERROR' };
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
data: null,
|
|
337
|
-
error: testError
|
|
338
|
-
})
|
|
339
|
-
);
|
|
382
|
+
const mockQueryBuilder = createMockQueryBuilder(null, testError);
|
|
383
|
+
mockSupabaseClient.from.mockReturnValue(mockQueryBuilder);
|
|
340
384
|
|
|
341
385
|
const { result } = renderHook(() => usePublicEvent('test-event'));
|
|
342
386
|
|
|
343
387
|
await waitFor(() => {
|
|
344
388
|
expect(result.current.isLoading).toBe(false);
|
|
345
|
-
}, { interval: 10 });
|
|
389
|
+
}, { interval: 10, timeout: 2000 });
|
|
346
390
|
|
|
347
391
|
expect(result.current.error).toBeInstanceOf(Error);
|
|
348
392
|
expect(result.current.error?.message).toBe('Database error');
|
|
349
393
|
expect(result.current.event).toBe(null);
|
|
350
394
|
|
|
351
|
-
// Verify the mock was called
|
|
352
|
-
expect(mockSupabaseClient.
|
|
353
|
-
event_code_param: 'test-event'
|
|
354
|
-
});
|
|
395
|
+
// Verify the mock was called (usePublicEvent uses table queries, not RPC)
|
|
396
|
+
expect(mockSupabaseClient.from).toHaveBeenCalled();
|
|
355
397
|
});
|
|
356
398
|
|
|
357
399
|
it('should handle missing Supabase client', async () => {
|
|
@@ -411,16 +453,24 @@ describe('usePublicEvent', () => {
|
|
|
411
453
|
event_logo: null
|
|
412
454
|
};
|
|
413
455
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
456
|
+
// usePublicEvent makes TWO queries: core_events + core_file_references (logo)
|
|
457
|
+
const mockEventQueryBuilder = createMockQueryBuilder({
|
|
458
|
+
...mockEventData,
|
|
459
|
+
event_code: 'test-event',
|
|
460
|
+
is_visible: true,
|
|
461
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
462
|
+
updated_at: '2024-01-01T00:00:00Z'
|
|
417
463
|
});
|
|
464
|
+
const mockLogoQueryBuilder = createMockQueryBuilder(null, null);
|
|
465
|
+
mockSupabaseClient.from
|
|
466
|
+
.mockReturnValueOnce(mockEventQueryBuilder)
|
|
467
|
+
.mockReturnValueOnce(mockLogoQueryBuilder);
|
|
418
468
|
|
|
419
469
|
const { result } = renderHook(() => usePublicEvent('test-event'));
|
|
420
470
|
|
|
421
471
|
await waitFor(() => {
|
|
422
472
|
expect(result.current.isLoading).toBe(false);
|
|
423
|
-
}, { interval: 10 });
|
|
473
|
+
}, { interval: 10, timeout: 2000 });
|
|
424
474
|
|
|
425
475
|
expect(result.current.event).toBeTruthy();
|
|
426
476
|
});
|
|
@@ -447,23 +497,34 @@ describe('usePublicEvent', () => {
|
|
|
447
497
|
event_email: 'event@example.com'
|
|
448
498
|
};
|
|
449
499
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
500
|
+
// usePublicEvent makes TWO queries per fetch: core_events + core_file_references (logo)
|
|
501
|
+
const mockEventQueryBuilder = createMockQueryBuilder({
|
|
502
|
+
...mockEventData,
|
|
503
|
+
event_code: 'test-event',
|
|
504
|
+
is_visible: true,
|
|
505
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
506
|
+
updated_at: '2024-01-01T00:00:00Z'
|
|
453
507
|
});
|
|
508
|
+
const mockLogoQueryBuilder = createMockQueryBuilder(null, null);
|
|
509
|
+
mockSupabaseClient.from
|
|
510
|
+
.mockReturnValueOnce(mockEventQueryBuilder)
|
|
511
|
+
.mockReturnValueOnce(mockLogoQueryBuilder)
|
|
512
|
+
.mockReturnValueOnce(mockEventQueryBuilder) // Refetch: event
|
|
513
|
+
.mockReturnValueOnce(mockLogoQueryBuilder); // Refetch: logo
|
|
454
514
|
|
|
455
515
|
const { result } = renderHook(() => usePublicEvent('test-event'));
|
|
456
516
|
|
|
457
517
|
await waitFor(() => {
|
|
458
518
|
expect(result.current.isLoading).toBe(false);
|
|
459
|
-
}, { interval: 10 });
|
|
519
|
+
}, { interval: 10, timeout: 2000 });
|
|
460
520
|
|
|
461
521
|
// Call refetch
|
|
462
522
|
await act(async () => {
|
|
463
523
|
await result.current.refetch();
|
|
464
524
|
});
|
|
465
525
|
|
|
466
|
-
|
|
526
|
+
// Initial fetch (2 calls) + refetch (2 calls) = 4 total
|
|
527
|
+
expect(mockSupabaseClient.from).toHaveBeenCalledTimes(4);
|
|
467
528
|
});
|
|
468
529
|
|
|
469
530
|
it('should clear cache when refetch is called', async () => {
|
|
@@ -486,24 +547,30 @@ describe('usePublicEvent', () => {
|
|
|
486
547
|
event_email: 'event@example.com'
|
|
487
548
|
};
|
|
488
549
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
550
|
+
// usePublicEvent uses table query, not RPC
|
|
551
|
+
const mockQueryBuilder = createMockQueryBuilder({
|
|
552
|
+
...mockEventData,
|
|
553
|
+
event_code: 'test-event',
|
|
554
|
+
is_visible: true,
|
|
555
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
556
|
+
updated_at: '2024-01-01T00:00:00Z'
|
|
492
557
|
});
|
|
558
|
+
mockSupabaseClient.from.mockReturnValue(mockQueryBuilder);
|
|
493
559
|
|
|
494
560
|
const { result } = renderHook(() => usePublicEvent('test-event'));
|
|
495
561
|
|
|
496
562
|
await waitFor(() => {
|
|
497
563
|
expect(result.current.isLoading).toBe(false);
|
|
498
|
-
}, { interval: 10 });
|
|
564
|
+
}, { interval: 10, timeout: 2000 });
|
|
499
565
|
|
|
500
566
|
// Call refetch
|
|
501
567
|
await act(async () => {
|
|
502
568
|
await result.current.refetch();
|
|
503
569
|
});
|
|
504
570
|
|
|
505
|
-
// Should call
|
|
506
|
-
|
|
571
|
+
// Should call query again (cache was cleared)
|
|
572
|
+
// Each fetch makes 2 calls (event + logo), so 2 fetches = 4 calls
|
|
573
|
+
expect(mockSupabaseClient.from).toHaveBeenCalledTimes(4);
|
|
507
574
|
});
|
|
508
575
|
});
|
|
509
576
|
|
|
@@ -531,7 +598,8 @@ describe('usePublicEvent', () => {
|
|
|
531
598
|
|
|
532
599
|
describe('Edge Cases', () => {
|
|
533
600
|
it('should handle null event data from RPC', async () => {
|
|
534
|
-
|
|
601
|
+
// Use table query mock instead of RPC
|
|
602
|
+
const mockQueryBuilder = createMockQueryBuilder({
|
|
535
603
|
data: null,
|
|
536
604
|
error: null
|
|
537
605
|
});
|
|
@@ -547,7 +615,8 @@ describe('usePublicEvent', () => {
|
|
|
547
615
|
});
|
|
548
616
|
|
|
549
617
|
it('should handle empty event data array from RPC', async () => {
|
|
550
|
-
|
|
618
|
+
// Use table query mock instead of RPC
|
|
619
|
+
const mockQueryBuilder = createMockQueryBuilder({
|
|
551
620
|
data: [],
|
|
552
621
|
error: null
|
|
553
622
|
});
|
|
@@ -563,7 +632,8 @@ describe('usePublicEvent', () => {
|
|
|
563
632
|
});
|
|
564
633
|
|
|
565
634
|
it('should handle undefined event data from RPC', async () => {
|
|
566
|
-
|
|
635
|
+
// Use table query mock instead of RPC
|
|
636
|
+
const mockQueryBuilder = createMockQueryBuilder({
|
|
567
637
|
data: [undefined],
|
|
568
638
|
error: null
|
|
569
639
|
});
|