@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
|
@@ -5,8 +5,16 @@
|
|
|
5
5
|
* @package @jmruthers/pace-core
|
|
6
6
|
* @module Scripts/install-cursor-rules
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Sets up cursor rules:
|
|
9
|
+
* - Copies cursor rules from pace-core to consuming app's .cursor/rules/ directory
|
|
10
|
+
*
|
|
9
11
|
* This is an opt-in script - it does NOT run automatically via postinstall.
|
|
12
|
+
*
|
|
13
|
+
* For ESLint setup, use install-eslint-config.cjs separately.
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* node install-cursor-rules.cjs # Install cursor rules
|
|
17
|
+
* node install-cursor-rules.cjs --force # Force update even if already configured
|
|
10
18
|
*/
|
|
11
19
|
|
|
12
20
|
const fs = require('fs');
|
|
@@ -171,9 +179,11 @@ function installCursorRules(force = false) {
|
|
|
171
179
|
const sourcePath = path.join(sourceDir, file);
|
|
172
180
|
const targetPath = path.join(targetDir, file);
|
|
173
181
|
|
|
174
|
-
// Check if this is a pace-core rule (00-
|
|
182
|
+
// Check if this is a pace-core rule (00-49) or app rule (50+)
|
|
183
|
+
// pace-core rules: 00-49 (currently 00-12, but leaving room for expansion)
|
|
184
|
+
// app rules: 50+ (custom rules for consuming apps)
|
|
175
185
|
const ruleNumber = parseInt(file.match(/^(\d+)-/)?.[1] || '99');
|
|
176
|
-
const isPaceCoreRule = ruleNumber >= 0 && ruleNumber <=
|
|
186
|
+
const isPaceCoreRule = ruleNumber >= 0 && ruleNumber <= 49;
|
|
177
187
|
|
|
178
188
|
if (fs.existsSync(targetPath)) {
|
|
179
189
|
if (isPaceCoreRule) {
|
|
@@ -208,18 +218,24 @@ function installCursorRules(force = false) {
|
|
|
208
218
|
console.log(`${colors.cyan}Restart Cursor to load the new rules.${colors.reset}`);
|
|
209
219
|
}
|
|
210
220
|
|
|
221
|
+
|
|
211
222
|
// Main execution
|
|
212
223
|
function main() {
|
|
213
224
|
const force = process.argv.includes('--force');
|
|
214
225
|
|
|
215
226
|
if (force) {
|
|
216
|
-
console.log(`${colors.yellow}Warning: --force flag is set. This will overwrite existing
|
|
227
|
+
console.log(`${colors.yellow}Warning: --force flag is set. This will overwrite existing configurations.${colors.reset}\n`);
|
|
217
228
|
}
|
|
218
229
|
|
|
219
230
|
try {
|
|
220
231
|
installCursorRules(force);
|
|
232
|
+
|
|
233
|
+
console.log(`\n${colors.cyan}Next steps:${colors.reset}`);
|
|
234
|
+
console.log(` • Restart Cursor to load the new rules`);
|
|
235
|
+
console.log(` • For ESLint setup, run: ${colors.bold}node node_modules/@jmruthers/pace-core/scripts/install-eslint-config.cjs${colors.reset}`);
|
|
236
|
+
|
|
221
237
|
} catch (error) {
|
|
222
|
-
console.error(`${colors.red}Error
|
|
238
|
+
console.error(`${colors.red}Error during setup:${colors.reset}`);
|
|
223
239
|
console.error(error.message);
|
|
224
240
|
if (error.stack) {
|
|
225
241
|
console.error(error.stack);
|
|
@@ -233,4 +249,7 @@ if (require.main === module) {
|
|
|
233
249
|
main();
|
|
234
250
|
}
|
|
235
251
|
|
|
236
|
-
module.exports = {
|
|
252
|
+
module.exports = {
|
|
253
|
+
installCursorRules,
|
|
254
|
+
getCursorRulesTarget
|
|
255
|
+
};
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Installation Script for pace-core ESLint Config
|
|
5
|
+
* @package @jmruthers/pace-core
|
|
6
|
+
* @module Scripts/install-eslint-config
|
|
7
|
+
*
|
|
8
|
+
* Sets up pace-core ESLint configuration in consuming apps.
|
|
9
|
+
* Adds pace-core ESLint config to consuming app's ESLint configuration.
|
|
10
|
+
*
|
|
11
|
+
* This is an opt-in script - it does NOT run automatically via postinstall.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* node install-eslint-config.cjs # Setup ESLint config
|
|
15
|
+
* node install-eslint-config.cjs --force # Force update even if already configured
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
// Check for safety guards
|
|
22
|
+
function checkSafetyGuards() {
|
|
23
|
+
// Check environment variable
|
|
24
|
+
if (process.env.PACE_ESLINT_CONFIG_DISABLED === '1') {
|
|
25
|
+
console.log(`${colors.yellow}Skipping ESLint config installation: PACE_ESLINT_CONFIG_DISABLED=1${colors.reset}`);
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check for .git folder (safety guard for CI)
|
|
30
|
+
const cwd = process.cwd();
|
|
31
|
+
if (!fs.existsSync(path.join(cwd, '.git'))) {
|
|
32
|
+
console.log(`${colors.yellow}Skipping ESLint config installation: No .git folder found${colors.reset}`);
|
|
33
|
+
console.log(`${colors.yellow}This is a safety guard. If you want to install anyway, run with --force${colors.reset}`);
|
|
34
|
+
if (!process.argv.includes('--force')) {
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ANSI color codes for terminal output
|
|
41
|
+
const colors = {
|
|
42
|
+
reset: '\x1b[0m',
|
|
43
|
+
green: '\x1b[32m',
|
|
44
|
+
yellow: '\x1b[33m',
|
|
45
|
+
blue: '\x1b[34m',
|
|
46
|
+
cyan: '\x1b[36m',
|
|
47
|
+
bold: '\x1b[1m',
|
|
48
|
+
red: '\x1b[31m'
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Find existing ESLint config file
|
|
52
|
+
function findESLintConfig() {
|
|
53
|
+
const cwd = process.cwd();
|
|
54
|
+
const possibleConfigs = [
|
|
55
|
+
'eslint.config.js',
|
|
56
|
+
'eslint.config.cjs',
|
|
57
|
+
'eslint.config.mjs',
|
|
58
|
+
'.eslintrc.js',
|
|
59
|
+
'.eslintrc.cjs',
|
|
60
|
+
'.eslintrc.json',
|
|
61
|
+
'.eslintrc.yaml',
|
|
62
|
+
'.eslintrc.yml',
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
for (const configFile of possibleConfigs) {
|
|
66
|
+
const configPath = path.join(cwd, configFile);
|
|
67
|
+
if (fs.existsSync(configPath)) {
|
|
68
|
+
return { path: configPath, name: configFile, isESM: configFile.endsWith('.js') || configFile.endsWith('.mjs') };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Check if pace-core config is already included
|
|
76
|
+
function hasPaceCoreConfig(configContent) {
|
|
77
|
+
// Check for pace-core config import/require
|
|
78
|
+
const paceCorePatterns = [
|
|
79
|
+
/@jmruthers\/pace-core\/eslint-config/,
|
|
80
|
+
/pace-core\/eslint-config/,
|
|
81
|
+
/paceCoreConfig/,
|
|
82
|
+
/pace-core-compliance/,
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
return paceCorePatterns.some(pattern => pattern.test(configContent));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Detect if file is ES module
|
|
89
|
+
function isESModule(filePath, content) {
|
|
90
|
+
if (filePath.endsWith('.mjs')) return true;
|
|
91
|
+
if (filePath.endsWith('.cjs')) return false;
|
|
92
|
+
if (filePath.endsWith('.js')) {
|
|
93
|
+
// Check for ES module indicators
|
|
94
|
+
return /^import\s+.*from|^export\s+default/.test(content.trim());
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Backup file before modification
|
|
100
|
+
function backupFile(filePath) {
|
|
101
|
+
const backupPath = `${filePath}.backup.${Date.now()}`;
|
|
102
|
+
fs.copyFileSync(filePath, backupPath);
|
|
103
|
+
return backupPath;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Setup ESLint configuration
|
|
107
|
+
function setupESLintConfig(force = false) {
|
|
108
|
+
const cwd = process.cwd();
|
|
109
|
+
const existingConfig = findESLintConfig();
|
|
110
|
+
|
|
111
|
+
if (existingConfig) {
|
|
112
|
+
// Read existing config
|
|
113
|
+
let content = fs.readFileSync(existingConfig.path, 'utf8');
|
|
114
|
+
const isESM = isESModule(existingConfig.path, content);
|
|
115
|
+
const format = isESM ? 'ES Module' : 'CommonJS';
|
|
116
|
+
|
|
117
|
+
console.log(`${colors.cyan}Found ESLint config:${colors.reset} ${existingConfig.name} (${format})`);
|
|
118
|
+
|
|
119
|
+
// Check if already configured
|
|
120
|
+
if (hasPaceCoreConfig(content)) {
|
|
121
|
+
if (!force) {
|
|
122
|
+
console.log(`${colors.blue}○${colors.reset} ${existingConfig.name} already includes pace-core rules`);
|
|
123
|
+
console.log(`${colors.blue} Use --force to update.${colors.reset}`);
|
|
124
|
+
return { action: 'skipped', file: existingConfig.name, format };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
console.log(`${colors.yellow}Updating existing ESLint config...${colors.reset}`);
|
|
128
|
+
} else {
|
|
129
|
+
console.log(`${colors.cyan}Adding pace-core config to ${existingConfig.name}...${colors.reset}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Backup before modification
|
|
133
|
+
const backupPath = backupFile(existingConfig.path);
|
|
134
|
+
console.log(`${colors.cyan} Backed up to ${path.basename(backupPath)}${colors.reset}`);
|
|
135
|
+
|
|
136
|
+
// Add pace-core config
|
|
137
|
+
if (isESM) {
|
|
138
|
+
// ES Module format
|
|
139
|
+
if (!content.includes('import paceCoreConfig')) {
|
|
140
|
+
// Add import at top (after other imports if they exist)
|
|
141
|
+
const importLines = content.match(/^(import\s+[^;]+;?\s*\n)+/m);
|
|
142
|
+
if (importLines) {
|
|
143
|
+
// Add after existing imports
|
|
144
|
+
content = content.replace(
|
|
145
|
+
importLines[0],
|
|
146
|
+
`${importLines[0]}import paceCoreConfig from '@jmruthers/pace-core/eslint-config';\n`
|
|
147
|
+
);
|
|
148
|
+
} else {
|
|
149
|
+
// Add at the beginning
|
|
150
|
+
content = `import paceCoreConfig from '@jmruthers/pace-core/eslint-config';\n${content}`;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Add to export default array
|
|
155
|
+
if (content.includes('export default [')) {
|
|
156
|
+
// Already an array, add paceCoreConfig at the beginning
|
|
157
|
+
if (!content.includes('...paceCoreConfig')) {
|
|
158
|
+
content = content.replace(
|
|
159
|
+
/(export\s+default\s*\[)\s*/,
|
|
160
|
+
'$1\n ...paceCoreConfig,'
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
} else if (content.includes('export default')) {
|
|
164
|
+
// Not an array, wrap it
|
|
165
|
+
const exportMatch = content.match(/(export\s+default\s+)(.+?)(;?\s*$)/s);
|
|
166
|
+
if (exportMatch) {
|
|
167
|
+
content = content.replace(
|
|
168
|
+
exportMatch[0],
|
|
169
|
+
`${exportMatch[1]}[\n ...paceCoreConfig,\n ${exportMatch[2]}\n];`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
// CommonJS format
|
|
175
|
+
if (!content.includes('require(\'@jmruthers/pace-core/eslint-config\')')) {
|
|
176
|
+
// Add require at top (after other requires if they exist)
|
|
177
|
+
const requireLines = content.match(/^(const\s+\w+\s*=\s*require\([^)]+\);\s*\n)+/m);
|
|
178
|
+
if (requireLines) {
|
|
179
|
+
content = content.replace(
|
|
180
|
+
requireLines[0],
|
|
181
|
+
`${requireLines[0]}const paceCoreConfig = require('@jmruthers/pace-core/eslint-config');\n`
|
|
182
|
+
);
|
|
183
|
+
} else {
|
|
184
|
+
content = `const paceCoreConfig = require('@jmruthers/pace-core/eslint-config');\n${content}`;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Add to module.exports
|
|
189
|
+
if (content.includes('module.exports = [')) {
|
|
190
|
+
// Already an array, add paceCoreConfig at the beginning
|
|
191
|
+
if (!content.includes('...paceCoreConfig')) {
|
|
192
|
+
content = content.replace(
|
|
193
|
+
/(module\.exports\s*=\s*\[)\s*/,
|
|
194
|
+
'$1\n ...paceCoreConfig,'
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
} else if (content.includes('module.exports =')) {
|
|
198
|
+
// Not an array, wrap it
|
|
199
|
+
const exportMatch = content.match(/(module\.exports\s*=\s*)(.+?)(;?\s*$)/s);
|
|
200
|
+
if (exportMatch) {
|
|
201
|
+
content = content.replace(
|
|
202
|
+
exportMatch[0],
|
|
203
|
+
`${exportMatch[1]}[\n ...paceCoreConfig,\n ${exportMatch[2]}\n];`
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Write updated config
|
|
210
|
+
fs.writeFileSync(existingConfig.path, content, 'utf8');
|
|
211
|
+
console.log(`${colors.green}✓${colors.reset} Updated ${existingConfig.name}`);
|
|
212
|
+
return { action: 'updated', file: existingConfig.name, backup: backupPath, format };
|
|
213
|
+
} else {
|
|
214
|
+
// Create new ESLint config (default to ES modules)
|
|
215
|
+
const configPath = path.join(cwd, 'eslint.config.js');
|
|
216
|
+
const configContent = `import paceCoreConfig from '@jmruthers/pace-core/eslint-config';
|
|
217
|
+
|
|
218
|
+
export default [
|
|
219
|
+
...paceCoreConfig,
|
|
220
|
+
// Your app-specific ESLint configuration
|
|
221
|
+
{
|
|
222
|
+
// Add your rules here
|
|
223
|
+
},
|
|
224
|
+
];
|
|
225
|
+
`;
|
|
226
|
+
|
|
227
|
+
console.log(`${colors.cyan}No ESLint config found. Creating eslint.config.js...${colors.reset}`);
|
|
228
|
+
fs.writeFileSync(configPath, configContent, 'utf8');
|
|
229
|
+
console.log(`${colors.green}✓${colors.reset} Created eslint.config.js`);
|
|
230
|
+
console.log(`${colors.cyan} Edit eslint.config.js to add your app-specific ESLint rules.${colors.reset}`);
|
|
231
|
+
return { action: 'created', file: 'eslint.config.js', format: 'ES Module' };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Main execution
|
|
236
|
+
function main() {
|
|
237
|
+
checkSafetyGuards();
|
|
238
|
+
|
|
239
|
+
const force = process.argv.includes('--force');
|
|
240
|
+
|
|
241
|
+
if (force) {
|
|
242
|
+
console.log(`${colors.yellow}Warning: --force flag is set. This will overwrite existing configurations.${colors.reset}\n`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
console.log(`${colors.cyan}Setting up ESLint configuration from pace-core...${colors.reset}\n`);
|
|
247
|
+
const result = setupESLintConfig(force);
|
|
248
|
+
|
|
249
|
+
// Summary
|
|
250
|
+
console.log(`\n${colors.bold}Setup Summary:${colors.reset}`);
|
|
251
|
+
if (result.action === 'created') {
|
|
252
|
+
console.log(` ${colors.green}ESLint Config:${colors.reset} Created ${result.file} (${result.format})`);
|
|
253
|
+
} else if (result.action === 'updated') {
|
|
254
|
+
console.log(` ${colors.green}ESLint Config:${colors.reset} Updated ${result.file} (${result.format})`);
|
|
255
|
+
console.log(` ${colors.yellow}Backup:${colors.reset} ${path.basename(result.backup)}`);
|
|
256
|
+
} else {
|
|
257
|
+
console.log(` ${colors.blue}ESLint Config:${colors.reset} Already configured (${result.file}, ${result.format})`);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
console.log(`\n${colors.cyan}ESLint configuration is now available${colors.reset}`);
|
|
261
|
+
console.log(`\n${colors.cyan}Next steps:${colors.reset}`);
|
|
262
|
+
console.log(` • Run ${colors.bold}npm run lint${colors.reset} to verify ESLint is working`);
|
|
263
|
+
console.log(` • Edit your ESLint config to add app-specific rules`);
|
|
264
|
+
console.log(` • See ${colors.bold}packages/core/docs/standards/${colors.reset} for complete standards documentation`);
|
|
265
|
+
|
|
266
|
+
} catch (error) {
|
|
267
|
+
console.error(`${colors.red}Error during setup:${colors.reset}`);
|
|
268
|
+
console.error(error.message);
|
|
269
|
+
if (error.stack) {
|
|
270
|
+
console.error(error.stack);
|
|
271
|
+
}
|
|
272
|
+
process.exit(1);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Run if called directly
|
|
277
|
+
if (require.main === module) {
|
|
278
|
+
main();
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
module.exports = {
|
|
282
|
+
setupESLintConfig,
|
|
283
|
+
findESLintConfig
|
|
284
|
+
};
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Reduces repeated mock setup across test files.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { createMockSupabaseClient
|
|
11
|
+
import { createMockSupabaseClient } from '../helpers/supabaseMock';
|
|
12
12
|
import type { User, Session } from '@supabase/supabase-js';
|
|
13
13
|
import { TEST_FIXTURES } from './test-data';
|
|
14
14
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import React from 'react';
|
|
9
9
|
import { render, screen } from '@testing-library/react';
|
|
10
|
-
import { describe, it, expect, vi
|
|
10
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
11
11
|
import userEvent from '@testing-library/user-event';
|
|
12
12
|
import {
|
|
13
13
|
componentTestPatterns,
|
|
@@ -23,7 +23,7 @@ vi.mock('../test-utils', () => ({
|
|
|
23
23
|
describe('[helpers] componentTestPatterns', () => {
|
|
24
24
|
describe('testRenders', () => {
|
|
25
25
|
it('creates test that renders component without crashing', () => {
|
|
26
|
-
const TestComponent = () => <
|
|
26
|
+
const TestComponent = () => <p data-testid="test-component">Test</p>;
|
|
27
27
|
const testFn = componentTestPatterns.testRenders(TestComponent);
|
|
28
28
|
|
|
29
29
|
expect(typeof testFn).toBe('function');
|
|
@@ -33,7 +33,7 @@ describe('[helpers] componentTestPatterns', () => {
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
it('creates test that renders component with props', () => {
|
|
36
|
-
const TestComponent = ({ name }: { name: string }) => <
|
|
36
|
+
const TestComponent = ({ name }: { name: string }) => <p data-testid="test-component">{name}</p>;
|
|
37
37
|
const testFn = componentTestPatterns.testRenders(TestComponent, { name: 'Test Name' });
|
|
38
38
|
|
|
39
39
|
expect(typeof testFn).toBe('function');
|
|
@@ -14,11 +14,11 @@ import { TestProviderWrapper, renderWithProviders, createMockUseUnifiedAuth, use
|
|
|
14
14
|
function TestComponent() {
|
|
15
15
|
const auth = useUnifiedAuth();
|
|
16
16
|
return (
|
|
17
|
-
<
|
|
17
|
+
<p>
|
|
18
18
|
<span data-testid="user-email">{auth.user?.email}</span>
|
|
19
19
|
<span data-testid="is-authenticated">{auth.isAuthenticated ? 'true' : 'false'}</span>
|
|
20
20
|
<span data-testid="app-name">{auth.appName}</span>
|
|
21
|
-
</
|
|
21
|
+
</p>
|
|
22
22
|
);
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import React from 'react';
|
|
9
9
|
import { render, screen } from '@testing-library/react';
|
|
10
|
-
import { describe, it, expect, vi
|
|
10
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
11
11
|
import { QueryClient } from '@tanstack/react-query';
|
|
12
12
|
import {
|
|
13
13
|
renderWithProviders,
|
|
@@ -41,32 +41,32 @@ vi.mock('../fixtures/test-data', () => ({
|
|
|
41
41
|
|
|
42
42
|
describe('[helpers] renderWithProviders', () => {
|
|
43
43
|
it('renders component with QueryClient provider by default', () => {
|
|
44
|
-
const TestComponent = () => <
|
|
44
|
+
const TestComponent = () => <p data-testid="test-component">Test</p>;
|
|
45
45
|
|
|
46
46
|
renderWithProviders(<TestComponent />);
|
|
47
47
|
|
|
48
|
-
expect(screen.getByTestId('test-component')).
|
|
48
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
it('renders component without QueryClient when withQueryClient is false', () => {
|
|
52
|
-
const TestComponent = () => <
|
|
52
|
+
const TestComponent = () => <p data-testid="test-component">Test</p>;
|
|
53
53
|
|
|
54
54
|
renderWithProviders(<TestComponent />, { withQueryClient: false });
|
|
55
55
|
|
|
56
|
-
expect(screen.getByTestId('test-component')).
|
|
56
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
it('uses custom QueryClient when provided', () => {
|
|
60
60
|
const customQueryClient = new QueryClient();
|
|
61
|
-
const TestComponent = () => <
|
|
61
|
+
const TestComponent = () => <p data-testid="test-component">Test</p>;
|
|
62
62
|
|
|
63
63
|
renderWithProviders(<TestComponent />, { queryClient: customQueryClient });
|
|
64
64
|
|
|
65
|
-
expect(screen.getByTestId('test-component')).
|
|
65
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
it('forwards additional render options', () => {
|
|
69
|
-
const TestComponent = () => <
|
|
69
|
+
const TestComponent = () => <p data-testid="test-component">Test</p>;
|
|
70
70
|
|
|
71
71
|
const { container } = renderWithProviders(<TestComponent />, {
|
|
72
72
|
container: document.body
|
|
@@ -273,7 +273,7 @@ describe('[helpers] createMockSupabaseClient', () => {
|
|
|
273
273
|
|
|
274
274
|
it('creates mock query builder with chaining methods', () => {
|
|
275
275
|
const mockClient = createMockSupabaseClient();
|
|
276
|
-
const queryBuilder = mockClient.from('test_table');
|
|
276
|
+
const queryBuilder = (mockClient.from as any)('test_table');
|
|
277
277
|
|
|
278
278
|
expect(queryBuilder).toHaveProperty('select');
|
|
279
279
|
expect(queryBuilder).toHaveProperty('insert');
|
|
@@ -302,7 +302,7 @@ describe('[helpers] createMockSupabaseClient', () => {
|
|
|
302
302
|
|
|
303
303
|
describe('[helpers] TestWrapper', () => {
|
|
304
304
|
it('renders children with QueryClient provider', () => {
|
|
305
|
-
const TestComponent = () => <
|
|
305
|
+
const TestComponent = () => <p data-testid="test-component">Test</p>;
|
|
306
306
|
|
|
307
307
|
render(
|
|
308
308
|
<TestWrapper>
|
|
@@ -310,7 +310,7 @@ describe('[helpers] TestWrapper', () => {
|
|
|
310
310
|
</TestWrapper>
|
|
311
311
|
);
|
|
312
312
|
|
|
313
|
-
expect(screen.getByTestId('test-component')).
|
|
313
|
+
expect(screen.getByTestId('test-component')).toBeDefined();
|
|
314
314
|
});
|
|
315
315
|
});
|
|
316
316
|
|
|
@@ -387,8 +387,8 @@ describe('[helpers] testHelpers', () => {
|
|
|
387
387
|
|
|
388
388
|
describe('[helpers] setupTest', () => {
|
|
389
389
|
it('sets up test environment', () => {
|
|
390
|
-
|
|
391
|
-
|
|
390
|
+
vi.spyOn(vi, 'clearAllMocks');
|
|
391
|
+
vi.spyOn(vi, 'restoreAllMocks');
|
|
392
392
|
|
|
393
393
|
setupTest();
|
|
394
394
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @description Specialized utilities for component testing
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { screen, cleanup } from '@testing-library/react';
|
|
7
7
|
import userEvent from '@testing-library/user-event';
|
|
8
8
|
import { vi } from 'vitest';
|
|
9
9
|
import { renderWithProviders } from './test-utils';
|
|
@@ -28,7 +28,7 @@ export const createMockQueryBuilder = (defaultData: any = { data: [], error: nul
|
|
|
28
28
|
|
|
29
29
|
// Create a thenable range function that returns self
|
|
30
30
|
const createRangeFunction = (builder: any) => {
|
|
31
|
-
return vi.fn().mockImplementation(function(
|
|
31
|
+
return vi.fn().mockImplementation(function(_min: number, _max: number) {
|
|
32
32
|
// Return builder with thenable interface
|
|
33
33
|
return Object.assign(builder, {
|
|
34
34
|
then: vi.fn().mockImplementation((resolve, reject) => {
|
|
@@ -132,7 +132,7 @@ export const createMockQueryBuilderWithData = (data: any, error: any = null) =>
|
|
|
132
132
|
});
|
|
133
133
|
|
|
134
134
|
// Ensure range() is available and returns a thenable
|
|
135
|
-
mockQueryBuilder.range = vi.fn().mockImplementation(function(
|
|
135
|
+
mockQueryBuilder.range = vi.fn().mockImplementation(function(_min: number, _max: number) {
|
|
136
136
|
// Return a thenable builder for range() that can be awaited
|
|
137
137
|
const rangedBuilder = Object.assign(this, {
|
|
138
138
|
then: vi.fn().mockImplementation((resolve, reject) => {
|
|
@@ -37,18 +37,18 @@ const UserProfile = ({ userId }: { userId: string }) => {
|
|
|
37
37
|
fetchUser();
|
|
38
38
|
}, [userId]);
|
|
39
39
|
|
|
40
|
-
if (loading) return <
|
|
41
|
-
if (error) return <
|
|
42
|
-
if (!user) return <
|
|
40
|
+
if (loading) return <p>Loading...</p>;
|
|
41
|
+
if (error) return <p>Error: {error}</p>;
|
|
42
|
+
if (!user) return <p>No user found</p>;
|
|
43
43
|
|
|
44
44
|
return (
|
|
45
|
-
<
|
|
45
|
+
<section data-testid="user-profile">
|
|
46
46
|
<h1>{user.name}</h1>
|
|
47
47
|
<p>{user.email}</p>
|
|
48
48
|
<button onClick={() => setUser({ ...user, name: 'Updated Name' })}>
|
|
49
49
|
Update Name
|
|
50
50
|
</button>
|
|
51
|
-
</
|
|
51
|
+
</section>
|
|
52
52
|
);
|
|
53
53
|
};
|
|
54
54
|
|
|
@@ -59,17 +59,17 @@ describe('User Profile Integration Tests', () => {
|
|
|
59
59
|
|
|
60
60
|
// The component loads data synchronously in this mock, so we just check the final state
|
|
61
61
|
await waitFor(() => {
|
|
62
|
-
expect(screen.getByText('John Doe')).
|
|
62
|
+
expect(screen.getByText('John Doe')).toBeDefined();
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
-
expect(screen.getByText('john@example.com')).
|
|
65
|
+
expect(screen.getByText('john@example.com')).toBeDefined();
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
it('handles user not found', async () => {
|
|
69
69
|
renderWithProviders(<UserProfile userId="999" />);
|
|
70
70
|
|
|
71
71
|
await waitFor(() => {
|
|
72
|
-
expect(screen.getByText('Error: User not found')).
|
|
72
|
+
expect(screen.getByText('Error: User not found')).toBeDefined();
|
|
73
73
|
});
|
|
74
74
|
});
|
|
75
75
|
});
|
|
@@ -80,13 +80,13 @@ describe('User Profile Integration Tests', () => {
|
|
|
80
80
|
renderWithProviders(<UserProfile userId="1" />);
|
|
81
81
|
|
|
82
82
|
await waitFor(() => {
|
|
83
|
-
expect(screen.getByText('John Doe')).
|
|
83
|
+
expect(screen.getByText('John Doe')).toBeDefined();
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
await user.click(screen.getByText('Update Name'));
|
|
87
87
|
|
|
88
|
-
expect(screen.getByText('Updated Name')).
|
|
89
|
-
expect(screen.queryByText('John Doe')).
|
|
88
|
+
expect(screen.getByText('Updated Name')).toBeDefined();
|
|
89
|
+
expect(screen.queryByText('John Doe')).toBeNull();
|
|
90
90
|
});
|
|
91
91
|
});
|
|
92
92
|
|
|
@@ -95,12 +95,12 @@ describe('User Profile Integration Tests', () => {
|
|
|
95
95
|
const { rerender } = renderWithProviders(<UserProfile userId="1" />);
|
|
96
96
|
|
|
97
97
|
await waitFor(() => {
|
|
98
|
-
expect(screen.getByText('John Doe')).
|
|
98
|
+
expect(screen.getByText('John Doe')).toBeDefined();
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
rerender(<UserProfile userId="1" />);
|
|
102
102
|
|
|
103
|
-
expect(screen.getByText('John Doe')).
|
|
103
|
+
expect(screen.getByText('John Doe')).toBeDefined();
|
|
104
104
|
});
|
|
105
105
|
});
|
|
106
106
|
});
|
|
@@ -117,7 +117,7 @@ describe('User Profile - Different Users', () => {
|
|
|
117
117
|
renderWithProviders(<UserProfile userId={userId} />);
|
|
118
118
|
|
|
119
119
|
await waitFor(() => {
|
|
120
|
-
expect(screen.getByText(expectedName)).
|
|
120
|
+
expect(screen.getByText(expectedName)).toBeDefined();
|
|
121
121
|
});
|
|
122
122
|
});
|
|
123
123
|
});
|