@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
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Testing Patterns Check Module
|
|
5
|
-
* @package @jmruthers/pace-core
|
|
6
|
-
* @module Audit/Checks/Testing
|
|
7
|
-
*
|
|
8
|
-
* Checks for:
|
|
9
|
-
* - Missing test files for critical components
|
|
10
|
-
* - Test files without assertions
|
|
11
|
-
* - Missing integration tests for RBAC flows
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const fs = require('fs');
|
|
15
|
-
const path = require('path');
|
|
16
|
-
const { getRelativePath } = require('../utils.cjs');
|
|
17
|
-
|
|
18
|
-
const testingCheck = {
|
|
19
|
-
name: 'testing',
|
|
20
|
-
description: 'Testing patterns (test coverage, missing tests)',
|
|
21
|
-
severity: 'suggestion',
|
|
22
|
-
|
|
23
|
-
async run(context) {
|
|
24
|
-
const { projectRoot, files } = context;
|
|
25
|
-
const issues = [];
|
|
26
|
-
const warnings = [];
|
|
27
|
-
const suggestions = [];
|
|
28
|
-
|
|
29
|
-
if (!files || files.length === 0) {
|
|
30
|
-
return { issues, warnings, suggestions };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Find all component files
|
|
34
|
-
const componentFiles = files.filter(f => f.match(/\.(tsx|jsx)$/) &&
|
|
35
|
-
!f.includes('.test.') &&
|
|
36
|
-
!f.includes('.spec.'));
|
|
37
|
-
|
|
38
|
-
// Find all test files
|
|
39
|
-
const testFiles = files.filter(f => f.match(/\.(test|spec)\.(ts|tsx|js|jsx)$/));
|
|
40
|
-
const testFileSet = new Set(testFiles.map(f => {
|
|
41
|
-
// Get base name without .test/.spec
|
|
42
|
-
return f.replace(/\.(test|spec)\.(ts|tsx|js|jsx)$/, '');
|
|
43
|
-
}));
|
|
44
|
-
|
|
45
|
-
// Check for components without tests
|
|
46
|
-
componentFiles.forEach(componentFile => {
|
|
47
|
-
const baseName = componentFile.replace(/\.(tsx|jsx)$/, '');
|
|
48
|
-
const hasTest = testFileSet.has(baseName + '.ts') ||
|
|
49
|
-
testFileSet.has(baseName + '.tsx') ||
|
|
50
|
-
testFileSet.has(baseName + '.js') ||
|
|
51
|
-
testFileSet.has(baseName + '.jsx');
|
|
52
|
-
|
|
53
|
-
if (!hasTest) {
|
|
54
|
-
const relativePath = getRelativePath(componentFile, projectRoot);
|
|
55
|
-
|
|
56
|
-
// Check if it's a critical component (has RBAC, auth, or is exported)
|
|
57
|
-
const content = fs.readFileSync(componentFile, 'utf8');
|
|
58
|
-
const isCritical = content.includes('usePermissions') ||
|
|
59
|
-
content.includes('useCan') ||
|
|
60
|
-
content.includes('PagePermissionGuard') ||
|
|
61
|
-
content.includes('useUnifiedAuth') ||
|
|
62
|
-
content.match(/^export\s+(default\s+)?(function|const|class)\s+\w+/m);
|
|
63
|
-
|
|
64
|
-
if (isCritical) {
|
|
65
|
-
warnings.push({
|
|
66
|
-
type: 'missing-test',
|
|
67
|
-
file: relativePath,
|
|
68
|
-
message: 'Critical component missing test file',
|
|
69
|
-
recommendation: `Create a test file for this component: ${path.basename(baseName)}.test.tsx`
|
|
70
|
-
});
|
|
71
|
-
} else {
|
|
72
|
-
suggestions.push({
|
|
73
|
-
type: 'missing-test',
|
|
74
|
-
file: relativePath,
|
|
75
|
-
message: 'Component missing test file',
|
|
76
|
-
recommendation: `Consider adding tests for this component: ${path.basename(baseName)}.test.tsx`
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// Check test files for assertions
|
|
83
|
-
testFiles.forEach(testFile => {
|
|
84
|
-
try {
|
|
85
|
-
const content = fs.readFileSync(testFile, 'utf8');
|
|
86
|
-
const relativePath = getRelativePath(testFile, projectRoot);
|
|
87
|
-
|
|
88
|
-
// Check for test assertions
|
|
89
|
-
const hasAssertions = /expect\(|assert\(|toBe\(|toEqual\(|toMatch\(/.test(content);
|
|
90
|
-
|
|
91
|
-
if (!hasAssertions) {
|
|
92
|
-
warnings.push({
|
|
93
|
-
type: 'test-without-assertions',
|
|
94
|
-
file: relativePath,
|
|
95
|
-
message: 'Test file has no assertions',
|
|
96
|
-
recommendation: 'Add assertions to verify test behavior'
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Check for RBAC-related tests
|
|
101
|
-
if (content.includes('usePermissions') || content.includes('useCan') || content.includes('PagePermissionGuard')) {
|
|
102
|
-
const hasRBACTests = /permission|rbac|access|role/i.test(content);
|
|
103
|
-
if (!hasRBACTests) {
|
|
104
|
-
suggestions.push({
|
|
105
|
-
type: 'missing-rbac-tests',
|
|
106
|
-
file: relativePath,
|
|
107
|
-
message: 'Component uses RBAC but tests may not cover permission scenarios',
|
|
108
|
-
recommendation: 'Add tests for different permission levels and access scenarios'
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
} catch (error) {
|
|
114
|
-
// Skip files with errors
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
return { issues, warnings, suggestions };
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
module.exports = testingCheck;
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* TypeScript Config Check Module
|
|
5
|
-
* @package @jmruthers/pace-core
|
|
6
|
-
* @module Audit/Checks/TypeScript
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const fs = require('fs');
|
|
10
|
-
const path = require('path');
|
|
11
|
-
|
|
12
|
-
const typescriptCheck = {
|
|
13
|
-
name: 'typescript',
|
|
14
|
-
description: 'TypeScript configuration checks (strict mode, etc.)',
|
|
15
|
-
severity: 'error',
|
|
16
|
-
|
|
17
|
-
async run(context) {
|
|
18
|
-
const { projectRoot } = context;
|
|
19
|
-
const issues = [];
|
|
20
|
-
const warnings = [];
|
|
21
|
-
|
|
22
|
-
const tsconfigPath = path.join(projectRoot, 'tsconfig.json');
|
|
23
|
-
if (!fs.existsSync(tsconfigPath)) {
|
|
24
|
-
return { issues, warnings, suggestions: [] };
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
const tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, 'utf8'));
|
|
29
|
-
const compilerOptions = tsconfig.compilerOptions || {};
|
|
30
|
-
|
|
31
|
-
if (!compilerOptions.strict) {
|
|
32
|
-
issues.push({
|
|
33
|
-
type: 'typescript-config',
|
|
34
|
-
file: 'tsconfig.json',
|
|
35
|
-
message: 'TypeScript strict mode is not enabled',
|
|
36
|
-
recommendation: 'Set "strict": true in tsconfig.json'
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (compilerOptions.noImplicitAny === false) {
|
|
41
|
-
issues.push({
|
|
42
|
-
type: 'typescript-config',
|
|
43
|
-
file: 'tsconfig.json',
|
|
44
|
-
message: 'noImplicitAny is disabled',
|
|
45
|
-
recommendation: 'Set "noImplicitAny": true in tsconfig.json'
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
} catch (error) {
|
|
49
|
-
warnings.push({
|
|
50
|
-
type: 'typescript-config',
|
|
51
|
-
file: 'tsconfig.json',
|
|
52
|
-
message: `Could not parse tsconfig.json: ${error.message}`,
|
|
53
|
-
recommendation: 'Check that tsconfig.json is valid JSON'
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return { issues, warnings, suggestions: [] };
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
module.exports = typescriptCheck;
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Core scanning engine that orchestrates all checks
|
|
5
|
-
* @package @jmruthers/pace-core
|
|
6
|
-
* @module Audit/Scanner
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const { findProjectRoot, findSourceFiles } = require('./utils.cjs');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Scanner class that orchestrates check execution
|
|
13
|
-
*/
|
|
14
|
-
class Scanner {
|
|
15
|
-
constructor(projectRoot = null) {
|
|
16
|
-
this.projectRoot = projectRoot || findProjectRoot();
|
|
17
|
-
this.checks = [];
|
|
18
|
-
this.context = {
|
|
19
|
-
projectRoot: this.projectRoot,
|
|
20
|
-
files: null,
|
|
21
|
-
packageJson: null,
|
|
22
|
-
manifest: null
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Register a check module
|
|
28
|
-
* @param {Object} check - Check module with { name, description, run, severity }
|
|
29
|
-
*/
|
|
30
|
-
registerCheck(check) {
|
|
31
|
-
if (!check.name || !check.run || typeof check.run !== 'function') {
|
|
32
|
-
throw new Error('Check must have name and run function');
|
|
33
|
-
}
|
|
34
|
-
this.checks.push(check);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Register multiple checks
|
|
39
|
-
* @param {Object[]} checks - Array of check modules
|
|
40
|
-
*/
|
|
41
|
-
registerChecks(checks) {
|
|
42
|
-
checks.forEach(check => this.registerCheck(check));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Initialize scanner context
|
|
47
|
-
* @param {Object} options - Options for initialization
|
|
48
|
-
*/
|
|
49
|
-
async initialize(options = {}) {
|
|
50
|
-
const { manifest = null, skipFileDiscovery = false } = options;
|
|
51
|
-
|
|
52
|
-
this.context.manifest = manifest;
|
|
53
|
-
|
|
54
|
-
if (!skipFileDiscovery) {
|
|
55
|
-
this.context.files = findSourceFiles(this.projectRoot);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Load package.json if needed
|
|
59
|
-
if (!this.context.packageJson) {
|
|
60
|
-
const { getPackageInfo } = require('./utils.cjs');
|
|
61
|
-
this.context.packageJson = getPackageInfo(this.projectRoot);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Run all registered checks
|
|
67
|
-
* @param {Object} options - Options for running checks
|
|
68
|
-
* @returns {Promise<Object>} Aggregated results from all checks
|
|
69
|
-
*/
|
|
70
|
-
async run(options = {}) {
|
|
71
|
-
const {
|
|
72
|
-
checkNames = null, // Run only specific checks
|
|
73
|
-
excludeChecks = [], // Exclude specific checks
|
|
74
|
-
parallel = false // Run checks in parallel
|
|
75
|
-
} = options;
|
|
76
|
-
|
|
77
|
-
// Filter checks to run
|
|
78
|
-
let checksToRun = this.checks;
|
|
79
|
-
if (checkNames && Array.isArray(checkNames)) {
|
|
80
|
-
checksToRun = this.checks.filter(check => checkNames.includes(check.name));
|
|
81
|
-
}
|
|
82
|
-
if (excludeChecks && Array.isArray(excludeChecks)) {
|
|
83
|
-
checksToRun = checksToRun.filter(check => !excludeChecks.includes(check.name));
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const results = {
|
|
87
|
-
checks: {},
|
|
88
|
-
summary: {
|
|
89
|
-
total: 0,
|
|
90
|
-
errors: 0,
|
|
91
|
-
warnings: 0,
|
|
92
|
-
suggestions: 0,
|
|
93
|
-
passed: 0
|
|
94
|
-
},
|
|
95
|
-
metadata: {
|
|
96
|
-
projectRoot: this.projectRoot,
|
|
97
|
-
filesScanned: this.context.files?.length || 0,
|
|
98
|
-
checksRun: checksToRun.length,
|
|
99
|
-
timestamp: new Date().toISOString()
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
// Run checks
|
|
104
|
-
if (parallel) {
|
|
105
|
-
const checkPromises = checksToRun.map(check => this.runCheck(check));
|
|
106
|
-
const checkResults = await Promise.all(checkPromises);
|
|
107
|
-
checkResults.forEach((result, index) => {
|
|
108
|
-
const check = checksToRun[index];
|
|
109
|
-
results.checks[check.name] = result;
|
|
110
|
-
this.updateSummary(results.summary, result);
|
|
111
|
-
});
|
|
112
|
-
} else {
|
|
113
|
-
for (const check of checksToRun) {
|
|
114
|
-
const result = await this.runCheck(check);
|
|
115
|
-
results.checks[check.name] = result;
|
|
116
|
-
this.updateSummary(results.summary, result);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return results;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Run a single check
|
|
125
|
-
* @param {Object} check - Check module to run
|
|
126
|
-
* @returns {Promise<Object>} Check result
|
|
127
|
-
*/
|
|
128
|
-
async runCheck(check) {
|
|
129
|
-
const startTime = Date.now();
|
|
130
|
-
try {
|
|
131
|
-
const result = await check.run(this.context);
|
|
132
|
-
const duration = Date.now() - startTime;
|
|
133
|
-
|
|
134
|
-
return {
|
|
135
|
-
name: check.name,
|
|
136
|
-
description: check.description || '',
|
|
137
|
-
severity: check.severity || 'warning',
|
|
138
|
-
status: 'completed',
|
|
139
|
-
duration,
|
|
140
|
-
...result
|
|
141
|
-
};
|
|
142
|
-
} catch (error) {
|
|
143
|
-
const duration = Date.now() - startTime;
|
|
144
|
-
return {
|
|
145
|
-
name: check.name,
|
|
146
|
-
description: check.description || '',
|
|
147
|
-
severity: check.severity || 'warning',
|
|
148
|
-
status: 'error',
|
|
149
|
-
error: error.message,
|
|
150
|
-
duration,
|
|
151
|
-
issues: [],
|
|
152
|
-
warnings: [],
|
|
153
|
-
suggestions: []
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Update summary statistics
|
|
160
|
-
* @param {Object} summary - Summary object to update
|
|
161
|
-
* @param {Object} result - Check result
|
|
162
|
-
*/
|
|
163
|
-
updateSummary(summary, result) {
|
|
164
|
-
summary.total++;
|
|
165
|
-
|
|
166
|
-
if (result.status === 'error') {
|
|
167
|
-
summary.errors++;
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const issues = result.issues || [];
|
|
172
|
-
const warnings = result.warnings || [];
|
|
173
|
-
const suggestions = result.suggestions || [];
|
|
174
|
-
|
|
175
|
-
if (issues.length > 0) {
|
|
176
|
-
summary.errors += issues.length;
|
|
177
|
-
}
|
|
178
|
-
if (warnings.length > 0) {
|
|
179
|
-
summary.warnings += warnings.length;
|
|
180
|
-
}
|
|
181
|
-
if (suggestions.length > 0) {
|
|
182
|
-
summary.suggestions += suggestions.length;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (issues.length === 0 && warnings.length === 0 && suggestions.length === 0) {
|
|
186
|
-
summary.passed++;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Get context for checks
|
|
192
|
-
* @returns {Object} Scanner context
|
|
193
|
-
*/
|
|
194
|
-
getContext() {
|
|
195
|
-
return this.context;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
module.exports = Scanner;
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Shared utilities for audit system
|
|
5
|
-
* @package @jmruthers/pace-core
|
|
6
|
-
* @module Audit/Utils
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const fs = require('fs');
|
|
10
|
-
const path = require('path');
|
|
11
|
-
|
|
12
|
-
// ANSI color codes for terminal output
|
|
13
|
-
const colors = {
|
|
14
|
-
reset: '\x1b[0m',
|
|
15
|
-
green: '\x1b[32m',
|
|
16
|
-
yellow: '\x1b[33m',
|
|
17
|
-
blue: '\x1b[34m',
|
|
18
|
-
cyan: '\x1b[36m',
|
|
19
|
-
bold: '\x1b[1m',
|
|
20
|
-
red: '\x1b[31m'
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Find project root by looking for package.json
|
|
25
|
-
* @param {string} startDir - Directory to start searching from
|
|
26
|
-
* @returns {string} Project root directory path
|
|
27
|
-
*/
|
|
28
|
-
function findProjectRoot(startDir = process.cwd()) {
|
|
29
|
-
let current = path.resolve(startDir);
|
|
30
|
-
while (current !== path.dirname(current)) {
|
|
31
|
-
if (fs.existsSync(path.join(current, 'package.json'))) {
|
|
32
|
-
return current;
|
|
33
|
-
}
|
|
34
|
-
current = path.dirname(current);
|
|
35
|
-
}
|
|
36
|
-
return startDir;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Recursively find all source files in a directory
|
|
41
|
-
* @param {string} dir - Directory to search
|
|
42
|
-
* @param {string[]} fileList - Accumulated file list (for recursion)
|
|
43
|
-
* @returns {string[]} Array of file paths
|
|
44
|
-
*/
|
|
45
|
-
function findSourceFiles(dir, fileList = []) {
|
|
46
|
-
const ignoreDirs = ['node_modules', 'dist', 'build', '.next', 'coverage', '__tests__', '__mocks__'];
|
|
47
|
-
const ignoreFiles = /\.(test|spec)\.(ts|tsx|js|jsx)$/;
|
|
48
|
-
const sourceExtensions = /\.(ts|tsx|js|jsx)$/;
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
const items = fs.readdirSync(dir);
|
|
52
|
-
|
|
53
|
-
items.forEach(item => {
|
|
54
|
-
const fullPath = path.join(dir, item);
|
|
55
|
-
const stat = fs.statSync(fullPath);
|
|
56
|
-
|
|
57
|
-
if (stat.isDirectory()) {
|
|
58
|
-
// Skip Edge Functions directory - they run in Deno, not React
|
|
59
|
-
if (item === 'functions' && dir.includes('supabase')) {
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
if (!ignoreDirs.includes(item) && !item.startsWith('.')) {
|
|
63
|
-
findSourceFiles(fullPath, fileList);
|
|
64
|
-
}
|
|
65
|
-
} else if (stat.isFile()) {
|
|
66
|
-
if (sourceExtensions.test(item) && !ignoreFiles.test(item)) {
|
|
67
|
-
fileList.push(fullPath);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
} catch (error) {
|
|
72
|
-
// Skip directories we can't read
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return fileList;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Get package.json info
|
|
80
|
-
* @param {string} projectRoot - Project root directory
|
|
81
|
-
* @returns {Object|null} Parsed package.json or null
|
|
82
|
-
*/
|
|
83
|
-
function getPackageInfo(projectRoot) {
|
|
84
|
-
const packagePath = path.join(projectRoot, 'package.json');
|
|
85
|
-
if (!fs.existsSync(packagePath)) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
try {
|
|
89
|
-
return JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
90
|
-
} catch (error) {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Get pace-core version from package.json
|
|
97
|
-
* @param {Object} packageJson - Parsed package.json
|
|
98
|
-
* @returns {string} Version string or 'unknown'
|
|
99
|
-
*/
|
|
100
|
-
function getPaceCoreVersion(packageJson) {
|
|
101
|
-
if (!packageJson) return 'unknown';
|
|
102
|
-
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
103
|
-
return deps['@jmruthers/pace-core'] || 'unknown';
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Get line number for a match in content
|
|
108
|
-
* @param {string} content - File content
|
|
109
|
-
* @param {string|number} match - Match string or index
|
|
110
|
-
* @returns {number} Line number (1-indexed)
|
|
111
|
-
*/
|
|
112
|
-
function getLineNumber(content, match) {
|
|
113
|
-
const index = typeof match === 'string' ? content.indexOf(match) : match;
|
|
114
|
-
if (index === -1) return 1;
|
|
115
|
-
const lines = content.substring(0, index).split('\n');
|
|
116
|
-
return lines.length;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Get relative path from project root
|
|
121
|
-
* @param {string} filePath - Absolute file path
|
|
122
|
-
* @param {string} projectRoot - Project root directory
|
|
123
|
-
* @returns {string} Relative path
|
|
124
|
-
*/
|
|
125
|
-
function getRelativePath(filePath, projectRoot) {
|
|
126
|
-
return path.relative(projectRoot, filePath);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
module.exports = {
|
|
130
|
-
colors,
|
|
131
|
-
findProjectRoot,
|
|
132
|
-
findSourceFiles,
|
|
133
|
-
getPackageInfo,
|
|
134
|
-
getPaceCoreVersion,
|
|
135
|
-
getLineNumber,
|
|
136
|
-
getRelativePath
|
|
137
|
-
};
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Console Reporter
|
|
5
|
-
* @package @jmruthers/pace-core
|
|
6
|
-
* @module Audit/Reporters/Console
|
|
7
|
-
*
|
|
8
|
-
* Formats audit results for terminal output with color coding
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const { colors } = require('../core/utils.cjs');
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Format check results for console output
|
|
15
|
-
*/
|
|
16
|
-
function formatCheckResult(checkName, result) {
|
|
17
|
-
const { issues = [], warnings = [], suggestions = [] } = result;
|
|
18
|
-
const total = issues.length + warnings.length + suggestions.length;
|
|
19
|
-
|
|
20
|
-
if (total === 0) {
|
|
21
|
-
return `${colors.green}✓${colors.reset} ${checkName}: No issues found`;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const parts = [];
|
|
25
|
-
if (issues.length > 0) {
|
|
26
|
-
parts.push(`${colors.red}${issues.length} error${issues.length !== 1 ? 's' : ''}${colors.reset}`);
|
|
27
|
-
}
|
|
28
|
-
if (warnings.length > 0) {
|
|
29
|
-
parts.push(`${colors.yellow}${warnings.length} warning${warnings.length !== 1 ? 's' : ''}${colors.reset}`);
|
|
30
|
-
}
|
|
31
|
-
if (suggestions.length > 0) {
|
|
32
|
-
parts.push(`${colors.blue}${suggestions.length} suggestion${suggestions.length !== 1 ? 's' : ''}${colors.reset}`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return `${colors.red}✗${colors.reset} ${checkName}: ${parts.join(', ')}`;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Format a single issue/warning/suggestion for console
|
|
40
|
-
*/
|
|
41
|
-
function formatItem(item, type) {
|
|
42
|
-
const icon = type === 'issue' ? `${colors.red}•${colors.reset}` :
|
|
43
|
-
type === 'warning' ? `${colors.yellow}⚠${colors.reset}` :
|
|
44
|
-
`${colors.blue}💡${colors.reset}`;
|
|
45
|
-
|
|
46
|
-
const fileInfo = item.line ? `${colors.yellow}${item.file}:${item.line}${colors.reset}` : `${colors.yellow}${item.file}${colors.reset}`;
|
|
47
|
-
|
|
48
|
-
let output = ` ${icon} ${fileInfo}\n`;
|
|
49
|
-
output += ` ${item.message || item.type}\n`;
|
|
50
|
-
|
|
51
|
-
if (item.recommendation) {
|
|
52
|
-
output += ` ${colors.green}Recommendation:${colors.reset} ${item.recommendation}\n`;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return output + '\n';
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Generate console report
|
|
60
|
-
*/
|
|
61
|
-
function generateReport(results, options = {}) {
|
|
62
|
-
const { verbose = false } = options;
|
|
63
|
-
|
|
64
|
-
console.log(`\n${colors.bold}${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}`);
|
|
65
|
-
console.log(`${colors.bold}${colors.cyan} pace-core Audit Report${colors.reset}`);
|
|
66
|
-
console.log(`${colors.bold}${colors.cyan}═══════════════════════════════════════════════════════════${colors.reset}\n`);
|
|
67
|
-
|
|
68
|
-
// Summary
|
|
69
|
-
const summary = results.summary || {};
|
|
70
|
-
console.log(`${colors.bold}Summary:${colors.reset}`);
|
|
71
|
-
console.log(` ${colors.red}Errors:${colors.reset} ${summary.errors || 0}`);
|
|
72
|
-
console.log(` ${colors.yellow}Warnings:${colors.reset} ${summary.warnings || 0}`);
|
|
73
|
-
console.log(` ${colors.blue}Suggestions:${colors.reset} ${summary.suggestions || 0}`);
|
|
74
|
-
console.log(` ${colors.green}Passed:${colors.reset} ${summary.passed || 0}`);
|
|
75
|
-
console.log(` ${colors.cyan}Total Checks:${colors.reset} ${summary.total || 0}\n`);
|
|
76
|
-
|
|
77
|
-
// Check results
|
|
78
|
-
if (results.checks) {
|
|
79
|
-
console.log(`${colors.bold}Check Results:${colors.reset}\n`);
|
|
80
|
-
Object.entries(results.checks).forEach(([checkName, result]) => {
|
|
81
|
-
console.log(formatCheckResult(checkName, result));
|
|
82
|
-
|
|
83
|
-
if (verbose && (result.issues?.length > 0 || result.warnings?.length > 0 || result.suggestions?.length > 0)) {
|
|
84
|
-
if (result.issues?.length > 0) {
|
|
85
|
-
console.log(`\n ${colors.red}${colors.bold}Errors:${colors.reset}\n`);
|
|
86
|
-
result.issues.forEach(issue => {
|
|
87
|
-
console.log(formatItem(issue, 'issue'));
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (result.warnings?.length > 0) {
|
|
92
|
-
console.log(` ${colors.yellow}${colors.bold}Warnings:${colors.reset}\n`);
|
|
93
|
-
result.warnings.forEach(warning => {
|
|
94
|
-
console.log(formatItem(warning, 'warning'));
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (result.suggestions?.length > 0) {
|
|
99
|
-
console.log(` ${colors.blue}${colors.bold}Suggestions:${colors.reset}\n`);
|
|
100
|
-
result.suggestions.forEach(suggestion => {
|
|
101
|
-
console.log(formatItem(suggestion, 'suggestion'));
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Compliance violations (if present)
|
|
109
|
-
if (results.checks?.compliance?.violations) {
|
|
110
|
-
const violations = results.checks.compliance.violations;
|
|
111
|
-
console.log(`\n${colors.bold}${colors.cyan}Compliance Details:${colors.reset}\n`);
|
|
112
|
-
|
|
113
|
-
// Format compliance violations similar to original report
|
|
114
|
-
formatComplianceViolations(violations);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
console.log('');
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Format compliance violations for console (similar to original format)
|
|
122
|
-
*/
|
|
123
|
-
function formatComplianceViolations(violations) {
|
|
124
|
-
const totalRestricted = violations.restrictedImports?.length || 0;
|
|
125
|
-
const totalDuplicates =
|
|
126
|
-
(violations.duplicateComponents?.length || 0) +
|
|
127
|
-
(violations.duplicateHooks?.length || 0) +
|
|
128
|
-
(violations.duplicateUtils?.length || 0);
|
|
129
|
-
|
|
130
|
-
if (totalRestricted > 0) {
|
|
131
|
-
console.log(`${colors.red}${colors.bold}❌ Restricted Imports: ${totalRestricted}${colors.reset}\n`);
|
|
132
|
-
violations.restrictedImports.forEach(({ module, reason, file, line }) => {
|
|
133
|
-
console.log(` ${colors.red}•${colors.reset} ${colors.yellow}${file}:${line}${colors.reset}`);
|
|
134
|
-
console.log(` Import: ${colors.cyan}${module}${colors.reset}`);
|
|
135
|
-
console.log(` ${colors.yellow}Reason:${colors.reset} ${reason}\n`);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (totalDuplicates > 0) {
|
|
140
|
-
console.log(`${colors.red}${colors.bold}❌ Duplicates: ${totalDuplicates}${colors.reset}\n`);
|
|
141
|
-
// Format duplicates...
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Format other violation types...
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
module.exports = {
|
|
148
|
-
generateReport,
|
|
149
|
-
formatCheckResult,
|
|
150
|
-
formatItem
|
|
151
|
-
};
|