@jmruthers/pace-core 0.6.5 → 0.6.7
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/audit-tool/00-dependencies.cjs +394 -0
- package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
- package/audit-tool/audits/02-project-structure.cjs +255 -0
- package/audit-tool/audits/03-architecture.cjs +196 -0
- package/audit-tool/audits/04-code-quality.cjs +149 -0
- package/audit-tool/audits/05-styling.cjs +224 -0
- package/audit-tool/audits/06-security-rbac.cjs +544 -0
- package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
- package/audit-tool/audits/08-testing-documentation.cjs +202 -0
- package/audit-tool/audits/09-operations.cjs +208 -0
- package/audit-tool/index.cjs +291 -0
- package/audit-tool/utils/code-utils.cjs +218 -0
- package/audit-tool/utils/file-utils.cjs +230 -0
- package/audit-tool/utils/report-utils.cjs +241 -0
- package/core-usage-manifest.json +93 -0
- package/cursor-rules/00-standards-overview.mdc +156 -0
- package/cursor-rules/01-pace-core-compliance.mdc +586 -0
- package/cursor-rules/02-project-structure.mdc +42 -4
- package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +126 -10
- package/cursor-rules/04-code-quality.mdc +419 -0
- package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +104 -34
- package/cursor-rules/06-security-rbac.mdc +518 -0
- package/cursor-rules/07-api-tech-stack.mdc +377 -0
- package/cursor-rules/08-testing-documentation.mdc +324 -0
- package/cursor-rules/09-operations.mdc +365 -0
- package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
- package/dist/DataTable-7PMH7XN7.js +15 -0
- package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
- package/dist/{PublicPageProvider-QTFVrL-Z.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +33 -72
- package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
- package/dist/api-Y4MQWOFW.js +4 -0
- package/dist/audit-MYQXYZFU.js +3 -0
- package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
- package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
- package/dist/{chunk-UPPMRMYG.js → chunk-5X4QLXRG.js} +73 -151
- package/dist/chunk-6F3IILHI.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-FMUCXFII.js → chunk-7ILTDCL2.js} +9 -5
- package/dist/{chunk-M43Y4SSO.js → chunk-A3W6LW53.js} +15 -13
- package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
- package/dist/{chunk-HU2C6SSC.js → chunk-BM4CQ5P3.js} +606 -559
- package/dist/chunk-C7NSAPTL.js +1 -0
- package/dist/{chunk-J36DSWQK.js → chunk-FEJLJNWA.js} +7 -41
- package/dist/{chunk-IHB5DR3H.js → chunk-FTCRZOG2.js} +188 -387
- package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
- package/dist/chunk-GHYHJTYV.js +994 -0
- package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
- package/dist/{chunk-FFQEQTNW.js → chunk-IUBRCBSY.js} +134 -45
- package/dist/{chunk-6COVEUS7.js → chunk-JGWDVX64.js} +983 -1034
- package/dist/{chunk-RGAWHO7N.js → chunk-L4XMVJKY.js} +77 -222
- package/dist/chunk-MBADTM7L.js +64 -0
- package/dist/{chunk-M7MPQISP.js → chunk-OJ4SKRSV.js} +3 -16
- package/dist/{chunk-IVOFDYWT.js → chunk-Q7Q7V5NV.js} +2109 -1604
- package/dist/{chunk-JGRYX5UX.js → chunk-S7DKJPLT.js} +29 -58
- package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
- package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
- package/dist/{chunk-NTM7ZSB6.js → chunk-VBCS3DUA.js} +261 -168
- package/dist/{chunk-EFN2EIMK.js → chunk-ZFYPMX46.js} +271 -87
- package/dist/{chunk-L4OXEN46.js → chunk-ZKAWKYT4.js} +10 -24
- package/dist/components.d.ts +7 -5
- package/dist/components.js +46 -257
- package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
- package/dist/eslint-rules/index.cjs +35 -0
- package/{src/eslint-rules/pace-core-compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +234 -235
- package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
- package/dist/eslint-rules/rules/05-styling.cjs +61 -0
- package/dist/eslint-rules/rules/06-security-rbac.cjs +806 -0
- package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
- package/dist/eslint-rules/rules/08-testing.cjs +94 -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 +6 -6
- package/dist/hooks.js +62 -172
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.js +1 -0
- package/dist/index.d.ts +12 -11
- package/dist/index.js +67 -660
- 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 +109 -586
- package/dist/rbac/index.js +14 -207
- package/dist/styles/index.js +2 -12
- package/dist/theming/runtime.d.ts +14 -1
- 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-DXstZpNI.d.ts} +4 -17
- package/dist/types-t9H8qKRw.d.ts +55 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +7 -94
- package/dist/{usePublicRouteParams-ClnV4tnv.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +20 -20
- package/dist/utils.d.ts +24 -117
- package/dist/utils.js +54 -392
- package/docs/README.md +17 -7
- package/docs/api/README.md +4 -402
- package/docs/api/modules.md +301 -871
- package/docs/api-reference/components.md +21 -21
- package/docs/api-reference/deprecated.md +31 -6
- package/docs/api-reference/hooks.md +80 -80
- package/docs/api-reference/rpc-functions.md +78 -3
- package/docs/api-reference/types.md +1 -1
- package/docs/api-reference/utilities.md +1 -1
- package/docs/architecture/README.md +1 -1
- package/docs/core-concepts/events.md +3 -3
- package/docs/core-concepts/organisations.md +6 -6
- package/docs/core-concepts/permissions.md +6 -6
- package/docs/documentation-index.md +12 -18
- package/docs/getting-started/cursor-rules.md +3 -23
- package/docs/getting-started/dependencies.md +650 -0
- package/docs/getting-started/documentation-index.md +1 -1
- package/docs/getting-started/examples/README.md +4 -4
- package/docs/getting-started/examples/full-featured-app.md +1 -1
- package/docs/getting-started/faq.md +2 -2
- package/docs/getting-started/installation-guide.md +20 -7
- package/docs/getting-started/quick-reference.md +4 -4
- package/docs/getting-started/quick-start.md +23 -12
- package/docs/implementation-guides/authentication.md +15 -15
- package/docs/implementation-guides/component-styling.md +1 -1
- package/docs/implementation-guides/data-tables.md +126 -33
- package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
- package/docs/implementation-guides/dynamic-colors.md +3 -3
- package/docs/implementation-guides/file-upload-storage.md +2 -2
- package/docs/implementation-guides/hierarchical-datatable.md +40 -60
- package/docs/implementation-guides/inactivity-tracking.md +3 -3
- package/docs/implementation-guides/large-datasets.md +3 -2
- package/docs/implementation-guides/organisation-security.md +2 -2
- package/docs/implementation-guides/performance.md +2 -2
- package/docs/implementation-guides/permission-enforcement.md +5 -1
- package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
- package/docs/migration/V0.4.0_rbac-migration.md +6 -6
- package/docs/rbac/MIGRATION_GUIDE.md +819 -0
- package/docs/rbac/RBAC_CONTRACT.md +724 -0
- package/docs/rbac/README.md +17 -8
- package/docs/rbac/advanced-patterns.md +6 -6
- package/docs/rbac/api-reference.md +20 -20
- package/docs/rbac/edge-functions-guide.md +376 -0
- package/docs/rbac/event-based-apps.md +3 -3
- package/docs/rbac/examples.md +41 -41
- package/docs/rbac/getting-started.md +37 -37
- package/docs/rbac/performance.md +1 -1
- package/docs/rbac/quick-start.md +52 -52
- package/docs/rbac/secure-client-protection.md +1 -35
- package/docs/rbac/troubleshooting.md +1 -1
- package/docs/security/README.md +5 -5
- package/docs/standards/0-standards-overview.md +220 -0
- package/docs/standards/1-pace-core-compliance-standards.md +986 -0
- package/docs/standards/2-project-structure-standards.md +949 -0
- package/docs/standards/3-architecture-standards.md +606 -0
- package/docs/standards/4-code-quality-standards.md +728 -0
- package/docs/standards/5-styling-standards.md +348 -0
- package/docs/standards/{07-rbac-and-rls-standard.md → 6-security-rbac-standards.md} +269 -66
- package/docs/standards/7-api-tech-stack-standards.md +662 -0
- package/docs/standards/8-testing-documentation-standards.md +401 -0
- package/docs/standards/9-operations-standards.md +1102 -0
- package/docs/standards/README.md +185 -57
- package/docs/troubleshooting/README.md +4 -4
- package/docs/troubleshooting/common-issues.md +2 -2
- package/docs/troubleshooting/debugging.md +9 -9
- package/docs/troubleshooting/migration.md +4 -4
- package/docs/troubleshooting/organisation-context-setup.md +42 -19
- package/eslint-config-pace-core.cjs +33 -6
- package/package.json +35 -23
- package/scripts/install-cursor-rules.cjs +25 -6
- package/scripts/install-eslint-config.cjs +284 -0
- package/src/__tests__/fixtures/supabase.ts +1 -1
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +3 -3
- 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-providers.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +13 -13
- package/src/__tests__/helpers/component-test-utils.tsx +1 -1
- package/src/__tests__/helpers/supabaseMock.ts +2 -2
- package/src/__tests__/integration/UserProfile.test.tsx +14 -14
- package/src/__tests__/public-recipe-view.test.ts +38 -9
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
- package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
- package/src/__tests__/templates/component.test.template.tsx +18 -15
- package/src/components/Button/Button.tsx +5 -1
- package/src/components/Calendar/Calendar.tsx +201 -47
- package/src/components/ContextSelector/ContextSelector.tsx +106 -119
- package/src/components/DataTable/AUDIT_REPORT.md +293 -0
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
- package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
- package/src/components/DataTable/components/DataTableCore.tsx +186 -13
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
- package/src/components/DataTable/components/DataTableLayout.tsx +35 -21
- package/src/components/DataTable/components/EditFields.tsx +23 -3
- package/src/components/DataTable/components/EditableRow.tsx +12 -9
- package/src/components/DataTable/components/EmptyState.tsx +10 -9
- package/src/components/DataTable/components/FilterRow.tsx +2 -4
- package/src/components/DataTable/components/ImportModal.tsx +124 -126
- package/src/components/DataTable/components/LoadingState.tsx +5 -6
- package/src/components/DataTable/components/RowComponent.tsx +12 -0
- package/src/components/DataTable/components/SortIndicator.tsx +50 -0
- package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
- package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
- package/src/components/DataTable/components/index.ts +2 -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 -18
- package/src/components/DataTable/utils/a11yUtils.ts +17 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
- package/src/components/DateTimeField/DateTimeField.tsx +10 -9
- package/src/components/Dialog/Dialog.test.tsx +128 -104
- package/src/components/Dialog/Dialog.tsx +742 -24
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
- package/src/components/FileDisplay/FileDisplay.test.tsx +4 -2
- package/src/components/FileDisplay/FileDisplay.tsx +23 -17
- package/src/components/FileUpload/FileUpload.test.tsx +52 -14
- package/src/components/FileUpload/FileUpload.tsx +112 -130
- package/src/components/Form/Form.test.tsx +6 -8
- package/src/components/Form/Form.tsx +365 -4
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
- package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +11 -15
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
- package/src/components/Progress/Progress.tsx +2 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
- package/src/components/Select/Select.tsx +109 -98
- package/src/components/Select/types.ts +4 -1
- package/src/components/UserMenu/UserMenu.tsx +9 -6
- package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
- package/src/hooks/__tests__/hooks.integration.test.tsx +55 -57
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
- 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 +67 -195
- package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
- package/src/hooks/public/usePublicEventLogo.ts +24 -14
- package/src/hooks/public/usePublicFileDisplay.ts +2 -2
- package/src/hooks/public/usePublicRouteParams.ts +5 -5
- package/src/hooks/useAppConfig.ts +28 -26
- package/src/hooks/useEventTheme.test.ts +217 -239
- package/src/hooks/useEventTheme.ts +16 -28
- package/src/hooks/useFileDisplay.ts +2 -2
- package/src/hooks/useOrganisationPermissions.ts +5 -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 +5 -0
- package/src/providers/OrganisationProvider.tsx +23 -14
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
- package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
- package/src/providers/__tests__/EventProvider.test.tsx +61 -61
- package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
- package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
- package/src/providers/services/EventServiceProvider.tsx +1 -24
- package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +13 -10
- 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/useResolvedScope.test.ts +57 -47
- package/src/rbac/hooks/useResolvedScope.ts +58 -140
- package/src/rbac/hooks/useResourcePermissions.test.ts +124 -38
- package/src/rbac/hooks/useResourcePermissions.ts +139 -48
- 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/utils/contextValidator.ts +9 -7
- package/src/services/AuthService.ts +130 -18
- package/src/services/EventService.ts +4 -97
- package/src/services/InactivityService.ts +16 -0
- 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 +7 -0
- package/src/theming/__tests__/parseEventColours.test.ts +9 -3
- package/src/theming/parseEventColours.ts +22 -10
- package/src/types/database.generated.ts +4733 -3809
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
- 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/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/README.md +1 -1
- 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/00-pace-core-compliance.mdc +0 -331
- package/cursor-rules/01-standards-compliance.mdc +0 -244
- package/cursor-rules/04-testing-standards.mdc +0 -268
- package/cursor-rules/05-bug-reports-and-features.mdc +0 -246
- package/cursor-rules/06-code-quality.mdc +0 -309
- package/cursor-rules/07-tech-stack-compliance.mdc +0 -214
- package/cursor-rules/CHANGELOG.md +0 -119
- package/cursor-rules/README.md +0 -192
- package/dist/DataTable-AOVNCPTX.js +0 -175
- package/dist/DataTable-AOVNCPTX.js.map +0 -1
- package/dist/UnifiedAuthProvider-4SBX4LU5.js +0 -18
- package/dist/UnifiedAuthProvider-4SBX4LU5.js.map +0 -1
- package/dist/api-O6HTBX5Y.js +0 -52
- package/dist/api-O6HTBX5Y.js.map +0 -1
- package/dist/audit-V53FV5AG.js +0 -17
- package/dist/audit-V53FV5AG.js.map +0 -1
- package/dist/chunk-5DRSZLL2.js.map +0 -1
- package/dist/chunk-63FOKYGO.js.map +0 -1
- package/dist/chunk-6COVEUS7.js.map +0 -1
- package/dist/chunk-AFVQODI2.js +0 -263
- package/dist/chunk-AFVQODI2.js.map +0 -1
- package/dist/chunk-DGUM43GV.js.map +0 -1
- package/dist/chunk-E66EQZE6.js.map +0 -1
- package/dist/chunk-EFN2EIMK.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-G7QEZTYQ.js +0 -2053
- package/dist/chunk-G7QEZTYQ.js.map +0 -1
- package/dist/chunk-HU2C6SSC.js.map +0 -1
- package/dist/chunk-IHB5DR3H.js.map +0 -1
- package/dist/chunk-IVOFDYWT.js.map +0 -1
- package/dist/chunk-J36DSWQK.js.map +0 -1
- package/dist/chunk-JGRYX5UX.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-NTM7ZSB6.js.map +0 -1
- package/dist/chunk-PWLANIRT.js.map +0 -1
- package/dist/chunk-QXHPKYJV.js.map +0 -1
- package/dist/chunk-RGAWHO7N.js.map +0 -1
- package/dist/chunk-UPPMRMYG.js.map +0 -1
- package/dist/chunk-VBXEHIUJ.js.map +0 -1
- package/dist/chunk-ZSAAAMVR.js.map +0 -1
- package/dist/components.js.map +0 -1
- package/dist/contextValidator-5OGXSPKS.js +0 -9
- package/dist/contextValidator-5OGXSPKS.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/best-practices/README.md +0 -472
- package/docs/best-practices/accessibility.md +0 -601
- package/docs/best-practices/common-patterns.md +0 -516
- package/docs/best-practices/deployment.md +0 -1103
- package/docs/best-practices/performance.md +0 -1328
- package/docs/best-practices/security.md +0 -940
- package/docs/best-practices/testing.md +0 -1034
- package/docs/rbac/compliance/compliance-guide.md +0 -544
- 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/04-code-style-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/index.cjs +0 -223
- 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/components/DataTable/components/DataTableBody.tsx +0 -454
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
- package/src/components/DataTable/components/ExpandButton.tsx +0 -113
- package/src/components/DataTable/components/GroupHeader.tsx +0 -54
- package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
- package/src/components/DataTable/core/DataTableContext.tsx +0 -216
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
- package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
- package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
- package/src/components/DataTable/utils/debugTools.ts +0 -514
- 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,584 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Code Style Check Module
|
|
5
|
-
* @package @jmruthers/pace-core
|
|
6
|
-
* @module Audit/Checks/Style
|
|
7
|
-
*
|
|
8
|
-
* Checks for:
|
|
9
|
-
* - Inline styles usage
|
|
10
|
-
* - Inconsistent naming conventions
|
|
11
|
-
* - Missing TypeScript types
|
|
12
|
-
* - any type usage
|
|
13
|
-
* - Console.log statements
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
const fs = require('fs');
|
|
17
|
-
const path = require('path');
|
|
18
|
-
const { getRelativePath, getLineNumber } = require('../utils.cjs');
|
|
19
|
-
|
|
20
|
-
const styleCheck = {
|
|
21
|
-
name: 'style',
|
|
22
|
-
description: 'Code style issues (inline styles, any types, console.log)',
|
|
23
|
-
severity: 'warning',
|
|
24
|
-
|
|
25
|
-
async run(context) {
|
|
26
|
-
const { projectRoot, files } = context;
|
|
27
|
-
const issues = [];
|
|
28
|
-
const warnings = [];
|
|
29
|
-
const suggestions = [];
|
|
30
|
-
|
|
31
|
-
if (!files || files.length === 0) {
|
|
32
|
-
return { issues, warnings, suggestions };
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
for (const filePath of files) {
|
|
36
|
-
try {
|
|
37
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
38
|
-
const relativePath = getRelativePath(filePath, projectRoot);
|
|
39
|
-
const normalizedPath = relativePath.replace(/\\/g, '/');
|
|
40
|
-
|
|
41
|
-
// Skip root-level src directory - in pace-core repository, this is a demo/showcase app
|
|
42
|
-
// Note: We DO check packages/core/ files because style issues (any types, console.log, inline styles) are real issues that should be fixed
|
|
43
|
-
const isRootSrc = normalizedPath.startsWith('src/') && !normalizedPath.includes('packages/');
|
|
44
|
-
if (isRootSrc) {
|
|
45
|
-
continue; // Skip demo app files
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Skip scripts directory - utility scripts don't need style validation
|
|
49
|
-
const isScript = normalizedPath.startsWith('scripts/') || normalizedPath.includes('/scripts/');
|
|
50
|
-
if (isScript) {
|
|
51
|
-
continue; // Skip script files
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Skip test setup, teardown, and configuration files - these are test infrastructure
|
|
55
|
-
// Test setup/teardown files legitimately use 'any' types for mocking and may have simpler type annotations
|
|
56
|
-
const fileName = path.basename(normalizedPath);
|
|
57
|
-
const isTestInfrastructure = normalizedPath.includes('.setup.') ||
|
|
58
|
-
normalizedPath.includes('.teardown.') ||
|
|
59
|
-
normalizedPath.includes('.config.') ||
|
|
60
|
-
normalizedPath.includes('setupTests') ||
|
|
61
|
-
normalizedPath.includes('test-setup') ||
|
|
62
|
-
normalizedPath.includes('test-setup.') ||
|
|
63
|
-
fileName.match(/^(vitest|jest|setupTests)\.(setup|teardown)\.(ts|js|tsx|jsx)$/i) ||
|
|
64
|
-
fileName.match(/\.(setup|teardown)\.(ts|js|tsx|jsx)$/i) ||
|
|
65
|
-
fileName.match(/^test-setup\.(ts|js|tsx|jsx)$/i);
|
|
66
|
-
if (isTestInfrastructure) {
|
|
67
|
-
continue; // Skip test infrastructure files
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Skip example files - these are demo/showcase code, not production code
|
|
71
|
-
const isExample = normalizedPath.includes('/examples/') ||
|
|
72
|
-
normalizedPath.includes('/example/') ||
|
|
73
|
-
fileName.includes('Example');
|
|
74
|
-
if (isExample) {
|
|
75
|
-
continue; // Skip example files
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Skip logger utility files - they intentionally use console.* and any[] for variadic arguments
|
|
79
|
-
const isLogger = normalizedPath.includes('/utils/core/logger') ||
|
|
80
|
-
normalizedPath.includes('/utils/core/debugLogger') ||
|
|
81
|
-
(normalizedPath.includes('/rbac/config') && content.includes('createLogger') && content.includes('RBACLogger'));
|
|
82
|
-
if (isLogger) {
|
|
83
|
-
continue; // Skip logger utilities
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Skip development utility files - these are meant to log to console for development/debugging
|
|
87
|
-
const isDevUtility = normalizedPath.includes('/utils/performance/') ||
|
|
88
|
-
normalizedPath.includes('/utils/debug/') ||
|
|
89
|
-
normalizedPath.includes('/utils/development/');
|
|
90
|
-
if (isDevUtility) {
|
|
91
|
-
continue; // Skip development utilities
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Check for inline styles
|
|
95
|
-
const inlineStylePattern = /style\s*=\s*\{\{/g;
|
|
96
|
-
let styleMatch;
|
|
97
|
-
while ((styleMatch = inlineStylePattern.exec(content)) !== null) {
|
|
98
|
-
// Get context around the inline style to check if it's necessary
|
|
99
|
-
const contextStart = Math.max(0, styleMatch.index - 100);
|
|
100
|
-
const contextEnd = Math.min(content.length, styleMatch.index + 300);
|
|
101
|
-
const context = content.substring(contextStart, contextEnd);
|
|
102
|
-
|
|
103
|
-
// Skip empty style objects - these are harmless placeholders
|
|
104
|
-
// Check if the style attribute contains only empty braces: style={{}}
|
|
105
|
-
// Look ahead from the match position to find the closing braces
|
|
106
|
-
const afterMatch = content.substring(styleMatch.index, Math.min(content.length, styleMatch.index + 50));
|
|
107
|
-
// Match patterns like: style={{}} or style={{ }} or style={{ }}
|
|
108
|
-
const isEmptyStyle = /style\s*=\s*\{\s*\{\s*\}\s*\}/.test(afterMatch);
|
|
109
|
-
if (isEmptyStyle) {
|
|
110
|
-
continue; // Skip empty style objects
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Skip legitimate inline styles that can't be replaced with Tailwind:
|
|
114
|
-
// 1. Dynamic positioning (top/bottom based on direction)
|
|
115
|
-
// 2. Dynamic maxHeight/maxWidth from props
|
|
116
|
-
// 3. Virtual scrolling styles (transform, position: absolute with dynamic values)
|
|
117
|
-
// 4. Dynamic height/width from props or calculations
|
|
118
|
-
// 5. Dynamic indentation/padding for hierarchical data
|
|
119
|
-
const isDynamicPositioning = context.includes('[opensUpward') ||
|
|
120
|
-
context.includes('direction') ||
|
|
121
|
-
context.includes('opensUpward ?') ||
|
|
122
|
-
context.includes('direction ===');
|
|
123
|
-
|
|
124
|
-
const isVirtualization = context.includes('transform') &&
|
|
125
|
-
(context.includes('translateY') || context.includes('translateX')) &&
|
|
126
|
-
(context.includes('virtualRow') || context.includes('virtualItem') || context.includes('virtualizer'));
|
|
127
|
-
|
|
128
|
-
const isDynamicSize = (context.includes('maxHeight') || context.includes('maxWidth') ||
|
|
129
|
-
context.includes('minHeight') || context.includes('minWidth') ||
|
|
130
|
-
context.includes('height:') || context.includes('width:') ||
|
|
131
|
-
context.includes('totalSize') || context.includes('virtualRow.size')) &&
|
|
132
|
-
!context.includes('style={{}}'); // But not empty objects
|
|
133
|
-
|
|
134
|
-
// Skip dynamic indentation/padding for hierarchical rows
|
|
135
|
-
const isDynamicIndentation = (context.includes('paddingLeft') || context.includes('paddingRight') ||
|
|
136
|
-
context.includes('indentation') || context.includes('indent')) &&
|
|
137
|
-
(context.includes('px') || context.includes('${'));
|
|
138
|
-
|
|
139
|
-
// Skip if it's just pointerEvents and className already has pointer-events-none
|
|
140
|
-
const isRedundantPointerEvents = context.includes('pointerEvents') &&
|
|
141
|
-
context.includes('pointer-events-none');
|
|
142
|
-
|
|
143
|
-
// Skip text overflow styles that are necessary for ellipsis
|
|
144
|
-
const isTextOverflow = context.includes('textOverflow') ||
|
|
145
|
-
context.includes('whiteSpace') ||
|
|
146
|
-
context.includes('overflow:') && context.includes('hidden');
|
|
147
|
-
|
|
148
|
-
if (isDynamicPositioning || isVirtualization || (isDynamicSize && !isEmptyStyle) || isTextOverflow || isDynamicIndentation) {
|
|
149
|
-
continue; // Skip dynamic styles that require runtime values
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (isRedundantPointerEvents) {
|
|
153
|
-
continue; // Skip redundant pointer events
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
warnings.push({
|
|
157
|
-
type: 'inline-style',
|
|
158
|
-
file: relativePath,
|
|
159
|
-
line: getLineNumber(content, styleMatch.index),
|
|
160
|
-
message: 'Inline style detected',
|
|
161
|
-
recommendation: 'Use Tailwind classes or pace-core component props instead of inline styles'
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Check for console.log in non-test files, but exclude CLI scripts and development utilities
|
|
166
|
-
if (!relativePath.includes('.test.') && !relativePath.includes('.spec.')) {
|
|
167
|
-
// Check if this is a CLI script (has shebang or is in scripts/ directory)
|
|
168
|
-
const isCLIScript = content.startsWith('#!/usr/bin/env node') ||
|
|
169
|
-
content.startsWith('#!/bin/node') ||
|
|
170
|
-
content.startsWith('#!/bin/env node') ||
|
|
171
|
-
relativePath.includes('/scripts/') ||
|
|
172
|
-
relativePath.startsWith('scripts/');
|
|
173
|
-
|
|
174
|
-
// Skip RBAC config - it's a logger utility that intentionally uses console methods
|
|
175
|
-
const isRBACConfig = normalizedPath.includes('/rbac/config');
|
|
176
|
-
|
|
177
|
-
// Skip development utilities - these are meant to log to console
|
|
178
|
-
const isDevUtility = normalizedPath.includes('/utils/performance/') ||
|
|
179
|
-
normalizedPath.includes('/utils/debug/') ||
|
|
180
|
-
normalizedPath.includes('/utils/development/');
|
|
181
|
-
|
|
182
|
-
if (!isCLIScript && !isRBACConfig && !isDevUtility) {
|
|
183
|
-
const consoleLogPattern = /console\.(log|debug|info)\s*\(/g;
|
|
184
|
-
let consoleMatch;
|
|
185
|
-
while ((consoleMatch = consoleLogPattern.exec(content)) !== null) {
|
|
186
|
-
// Skip if it's in a comment (JSDoc examples, etc.)
|
|
187
|
-
const beforeMatch = content.substring(Math.max(0, consoleMatch.index - 150), consoleMatch.index);
|
|
188
|
-
const afterMatch = content.substring(consoleMatch.index, Math.min(content.length, consoleMatch.index + 50));
|
|
189
|
-
|
|
190
|
-
// Check if it's in a comment block (JSDoc, regular comments)
|
|
191
|
-
// Look for JSDoc comment markers (* at start of line) or regular comment markers
|
|
192
|
-
const isInJSDocComment = beforeMatch.match(/\n\s*\*\s/) || beforeMatch.match(/\/\*\*/);
|
|
193
|
-
const isInRegularComment = beforeMatch.includes('//') || beforeMatch.includes('/*');
|
|
194
|
-
const isInComment = isInJSDocComment || isInRegularComment;
|
|
195
|
-
|
|
196
|
-
// Check if it's in a code example within JSDoc (between ``` markers or in @example blocks)
|
|
197
|
-
const beforeCode = content.substring(Math.max(0, consoleMatch.index - 500), consoleMatch.index);
|
|
198
|
-
const isInCodeBlock = beforeCode.includes('```') &&
|
|
199
|
-
(beforeCode.match(/```/g) || []).length % 2 === 1; // Odd number of ``` means we're inside a code block
|
|
200
|
-
const isInJSDocExample = beforeMatch.match(/\*\s*@example/) ||
|
|
201
|
-
beforeMatch.match(/\*\s*```/) ||
|
|
202
|
-
beforeMatch.match(/\*\s*</); // JSX in JSDoc examples
|
|
203
|
-
const isInCodeExample = isInCodeBlock || isInJSDocExample;
|
|
204
|
-
|
|
205
|
-
// Check if it's wrapped in a development check (process.env.NODE_ENV === 'development')
|
|
206
|
-
const contextForDevCheck = content.substring(Math.max(0, consoleMatch.index - 200), Math.min(content.length, consoleMatch.index + 200));
|
|
207
|
-
const isInDevCheck = contextForDevCheck.includes('process.env.NODE_ENV') &&
|
|
208
|
-
(contextForDevCheck.includes("=== 'development'") ||
|
|
209
|
-
contextForDevCheck.includes('=== "development"') ||
|
|
210
|
-
contextForDevCheck.includes("== 'development'") ||
|
|
211
|
-
contextForDevCheck.includes('== "development"'));
|
|
212
|
-
|
|
213
|
-
if (isInComment || isInCodeExample || isInDevCheck) {
|
|
214
|
-
continue; // Skip console.log in comments/documentation/code examples or development checks
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
warnings.push({
|
|
218
|
-
type: 'console-log',
|
|
219
|
-
file: relativePath,
|
|
220
|
-
line: getLineNumber(content, consoleMatch.index),
|
|
221
|
-
message: `console.${consoleMatch[1]} found in production code`,
|
|
222
|
-
recommendation: 'Remove console.log statements or use a proper logging utility. CLI scripts in scripts/ directory are allowed to use console output.'
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Check for 'any' type usage in TypeScript files
|
|
229
|
-
if (filePath.match(/\.(ts|tsx)$/)) {
|
|
230
|
-
const anyTypePattern = /:\s*any\b|<\s*any\s*>|any\[\]/g;
|
|
231
|
-
let anyMatch;
|
|
232
|
-
while ((anyMatch = anyTypePattern.exec(content)) !== null) {
|
|
233
|
-
// Skip if it's in a comment or string
|
|
234
|
-
const beforeMatch = content.substring(Math.max(0, anyMatch.index - 50), anyMatch.index);
|
|
235
|
-
const isInComment = beforeMatch.includes('//') || beforeMatch.includes('/*');
|
|
236
|
-
|
|
237
|
-
if (isInComment) {
|
|
238
|
-
continue;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Skip legitimate any[] usage in variadic function arguments (e.g., logger utilities)
|
|
242
|
-
const contextMatch = content.substring(Math.max(0, anyMatch.index - 100), Math.min(content.length, anyMatch.index + 50));
|
|
243
|
-
const isVariadicArg = contextMatch.match(/\.\.\.\s*args?\s*:\s*any\[\]/) ||
|
|
244
|
-
contextMatch.match(/\.\.\.\s*args?\s*:\s*any\b/);
|
|
245
|
-
if (isVariadicArg) {
|
|
246
|
-
continue; // Skip variadic arguments - these are legitimate uses of any[]
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Skip generic cache implementations where any is used for value types
|
|
250
|
-
const isCacheGeneric = contextMatch.includes('CacheEntry<any>') ||
|
|
251
|
-
contextMatch.includes('Map<string, any>') ||
|
|
252
|
-
(contextMatch.includes('Map<') && contextMatch.includes('any>')) ||
|
|
253
|
-
(contextMatch.includes('Map<') && contextMatch.includes('any')) ||
|
|
254
|
-
(contextMatch.includes('cache') && (contextMatch.includes('data: any') || contextMatch.includes('{ data: any'))) ||
|
|
255
|
-
(contextMatch.includes('Cache') && contextMatch.includes('any')) ||
|
|
256
|
-
(contextMatch.includes('new Map') && contextMatch.includes('any'));
|
|
257
|
-
if (isCacheGeneric) {
|
|
258
|
-
continue; // Skip generic cache types - these are legitimate
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Skip generic component types (React.ComponentType<any>, etc.)
|
|
262
|
-
const isGenericComponentType = contextMatch.includes('ComponentType<any>') ||
|
|
263
|
-
contextMatch.includes('React.ComponentType<any>') ||
|
|
264
|
-
(contextMatch.includes('ComponentType') && contextMatch.includes('<any>'));
|
|
265
|
-
if (isGenericComponentType) {
|
|
266
|
-
continue; // Skip generic component types - necessary for dynamic components
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// Skip generic Promise callbacks
|
|
270
|
-
const isPromiseCallback = contextMatch.includes('Promise<any>') ||
|
|
271
|
-
contextMatch.includes('Promise<') && contextMatch.includes('any>') ||
|
|
272
|
-
(contextMatch.includes('Promise') && contextMatch.includes('() => Promise<any>'));
|
|
273
|
-
if (isPromiseCallback) {
|
|
274
|
-
continue; // Skip Promise callbacks with any - necessary for generic async operations
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// Skip props: any in generic wrapper components
|
|
278
|
-
const isGenericProps = (contextMatch.includes('props: any') || contextMatch.includes('props?: any')) &&
|
|
279
|
-
(normalizedPath.includes('/utils/') || normalizedPath.includes('/components/'));
|
|
280
|
-
if (isGenericProps) {
|
|
281
|
-
continue; // Skip generic props - necessary for wrapper components
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Skip this: any in utility functions (throttle, debounce, etc.) - necessary for preserving context
|
|
285
|
-
const isThisContext = contextMatch.includes('this: any') &&
|
|
286
|
-
(normalizedPath.includes('/hooks/') || normalizedPath.includes('/utils/'));
|
|
287
|
-
if (isThisContext) {
|
|
288
|
-
continue; // Skip this: any - necessary for function binding utilities
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Skip any types in generic library components (DataTable, RBAC, etc.)
|
|
292
|
-
// These are necessary for flexibility when working with unknown data structures
|
|
293
|
-
const isGenericLibraryCode =
|
|
294
|
-
// DataTable components - any is necessary for row data flexibility and generic components
|
|
295
|
-
(normalizedPath.includes('/DataTable/') || normalizedPath.includes('/DataTable.tsx')) ||
|
|
296
|
-
// RBAC code - needs any to work with Supabase's dynamic types and unknown data structures
|
|
297
|
-
(normalizedPath.includes('/rbac/')) ||
|
|
298
|
-
// Generic utility functions that need to work with unknown types
|
|
299
|
-
(normalizedPath.includes('/utils/') && (
|
|
300
|
-
contextMatch.includes('unknown') ||
|
|
301
|
-
contextMatch.includes('Record<string') ||
|
|
302
|
-
contextMatch.includes('lazyLoad') ||
|
|
303
|
-
contextMatch.includes('dynamic')
|
|
304
|
-
)) ||
|
|
305
|
-
// Form components that work with generic form data
|
|
306
|
-
(normalizedPath.includes('/Form/') && (
|
|
307
|
-
contextMatch.includes('formData') ||
|
|
308
|
-
contextMatch.includes('values:')
|
|
309
|
-
)) ||
|
|
310
|
-
// React.ReactElement<any> - common React pattern for generic elements
|
|
311
|
-
contextMatch.includes('React.ReactElement<any>') ||
|
|
312
|
-
contextMatch.includes('ReactElement<any>') ||
|
|
313
|
-
// Icon props - common pattern for icon components (can be any icon type)
|
|
314
|
-
(contextMatch.includes('icon') && (contextMatch.includes('?: any') || contextMatch.includes(': any'))) ||
|
|
315
|
-
// Callback functions with generic row/data parameters
|
|
316
|
-
(contextMatch.includes('onClick') && contextMatch.includes('(row: any)')) ||
|
|
317
|
-
(contextMatch.includes('onClick') && contextMatch.includes('(data: any)')) ||
|
|
318
|
-
(contextMatch.includes('callback') && contextMatch.includes(': any')) ||
|
|
319
|
-
// Generic hooks that work with unknown data - exclude all hooks in /hooks/public/ and specific hook files
|
|
320
|
-
(normalizedPath.includes('/hooks/public/')) ||
|
|
321
|
-
(normalizedPath.includes('/hooks/useDataTable')) ||
|
|
322
|
-
(normalizedPath.includes('/hooks/useFileDisplay')) ||
|
|
323
|
-
(normalizedPath.includes('/hooks/useQueryCache')) ||
|
|
324
|
-
(normalizedPath.includes('/hooks/useDataTablePerformance')) ||
|
|
325
|
-
(normalizedPath.includes('/hooks/useDataTableState')) ||
|
|
326
|
-
(normalizedPath.includes('/hooks/useInactivityTracker')) ||
|
|
327
|
-
(normalizedPath.includes('/hooks/') && (
|
|
328
|
-
contextMatch.includes('useDataTable') ||
|
|
329
|
-
contextMatch.includes('useFileDisplay') ||
|
|
330
|
-
contextMatch.includes('usePublic') ||
|
|
331
|
-
contextMatch.includes('useQueryCache') ||
|
|
332
|
-
contextMatch.includes('useInactivityTracker')
|
|
333
|
-
)) ||
|
|
334
|
-
// Calendar component - works with generic event data
|
|
335
|
-
(normalizedPath.includes('/Calendar/')) ||
|
|
336
|
-
// Select component - works with generic option values
|
|
337
|
-
(normalizedPath.includes('/Select/') && (
|
|
338
|
-
contextMatch.includes('value:') ||
|
|
339
|
-
contextMatch.includes('option')
|
|
340
|
-
)) ||
|
|
341
|
-
// OrganisationProvider - works with dynamic organisation data
|
|
342
|
-
(normalizedPath.includes('OrganisationProvider')) ||
|
|
343
|
-
// Theming utilities - work with dynamic color data
|
|
344
|
-
(normalizedPath.includes('/theming/')) ||
|
|
345
|
-
// Services that work with Supabase data - exclude all services working with dynamic data
|
|
346
|
-
(normalizedPath.includes('/services/') && (
|
|
347
|
-
contextMatch.includes('Supabase') ||
|
|
348
|
-
contextMatch.includes('Database') ||
|
|
349
|
-
contextMatch.includes('forEach') ||
|
|
350
|
-
contextMatch.includes('role: any') ||
|
|
351
|
-
contextMatch.includes('data: any') ||
|
|
352
|
-
contextMatch.includes(': any)')
|
|
353
|
-
)) ||
|
|
354
|
-
// Utils directory - many generic utilities, exclude dynamic and request utilities
|
|
355
|
-
(normalizedPath.includes('/utils/dynamic/')) ||
|
|
356
|
-
(normalizedPath.includes('/utils/request-')) ||
|
|
357
|
-
(normalizedPath.includes('/utils/') && (
|
|
358
|
-
contextMatch.includes('lazyLoad') ||
|
|
359
|
-
contextMatch.includes('createLazyComponent') ||
|
|
360
|
-
contextMatch.includes('request-deduplication')
|
|
361
|
-
));
|
|
362
|
-
|
|
363
|
-
if (isGenericLibraryCode) {
|
|
364
|
-
continue; // Skip legitimate any usage in generic library code
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
warnings.push({
|
|
368
|
-
type: 'any-type',
|
|
369
|
-
file: relativePath,
|
|
370
|
-
line: getLineNumber(content, anyMatch.index),
|
|
371
|
-
message: 'TypeScript any type usage detected',
|
|
372
|
-
recommendation: 'Replace any with proper types for better type safety'
|
|
373
|
-
});
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// Check for missing return types on exported functions
|
|
377
|
-
// Skip React components and hooks where TypeScript inference is sufficient
|
|
378
|
-
const exportedFunctionPattern = /export\s+(?:default\s+)?(?:async\s+)?(function|const)\s+(\w+)\s*[=\(]/g;
|
|
379
|
-
let funcMatch;
|
|
380
|
-
while ((funcMatch = exportedFunctionPattern.exec(content)) !== null) {
|
|
381
|
-
const funcName = funcMatch[2];
|
|
382
|
-
// Get more context to handle multi-line function signatures
|
|
383
|
-
const startPos = funcMatch.index;
|
|
384
|
-
const afterMatch = content.substring(startPos, Math.min(content.length, startPos + 800));
|
|
385
|
-
|
|
386
|
-
// For const declarations, check if it's actually a function (arrow function)
|
|
387
|
-
// Skip const declarations that are just values (zod schemas, objects, etc.)
|
|
388
|
-
if (funcMatch[1] === 'const') {
|
|
389
|
-
// Extract the part after the equals sign to check what follows
|
|
390
|
-
const equalsIndex = afterMatch.indexOf('=');
|
|
391
|
-
if (equalsIndex === -1) {
|
|
392
|
-
continue; // No equals sign found, skip
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
const afterEquals = afterMatch.substring(equalsIndex + 1).trim();
|
|
396
|
-
|
|
397
|
-
// Check if it's an arrow function: const name = (...) => ... or const name = async (...) => ...
|
|
398
|
-
const isArrowFunction = /^\s*(?:async\s+)?\([^)]*\)\s*=>/.test(afterEquals) ||
|
|
399
|
-
/^\s*(?:async\s+)?\w+\s*=>/.test(afterEquals) ||
|
|
400
|
-
/^\s*\([^)]*\)\s*:\s*\w+\s*=>/.test(afterEquals);
|
|
401
|
-
|
|
402
|
-
// If it's not an arrow function, it's a const value (zod schema, object, etc.)
|
|
403
|
-
if (!isArrowFunction) {
|
|
404
|
-
continue; // Skip const values - not functions
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// Additional check: if it looks like a value assignment before the arrow function
|
|
408
|
-
// Pattern: const name = z.string()... or const name = new Class()... or const name = {...}
|
|
409
|
-
// But only if there's no arrow function syntax
|
|
410
|
-
const looksLikeValueBeforeArrow = /=\s*(z\.|new\s+\w+\(|\[|{|\d+|'|"|`|true|false|null)/.test(afterMatch);
|
|
411
|
-
if (looksLikeValueBeforeArrow && !isArrowFunction) {
|
|
412
|
-
continue; // Skip const values
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// Skip React hooks - TypeScript infers return types well for hooks
|
|
417
|
-
if (funcName.startsWith('use') && funcName.length > 3) {
|
|
418
|
-
continue; // Skip hooks - inference is sufficient
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// Skip React components - TypeScript infers JSX.Element well
|
|
422
|
-
// Check if function returns JSX (has return statement with JSX or is a component pattern)
|
|
423
|
-
const hasJSXReturn = afterMatch.includes('return (') ||
|
|
424
|
-
afterMatch.includes('return <') ||
|
|
425
|
-
afterMatch.includes('return React') ||
|
|
426
|
-
(afterMatch.includes('React.') && afterMatch.includes('createElement'));
|
|
427
|
-
|
|
428
|
-
// Check if it's a React component by name pattern (PascalCase, ends with Provider, etc.)
|
|
429
|
-
const isComponentName = /^[A-Z]/.test(funcName) ||
|
|
430
|
-
funcName.endsWith('Provider') ||
|
|
431
|
-
funcName.endsWith('Layout') ||
|
|
432
|
-
funcName.endsWith('Modal') ||
|
|
433
|
-
funcName.endsWith('Form') ||
|
|
434
|
-
funcName.endsWith('Button') ||
|
|
435
|
-
funcName.endsWith('Input') ||
|
|
436
|
-
funcName.endsWith('Select');
|
|
437
|
-
|
|
438
|
-
if (hasJSXReturn || isComponentName) {
|
|
439
|
-
continue; // Skip React components - inference is sufficient
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// Skip simple utility functions where return type is obvious
|
|
443
|
-
// (e.g., getX, isX, hasX, createX, parseX, validateX, etc.)
|
|
444
|
-
const isSimpleUtility = /^(get|is|has|create|parse|validate|format|to|from|can|should|will|do|make|build|generate|find|search|filter|map|reduce|sort|compare|check|test|verify|ensure|normalize|sanitize|escape|unescape|encode|decode)/i.test(funcName);
|
|
445
|
-
if (isSimpleUtility && afterMatch.length < 150) {
|
|
446
|
-
// Only skip if function is relatively simple (short context)
|
|
447
|
-
continue; // Skip simple utilities - inference is usually sufficient
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// Check if function has explicit return type
|
|
451
|
-
if (funcMatch[1] === 'function') {
|
|
452
|
-
// function name(...): returnType
|
|
453
|
-
// Look for closing paren followed by colon and then any type annotation
|
|
454
|
-
// This matches: ): Type, ): Promise<Type>, ): 'type' | 'type', ): { ... }, etc.
|
|
455
|
-
// Handle both single-line and multi-line function signatures
|
|
456
|
-
|
|
457
|
-
// Find the function body opening brace
|
|
458
|
-
const braceIndex = afterMatch.indexOf('{');
|
|
459
|
-
if (braceIndex === -1) {
|
|
460
|
-
continue; // No function body found, might be a type declaration
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
// Get everything before the opening brace (the function signature)
|
|
464
|
-
const funcSignature = afterMatch.substring(0, braceIndex);
|
|
465
|
-
|
|
466
|
-
// Check if there's a return type annotation
|
|
467
|
-
// Look for closing paren followed by colon (allowing whitespace/newlines)
|
|
468
|
-
// Then check for any non-whitespace character (start of return type)
|
|
469
|
-
// This handles:
|
|
470
|
-
// - ): Type
|
|
471
|
-
// - ): Promise<void>
|
|
472
|
-
// - ): 'type' | 'type'
|
|
473
|
-
// - ): { ... }
|
|
474
|
-
// - Multi-line: )\n: Type
|
|
475
|
-
// - Multi-line async: )\n: Promise<Type>
|
|
476
|
-
|
|
477
|
-
// Find the last closing paren (end of parameter list)
|
|
478
|
-
// Then check if there's a colon after it (return type annotation)
|
|
479
|
-
let lastParenIndex = -1;
|
|
480
|
-
let depth = 0;
|
|
481
|
-
let inString = false;
|
|
482
|
-
let stringChar = '';
|
|
483
|
-
|
|
484
|
-
// Find the last closing paren that's not inside nested parens (parameter list end)
|
|
485
|
-
// Start from the function name position to find the opening paren of the parameter list
|
|
486
|
-
const funcNameMatch = funcSignature.match(new RegExp(`\\b${funcName}\\s*\\(`));
|
|
487
|
-
const startSearchIndex = funcNameMatch ? funcNameMatch.index + funcNameMatch[0].length - 1 : 0;
|
|
488
|
-
|
|
489
|
-
for (let i = startSearchIndex; i < funcSignature.length; i++) {
|
|
490
|
-
const char = funcSignature[i];
|
|
491
|
-
|
|
492
|
-
// Handle string literals
|
|
493
|
-
if ((char === '"' || char === "'" || char === '`') && (i === 0 || funcSignature[i - 1] !== '\\')) {
|
|
494
|
-
if (!inString) {
|
|
495
|
-
inString = true;
|
|
496
|
-
stringChar = char;
|
|
497
|
-
} else if (char === stringChar) {
|
|
498
|
-
inString = false;
|
|
499
|
-
stringChar = '';
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
if (!inString) {
|
|
504
|
-
if (char === '(') depth++;
|
|
505
|
-
else if (char === ')') {
|
|
506
|
-
depth--;
|
|
507
|
-
if (depth === 0) {
|
|
508
|
-
lastParenIndex = i; // This is the end of the parameter list
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
// Check if there's a return type after the last closing paren
|
|
515
|
-
let hasReturnType = false;
|
|
516
|
-
if (lastParenIndex >= 0) {
|
|
517
|
-
const afterLastParen = funcSignature.substring(lastParenIndex);
|
|
518
|
-
// Look for colon followed by non-whitespace (return type)
|
|
519
|
-
// Normalize whitespace to handle multi-line signatures
|
|
520
|
-
const normalizedAfterParen = afterLastParen.replace(/\s+/g, ' ');
|
|
521
|
-
hasReturnType = /\)\s*:\s*\S/.test(normalizedAfterParen);
|
|
522
|
-
} else {
|
|
523
|
-
// Fallback: check if there's a colon anywhere in the signature (might be a return type)
|
|
524
|
-
// This handles edge cases where paren tracking might fail
|
|
525
|
-
const hasColonBeforeBrace = funcSignature.includes(':') &&
|
|
526
|
-
funcSignature.lastIndexOf(':') < braceIndex &&
|
|
527
|
-
funcSignature.lastIndexOf(':') > funcSignature.indexOf('(');
|
|
528
|
-
if (hasColonBeforeBrace) {
|
|
529
|
-
// Check if the colon is followed by a type (not a default value)
|
|
530
|
-
const colonIndex = funcSignature.lastIndexOf(':');
|
|
531
|
-
const afterColon = funcSignature.substring(colonIndex + 1, braceIndex).trim();
|
|
532
|
-
// If after colon we see a type-like pattern (starts with letter, Promise, {, [, etc.)
|
|
533
|
-
hasReturnType = /^[A-Za-z_$]|^Promise|^\{|^\[|^'|^"/.test(afterColon);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
if (!hasReturnType) {
|
|
538
|
-
suggestions.push({
|
|
539
|
-
type: 'missing-return-type',
|
|
540
|
-
file: relativePath,
|
|
541
|
-
line: getLineNumber(content, funcMatch.index),
|
|
542
|
-
message: `Exported function '${funcName}' missing explicit return type`,
|
|
543
|
-
recommendation: 'Add explicit return type annotation for better type safety'
|
|
544
|
-
});
|
|
545
|
-
}
|
|
546
|
-
} else {
|
|
547
|
-
// const name = (...) => ...
|
|
548
|
-
// Check if arrow function has return type
|
|
549
|
-
// Match: const name = (...): ReturnType => ...
|
|
550
|
-
// Look for ): before the => arrow
|
|
551
|
-
const arrowIndex = afterMatch.indexOf('=>');
|
|
552
|
-
if (arrowIndex > 0) {
|
|
553
|
-
const beforeArrow = afterMatch.substring(0, arrowIndex);
|
|
554
|
-
// Check if there's a return type annotation (): Type) before the arrow
|
|
555
|
-
// Normalize newlines to spaces for matching
|
|
556
|
-
const hasArrowReturnType = /\)\s*:\s*\S/.test(beforeArrow.replace(/\n/g, ' '));
|
|
557
|
-
|
|
558
|
-
if (!hasArrowReturnType) {
|
|
559
|
-
suggestions.push({
|
|
560
|
-
type: 'missing-return-type',
|
|
561
|
-
file: relativePath,
|
|
562
|
-
line: getLineNumber(content, funcMatch.index),
|
|
563
|
-
message: `Exported function '${funcName}' missing explicit return type`,
|
|
564
|
-
recommendation: 'Add explicit return type annotation: const name = (...): ReturnType => ...'
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
// Check for inconsistent naming (simplified)
|
|
573
|
-
// This would need more sophisticated analysis
|
|
574
|
-
|
|
575
|
-
} catch (error) {
|
|
576
|
-
// Skip files with errors
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
return { issues, warnings, suggestions };
|
|
581
|
-
}
|
|
582
|
-
};
|
|
583
|
-
|
|
584
|
-
module.exports = styleCheck;
|