@jmruthers/pace-core 0.6.6 → 0.6.8
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/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +227 -22
- package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
- package/audit-tool/audits/02-project-structure.cjs +240 -0
- package/audit-tool/audits/03-architecture.cjs +224 -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 +554 -0
- package/audit-tool/audits/07-api-tech-stack.cjs +355 -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 +295 -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 +380 -0
- package/cursor-rules/00-standards-overview.mdc +156 -0
- package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
- package/cursor-rules/02-project-structure.mdc +37 -5
- package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
- package/cursor-rules/04-code-quality.mdc +419 -0
- package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
- package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
- 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/DataTable-6RMSCQJ6.js +15 -0
- package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
- package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-CIGSujI2.d.ts} +40 -24
- package/dist/{UnifiedAuthProvider-ZT6TIGM7.js → UnifiedAuthProvider-7SNDOWYD.js} +2 -2
- package/dist/{api-Y4MQWOFW.js → api-7P7DI652.js} +1 -1
- package/dist/{chunk-MAGBIDNS.js → chunk-4DDCYDQ3.js} +8 -7
- package/dist/{chunk-BVP2BCJF.js → chunk-5W2A3DRC.js} +10 -9
- package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
- package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
- package/dist/{chunk-3O3WHILE.js → chunk-EF2UGZWY.js} +239 -63
- package/dist/{chunk-LAZMKTTF.js → chunk-EURB7QFZ.js} +341 -337
- package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
- package/dist/{chunk-7TYHROIV.js → chunk-GS5672WG.js} +55 -13
- package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
- package/dist/{chunk-ZFYPMX46.js → chunk-LX6U42O3.js} +1 -1
- package/dist/{chunk-FENMYN2U.js → chunk-MPBLMWVR.js} +3 -3
- package/dist/{chunk-ZS5VO5JB.js → chunk-NKHKXPI4.js} +408 -453
- package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
- package/dist/{chunk-4T7OBVTU.js → chunk-S6ZQKDY6.js} +1 -1
- package/dist/{chunk-FTCRZOG2.js → chunk-T5CVK4R3.js} +5 -5
- package/dist/{chunk-OHIK3MIO.js → chunk-Z2FNRKF3.js} +13 -13
- package/dist/components.d.ts +5 -4
- package/dist/components.js +29 -34
- package/dist/eslint-rules/index.cjs +22 -9
- package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
- package/dist/eslint-rules/rules/04-code-quality.cjs +346 -0
- package/dist/eslint-rules/rules/05-styling.cjs +61 -0
- package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +34 -13
- package/dist/eslint-rules/rules/07-api-tech-stack.cjs +385 -0
- package/dist/eslint-rules/rules/08-testing.cjs +94 -0
- package/dist/{functions-DHebl8-F.d.ts → functions-lBy5L2ry.d.ts} +1 -1
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +8 -8
- package/dist/index.d.ts +7 -7
- package/dist/index.js +21 -20
- package/dist/providers.js +2 -2
- package/dist/rbac/index.d.ts +1 -1
- package/dist/rbac/index.js +8 -8
- package/dist/theming/runtime.d.ts +61 -1
- package/dist/theming/runtime.js +1 -1
- package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
- package/dist/types.d.ts +2 -2
- package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +8 -8
- package/docs/README.md +1 -1
- package/docs/api/modules.md +106 -41
- package/docs/api-reference/components.md +18 -20
- package/docs/api-reference/hooks.md +80 -80
- 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/dependencies.md +23 -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/quick-reference.md +4 -4
- package/docs/implementation-guides/app-layout.md +1 -1
- package/docs/implementation-guides/authentication.md +15 -15
- package/docs/implementation-guides/component-styling.md +1 -1
- package/docs/implementation-guides/data-tables.md +127 -34
- 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 +1 -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/README.md +5 -5
- package/docs/rbac/advanced-patterns.md +6 -6
- package/docs/rbac/api-reference.md +20 -20
- 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 -1
- 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/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +241 -185
- package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
- package/docs/standards/3-architecture-standards.md +606 -0
- package/docs/standards/4-code-quality-standards.md +728 -0
- package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
- package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
- 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 +203 -104
- 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/eslint-config-pace-core.cjs +50 -20
- package/package.json +50 -19
- package/scripts/eslint-audit.cjs +123 -0
- package/scripts/install-cursor-rules.cjs +11 -243
- package/scripts/install-eslint-config.cjs +349 -0
- package/scripts/validate-dependencies.cjs +248 -0
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +30 -18
- package/src/__tests__/integration/UserProfile.test.tsx +14 -14
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
- package/src/__tests__/templates/accessibility.test.template.tsx +10 -9
- package/src/__tests__/templates/component.test.template.tsx +18 -15
- package/src/components/AddressField/AddressField.tsx +26 -1
- package/src/components/Alert/Alert.test.tsx +86 -22
- package/src/components/Alert/Alert.tsx +19 -11
- package/src/components/Badge/Badge.tsx +1 -1
- package/src/components/Calendar/Calendar.tsx +201 -47
- package/src/components/Checkbox/Checkbox.test.tsx +2 -1
- package/src/components/ContextSelector/ContextSelector.tsx +108 -126
- package/src/components/DataTable/AUDIT_REPORT.md +293 -0
- package/src/components/DataTable/DataTable.tsx +1 -19
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +6 -2
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +21 -6
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +3 -2
- 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/DataTableErrorBoundary.tsx +9 -11
- package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
- package/src/components/DataTable/components/EditableRow.tsx +5 -7
- package/src/components/DataTable/components/EmptyState.tsx +11 -10
- 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/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 +45 -27
- package/src/components/DataTable/components/index.ts +2 -1
- package/src/components/DataTable/types.ts +0 -18
- package/src/components/DataTable/utils/a11yUtils.ts +17 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
- package/src/components/DateTimeField/DateTimeField.tsx +7 -8
- package/src/components/Dialog/Dialog.test.tsx +1 -0
- package/src/components/Dialog/Dialog.tsx +25 -8
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
- package/src/components/FileUpload/FileUpload.test.tsx +45 -16
- package/src/components/FileUpload/FileUpload.tsx +141 -130
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +48 -12
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +9 -9
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +30 -30
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -4
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +7 -1
- package/src/components/Progress/Progress.tsx +2 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
- package/src/components/Select/Select.tsx +86 -77
- package/src/components/Select/types.ts +3 -0
- package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
- package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +8 -5
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +4 -0
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +99 -99
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +45 -8
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +22 -2
- package/src/hooks/public/usePublicEvent.ts +5 -5
- package/src/hooks/public/usePublicEventLogo.ts +5 -5
- package/src/hooks/public/usePublicFileDisplay.ts +2 -2
- package/src/hooks/public/usePublicRouteParams.ts +13 -9
- package/src/hooks/useAddressAutocomplete.test.ts +18 -18
- package/src/hooks/useAppConfig.ts +2 -2
- package/src/hooks/useEventTheme.test.ts +7 -7
- package/src/hooks/useEventTheme.ts +2 -1
- package/src/hooks/useFileDisplay.ts +2 -2
- package/src/hooks/useFileUrl.ts +52 -8
- package/src/hooks/useOrganisationSecurity.test.ts +2 -1
- 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 +38 -38
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +15 -6
- package/src/rbac/__tests__/rbac-functions.test.ts +3 -3
- package/src/rbac/api.test.ts +104 -0
- package/src/rbac/engine.ts +1 -1
- package/src/rbac/hooks/useCan.test.ts +2 -2
- package/src/rbac/secureClient.ts +1 -1
- package/src/rbac/types/functions.ts +1 -1
- package/src/styles/core.css +7 -0
- package/src/theming/__tests__/parseEventColours.test.ts +118 -3
- package/src/theming/parseEventColours.ts +77 -11
- package/src/types/supabase.ts +2 -3
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +9 -9
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
- package/src/utils/file-reference/__tests__/file-reference.test.ts +4 -0
- package/src/utils/formatting/formatDate.test.ts +3 -2
- package/src/utils/formatting/formatDateTime.test.ts +2 -2
- package/src/utils/google-places/googlePlacesUtils.test.ts +36 -24
- package/src/utils/storage/README.md +1 -1
- package/src/utils/storage/__tests__/helpers.unit.test.ts +19 -12
- package/src/utils/storage/helpers.test.ts +69 -3
- package/cursor-rules/01-standards-compliance.mdc +0 -285
- package/cursor-rules/04-testing-standards.mdc +0 -270
- package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
- package/cursor-rules/06-code-quality.mdc +0 -311
- package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
- package/cursor-rules/10-error-handling-patterns.mdc +0 -179
- package/cursor-rules/11-performance-optimization.mdc +0 -169
- package/cursor-rules/12-ci-cd-integration.mdc +0 -150
- package/dist/DataTable-LRJL4IRV.js +0 -15
- package/dist/eslint-rules/rules/compliance.cjs +0 -348
- package/dist/eslint-rules/rules/components.cjs +0 -113
- package/dist/eslint-rules/rules/imports.cjs +0 -102
- package/docs/best-practices/README.md +0 -472
- package/docs/best-practices/accessibility.md +0 -604
- 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-standards-compliance.md +0 -188
- package/docs/standards/03-solid-principles.md +0 -39
- package/docs/standards/04-testing-standards.md +0 -36
- package/docs/standards/05-bug-reports-and-features.md +0 -27
- package/docs/standards/06-code-quality.md +0 -34
- package/docs/standards/07-tech-stack-compliance.md +0 -30
- package/docs/standards/10-error-handling-patterns.md +0 -401
- package/docs/standards/11-performance-optimization.md +0 -348
- package/docs/standards/12-ci-cd-integration.md +0 -370
- package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
- package/scripts/audit/audit-compliance.cjs +0 -1295
- package/scripts/audit/audit-components.cjs +0 -260
- package/scripts/audit/audit-rbac.cjs +0 -954
- package/scripts/audit/audit-standards.cjs +0 -1268
- package/scripts/audit/index.cjs +0 -1927
- package/src/components/DataTable/components/DataTableBody.tsx +0 -478
- 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/index.cjs +0 -22
- package/src/eslint-rules/rules/components.cjs +0 -113
- package/src/eslint-rules/rules/imports.cjs +0 -102
- package/src/eslint-rules/rules/rbac.cjs +0 -790
- package/src/eslint-rules/utils/helpers.cjs +0 -42
- package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Enforce tech stack compliance including Tailwind v4, React 19+, Supabase, and other required technologies
|
|
3
|
-
globs: ["src/**/*.{ts,tsx,js,jsx,css}", "*.config.{ts,js}"]
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
paceCoreVersion: "0.6.x"
|
|
6
|
-
rulesVersion: "2025-01-28"
|
|
7
|
-
---
|
|
8
|
-
# Tech Stack Compliance Guide
|
|
9
|
-
|
|
10
|
-
**📚 Human-Readable Standard**: See [07-tech-stack-compliance.md](../../packages/core/docs/standards/07-tech-stack-compliance.md) for complete documentation.
|
|
11
|
-
|
|
12
|
-
This guide ensures consuming apps use the correct versions and patterns for all technologies in the PACE stack.
|
|
13
|
-
|
|
14
|
-
## Tailwind CSS v4
|
|
15
|
-
|
|
16
|
-
### MUST: Use Tailwind v4 CSS-First Approach
|
|
17
|
-
|
|
18
|
-
**MUST use Tailwind v4 CSS-first syntax, NOT v3 patterns:**
|
|
19
|
-
|
|
20
|
-
```css
|
|
21
|
-
/* ✅ CORRECT: Tailwind v4 CSS-first (@import 'tailwindcss'; @theme { ... }) */
|
|
22
|
-
/* ❌ WRONG: Tailwind v3 (@tailwind base/components/utilities directives) */
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
### MUST NOT: Use Bracket Syntax
|
|
26
|
-
|
|
27
|
-
**MUST NOT use bracket syntax like `bg-[oklch(...)]`. Map everything through theme variables:**
|
|
28
|
-
|
|
29
|
-
```tsx
|
|
30
|
-
// ❌ WRONG: Bracket syntax (bg-[oklch(...)])
|
|
31
|
-
// ✅ CORRECT: Theme variable (bg-main-500)
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### MUST: Use Custom Color Namespaces
|
|
35
|
-
|
|
36
|
-
**MUST use custom color namespaces:**
|
|
37
|
-
- `main-*` for primary colors (green, emerald, teal, cyan, sky, blue)
|
|
38
|
-
- `sec-*` for secondary colors (indigo, violet, purple, fuchsia, slate, gray, zinc, neutral, stone)
|
|
39
|
-
- `acc-*` for accent colors (red, orange, amber, yellow, lime, pink, rose)
|
|
40
|
-
|
|
41
|
-
```tsx
|
|
42
|
-
// ✅ CORRECT: Custom namespaces (main-*, sec-*, acc-*)
|
|
43
|
-
// ❌ WRONG: Standard Tailwind colors (blue-*, gray-*, red-*)
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### MUST: Use Semantic Classes
|
|
47
|
-
|
|
48
|
-
**MUST use semantic classes mapped in index.css:**
|
|
49
|
-
|
|
50
|
-
```tsx
|
|
51
|
-
// ✅ CORRECT - Semantic classes
|
|
52
|
-
<div className="bg-background text-foreground">
|
|
53
|
-
|
|
54
|
-
// ❌ WRONG - Direct color classes (unless necessary)
|
|
55
|
-
<div className="bg-main-50 text-main-950">
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## React 19+
|
|
59
|
-
|
|
60
|
-
### MUST: Use React 19+ Features
|
|
61
|
-
|
|
62
|
-
**MUST use React 19+ patterns:**
|
|
63
|
-
|
|
64
|
-
```tsx
|
|
65
|
-
// ✅ CORRECT: React 19+ features (Suspense, useTransition, etc.)
|
|
66
|
-
import { Suspense, useTransition } from 'react';
|
|
67
|
-
function App() {
|
|
68
|
-
const [isPending, startTransition] = useTransition();
|
|
69
|
-
return <Suspense fallback={<Loading />}><Component /></Suspense>;
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### MUST: Use Functional Components
|
|
74
|
-
|
|
75
|
-
**MUST use functional components with hooks exclusively:**
|
|
76
|
-
|
|
77
|
-
```tsx
|
|
78
|
-
// ✅ CORRECT: Functional components with hooks
|
|
79
|
-
function MyComponent() { const [state, setState] = useState(); return <div>...</div>; }
|
|
80
|
-
|
|
81
|
-
// ❌ WRONG: Class components
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Supabase
|
|
85
|
-
|
|
86
|
-
### MUST: Use Secure Supabase Client
|
|
87
|
-
|
|
88
|
-
**MUST use `useSecureSupabase()` for all database operations:**
|
|
89
|
-
|
|
90
|
-
```tsx
|
|
91
|
-
// ✅ CORRECT: useSecureSupabase() from '@jmruthers/pace-core/rbac'
|
|
92
|
-
// ❌ WRONG: createClient() from '@supabase/supabase-js' (base client)
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### MUST: Enforce RLS
|
|
96
|
-
|
|
97
|
-
**MUST ensure RLS is enabled on all tables. Never bypass RLS.**
|
|
98
|
-
|
|
99
|
-
### SHOULD: Use RPC Functions
|
|
100
|
-
|
|
101
|
-
**SHOULD use RPC functions for complex queries:**
|
|
102
|
-
|
|
103
|
-
```tsx
|
|
104
|
-
// ✅ CORRECT: RPC functions for complex queries
|
|
105
|
-
const { data } = await secureSupabase.rpc('data_events_list', { organisation_id: orgId });
|
|
106
|
-
|
|
107
|
-
// ❌ AVOID: Complex client-side queries with many joins
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## TanStack Query
|
|
111
|
-
|
|
112
|
-
### MUST: Use TanStack Query for Server State
|
|
113
|
-
|
|
114
|
-
**MUST use TanStack Query for all server state management:**
|
|
115
|
-
|
|
116
|
-
```tsx
|
|
117
|
-
// ✅ CORRECT: TanStack Query for server state
|
|
118
|
-
import { useQuery, useMutation } from '@tanstack/react-query';
|
|
119
|
-
const { data, isLoading } = useQuery({ queryKey: ['events', orgId], queryFn: () => fetchEvents(orgId) });
|
|
120
|
-
|
|
121
|
-
// ❌ WRONG: useState + useEffect for server state
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### SHOULD: Configure Query Client
|
|
125
|
-
|
|
126
|
-
**SHOULD configure QueryClient with appropriate defaults:**
|
|
127
|
-
|
|
128
|
-
```tsx
|
|
129
|
-
// ✅ CORRECT: Configure QueryClient with appropriate defaults (staleTime, cacheTime, retry)
|
|
130
|
-
const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 5 * 60 * 1000, cacheTime: 10 * 60 * 1000, retry: 1 } } });
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
## React Hook Form + Zod
|
|
134
|
-
|
|
135
|
-
### MUST: Use React Hook Form with Zod
|
|
136
|
-
|
|
137
|
-
**MUST use React Hook Form with Zod for all forms:**
|
|
138
|
-
|
|
139
|
-
```tsx
|
|
140
|
-
// ✅ CORRECT: React Hook Form + Zod (useZodForm from pace-core)
|
|
141
|
-
import { useZodForm } from '@jmruthers/pace-core';
|
|
142
|
-
const schema = z.object({ email: z.string().email(), name: z.string().min(1) });
|
|
143
|
-
const form = useZodForm(schema);
|
|
144
|
-
|
|
145
|
-
// ❌ WRONG: Manual form handling (useState for form state)
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
## Vite
|
|
149
|
-
|
|
150
|
-
### MUST: Use Vite for Build Tooling
|
|
151
|
-
|
|
152
|
-
**MUST use Vite for all build tooling:**
|
|
153
|
-
|
|
154
|
-
```typescript
|
|
155
|
-
// ✅ CORRECT: Vite for build tooling
|
|
156
|
-
import { defineConfig } from 'vite';
|
|
157
|
-
import react from '@vitejs/plugin-react';
|
|
158
|
-
export default defineConfig({ plugins: [react()] });
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### MUST: Use Environment Variables Correctly
|
|
162
|
-
|
|
163
|
-
**MUST use `import.meta.env` for environment variables:**
|
|
164
|
-
|
|
165
|
-
```tsx
|
|
166
|
-
// ✅ CORRECT: import.meta.env.VITE_API_URL (Vite env vars)
|
|
167
|
-
// ❌ WRONG: process.env.VITE_API_URL (Node.js env vars)
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
## TypeScript
|
|
171
|
-
|
|
172
|
-
### MUST: Use TypeScript 5+
|
|
173
|
-
|
|
174
|
-
**MUST use TypeScript 5+ with strict mode:**
|
|
175
|
-
|
|
176
|
-
```json
|
|
177
|
-
// ✅ CORRECT: TypeScript 5+ with strict mode
|
|
178
|
-
{ "compilerOptions": { "target": "ES2022", "module": "ESNext", "strict": true } }
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
## Version Requirements
|
|
182
|
-
|
|
183
|
-
### MUST: Use Required Versions
|
|
184
|
-
|
|
185
|
-
**MUST use compatible versions:**
|
|
186
|
-
|
|
187
|
-
- React: `^19.0.0`
|
|
188
|
-
- TypeScript: `^5.0.0`
|
|
189
|
-
- Tailwind CSS: `^4.0.0`
|
|
190
|
-
- Vite: `^6.0.0`
|
|
191
|
-
- Supabase: `^2.49.0+`
|
|
192
|
-
|
|
193
|
-
**Check `package.json` for exact versions required by pace-core.**
|
|
194
|
-
|
|
195
|
-
## Tech Stack Checklist
|
|
196
|
-
|
|
197
|
-
Before committing, verify:
|
|
198
|
-
- [ ] Tailwind v4 CSS-first syntax (no @tailwind directives)
|
|
199
|
-
- [ ] No bracket syntax for colors (use theme variables)
|
|
200
|
-
- [ ] Custom color namespaces (main-*, sec-*, acc-*)
|
|
201
|
-
- [ ] React 19+ functional components
|
|
202
|
-
- [ ] Secure Supabase client (useSecureSupabase)
|
|
203
|
-
- [ ] TanStack Query for server state
|
|
204
|
-
- [ ] React Hook Form + Zod for forms
|
|
205
|
-
- [ ] Vite for build tooling
|
|
206
|
-
- [ ] TypeScript 5+ with strict mode
|
|
207
|
-
- [ ] All versions compatible with pace-core
|
|
208
|
-
|
|
209
|
-
## Reference
|
|
210
|
-
|
|
211
|
-
- Tailwind v4: https://tailwindcss.com/blog/tailwindcss-v4
|
|
212
|
-
- React 19: https://react.dev/blog/2024/04/25/react-19-upgrade-guide
|
|
213
|
-
- Supabase: https://supabase.com/docs
|
|
214
|
-
- TanStack Query: https://tanstack.com/query
|
|
215
|
-
- React Hook Form: https://react-hook-form.com
|
|
216
|
-
- Vite: https://vitejs.dev
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Enforce consistent error handling patterns including type-safe errors, user-friendly messages, and proper logging
|
|
3
|
-
globs: ["src/**/*.{ts,tsx,js,jsx}"]
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
paceCoreVersion: "0.6.x"
|
|
6
|
-
rulesVersion: "2025-01-28"
|
|
7
|
-
---
|
|
8
|
-
# Error Handling Patterns Guide
|
|
9
|
-
|
|
10
|
-
**📚 Human-Readable Standard**: See [10-error-handling-patterns.md](../../packages/core/docs/standards/10-error-handling-patterns.md) for complete documentation.
|
|
11
|
-
|
|
12
|
-
This guide enforces consistent error handling patterns to ensure user-friendly errors, type-safe handling, and proper logging.
|
|
13
|
-
|
|
14
|
-
**AI Agent Instructions**: When writing error handling code, ALWAYS follow these patterns. Never expose internal details to users. Always use type-safe error handling.
|
|
15
|
-
|
|
16
|
-
## MUST: Use Type-Safe Error Handling
|
|
17
|
-
|
|
18
|
-
**MUST use type guards or Result types, NEVER use `any`:**
|
|
19
|
-
|
|
20
|
-
```tsx
|
|
21
|
-
// ❌ WRONG: Using any
|
|
22
|
-
catch (error: any) {
|
|
23
|
-
console.log(error.message);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// ✅ CORRECT: Type guard
|
|
27
|
-
function isApiError(error: unknown): error is ApiError {
|
|
28
|
-
return typeof error === 'object' && error !== null && 'ok' in error && (error as ApiError).ok === false;
|
|
29
|
-
}
|
|
30
|
-
catch (error) {
|
|
31
|
-
if (isApiError(error)) {
|
|
32
|
-
handleApiError(error);
|
|
33
|
-
} else {
|
|
34
|
-
handleUnknownError(error);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// ✅ CORRECT: Result type
|
|
39
|
-
type Result<T> = { ok: true; data: T } | { ok: false; error: ApiError };
|
|
40
|
-
const result = await fetchData();
|
|
41
|
-
if (result.ok) {
|
|
42
|
-
useData(result.data);
|
|
43
|
-
} else {
|
|
44
|
-
showError(result.error.message);
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## MUST: Never Expose Internal Details
|
|
49
|
-
|
|
50
|
-
**MUST NOT expose SQL, stack traces, file paths, or internal errors to users:**
|
|
51
|
-
|
|
52
|
-
```tsx
|
|
53
|
-
// ❌ WRONG: Exposing internal details
|
|
54
|
-
toast.error(error.message); // May contain SQL, stack traces
|
|
55
|
-
|
|
56
|
-
// ✅ CORRECT: User-friendly message
|
|
57
|
-
toast.error('Unable to save changes. Please try again.');
|
|
58
|
-
logger.error('Save failed', { error: error.message, context: 'saveUser' });
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## MUST: Use Consistent Error Shapes
|
|
62
|
-
|
|
63
|
-
**MUST use ApiResult shape for API errors:**
|
|
64
|
-
|
|
65
|
-
```tsx
|
|
66
|
-
// ✅ CORRECT: Consistent error shape
|
|
67
|
-
type ApiError = {
|
|
68
|
-
ok: false;
|
|
69
|
-
error: {
|
|
70
|
-
code: string;
|
|
71
|
-
message: string; // User-friendly
|
|
72
|
-
details?: object; // Non-sensitive context
|
|
73
|
-
};
|
|
74
|
-
};
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## MUST: Log Errors with Context
|
|
78
|
-
|
|
79
|
-
**MUST log errors with context, but NEVER log sensitive data:**
|
|
80
|
-
|
|
81
|
-
```tsx
|
|
82
|
-
// ✅ CORRECT: Log with context, no sensitive data
|
|
83
|
-
logger.error('Failed to save user', {
|
|
84
|
-
userId: user.id,
|
|
85
|
-
operation: 'updateUser',
|
|
86
|
-
errorCode: error.code,
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// ❌ WRONG: Logging sensitive data
|
|
90
|
-
logger.error('Failed to save user', {
|
|
91
|
-
password: user.password, // NEVER
|
|
92
|
-
token: authToken, // NEVER
|
|
93
|
-
ssn: user.ssn, // NEVER
|
|
94
|
-
});
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## SHOULD: Provide Recovery Paths
|
|
98
|
-
|
|
99
|
-
**SHOULD provide retry logic or fallback values when appropriate:**
|
|
100
|
-
|
|
101
|
-
```tsx
|
|
102
|
-
// ✅ CORRECT: Retry with exponential backoff
|
|
103
|
-
async function fetchWithRetry<T>(fn: () => Promise<Result<T>>, maxRetries = 3): Promise<Result<T>> {
|
|
104
|
-
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
105
|
-
const result = await fn();
|
|
106
|
-
if (result.ok) return result;
|
|
107
|
-
if (result.error.code?.startsWith('4')) return result; // Don't retry 4xx
|
|
108
|
-
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
|
|
109
|
-
}
|
|
110
|
-
return { ok: false, error: { code: 'MAX_RETRIES', message: 'Operation failed after retries' } };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// ✅ CORRECT: Fallback values
|
|
114
|
-
const preferences = await fetchPreferences().catch(() => ({ theme: 'light', language: 'en' }));
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## SHOULD: Use Error Boundaries for React
|
|
118
|
-
|
|
119
|
-
**SHOULD use ErrorBoundary for React component errors:**
|
|
120
|
-
|
|
121
|
-
```tsx
|
|
122
|
-
// ✅ CORRECT: Error boundary
|
|
123
|
-
import { ErrorBoundary } from '@jmruthers/pace-core';
|
|
124
|
-
<ErrorBoundary fallback={<ErrorFallback />} onError={(error, errorInfo) => logger.error('React error', { error, errorInfo })}>
|
|
125
|
-
<YourApp />
|
|
126
|
-
</ErrorBoundary>
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
## Decision Tree: Error Handling
|
|
130
|
-
|
|
131
|
-
**ALWAYS follow this decision tree:**
|
|
132
|
-
|
|
133
|
-
```
|
|
134
|
-
1. What type of error is this?
|
|
135
|
-
├─ API Error → Use ApiResult shape, user-friendly message
|
|
136
|
-
├─ Validation Error → Use Zod errors, field-specific messages
|
|
137
|
-
├─ Network Error → Retry logic, connection message
|
|
138
|
-
└─ Unknown Error → Generic user message, detailed log
|
|
139
|
-
|
|
140
|
-
2. Should user see this error?
|
|
141
|
-
├─ YES → User-friendly message (no internals)
|
|
142
|
-
└─ NO → Log only, show generic message
|
|
143
|
-
|
|
144
|
-
3. Can we recover?
|
|
145
|
-
├─ YES → Retry logic or fallback value
|
|
146
|
-
└─ NO → Show error, allow user to retry
|
|
147
|
-
|
|
148
|
-
4. Is this sensitive data?
|
|
149
|
-
├─ YES → Never log (passwords, tokens, PII)
|
|
150
|
-
└─ NO → Log with context
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
## Error Handling Checklist
|
|
154
|
-
|
|
155
|
-
Before committing error handling code, verify:
|
|
156
|
-
|
|
157
|
-
- [ ] Type-safe error handling (no `any`)
|
|
158
|
-
- [ ] User-friendly error messages (no internals)
|
|
159
|
-
- [ ] Errors logged with context (no sensitive data)
|
|
160
|
-
- [ ] Recovery paths provided when possible
|
|
161
|
-
- [ ] Consistent error shapes used
|
|
162
|
-
- [ ] Error boundaries for React components
|
|
163
|
-
- [ ] Async operations have proper error handling
|
|
164
|
-
- [ ] Validation errors use Zod
|
|
165
|
-
- [ ] Network errors handled gracefully
|
|
166
|
-
|
|
167
|
-
## Common Mistakes to Avoid
|
|
168
|
-
|
|
169
|
-
1. **Exposing internal details** - Never show SQL, stack traces, file paths
|
|
170
|
-
2. **Using `any` for errors** - Always use type guards or Result types
|
|
171
|
-
3. **Logging sensitive data** - Never log passwords, tokens, PII
|
|
172
|
-
4. **Ignoring errors** - Always handle errors, even if just logging
|
|
173
|
-
5. **Generic error messages** - Provide specific, actionable messages
|
|
174
|
-
|
|
175
|
-
## Reference
|
|
176
|
-
|
|
177
|
-
- **Standard**: `packages/core/docs/standards/10-error-handling-patterns.md`
|
|
178
|
-
- **Code Quality**: See `06-code-quality.mdc` for TypeScript standards
|
|
179
|
-
- **Security**: See `01-standards-compliance.mdc` for security requirements
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Enforce performance optimization patterns including React memoization, database query optimization, and caching strategies
|
|
3
|
-
globs: ["src/**/*.{ts,tsx,js,jsx}", "supabase/migrations/**/*.sql"]
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
paceCoreVersion: "0.6.x"
|
|
6
|
-
rulesVersion: "2025-01-28"
|
|
7
|
-
---
|
|
8
|
-
# Performance Optimization Guide
|
|
9
|
-
|
|
10
|
-
**📚 Human-Readable Standard**: See [11-performance-optimization.md](../../packages/core/docs/standards/11-performance-optimization.md) for complete documentation.
|
|
11
|
-
|
|
12
|
-
This guide enforces performance optimization patterns to ensure fast, responsive applications.
|
|
13
|
-
|
|
14
|
-
**AI Agent Instructions**: When writing performance-sensitive code, ALWAYS apply these optimizations. Use the decision trees below to determine when to optimize.
|
|
15
|
-
|
|
16
|
-
## MUST: Optimize React Re-renders
|
|
17
|
-
|
|
18
|
-
**MUST use memoization for expensive computations and stable references:**
|
|
19
|
-
|
|
20
|
-
```tsx
|
|
21
|
-
// ✅ CORRECT - Memoize expensive computation
|
|
22
|
-
const expensiveValue = useMemo(() => computeExpensiveValue(data), [data]);
|
|
23
|
-
|
|
24
|
-
// ✅ CORRECT - Stable callback reference
|
|
25
|
-
const handleClick = useCallback(() => doSomething(id), [id]);
|
|
26
|
-
|
|
27
|
-
// ✅ CORRECT - Memoize component
|
|
28
|
-
const ExpensiveComponent = React.memo(({ data }) => <div>{/* ... */}</div>);
|
|
29
|
-
|
|
30
|
-
// ❌ WRONG - Recomputes on every render
|
|
31
|
-
const expensiveValue = computeExpensiveValue(data);
|
|
32
|
-
const handleClick = () => doSomething(id);
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## MUST: Avoid Creating New Objects in Render
|
|
36
|
-
|
|
37
|
-
**MUST NOT create new objects/arrays in render:**
|
|
38
|
-
|
|
39
|
-
```tsx
|
|
40
|
-
// ❌ WRONG - New object on every render
|
|
41
|
-
function Component({ items }) {
|
|
42
|
-
const config = { items, enabled: true };
|
|
43
|
-
return <Child config={config} />;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// ✅ CORRECT - Memoize object
|
|
47
|
-
function Component({ items }) {
|
|
48
|
-
const config = useMemo(() => ({ items, enabled: true }), [items]);
|
|
49
|
-
return <Child config={config} />;
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## MUST: Use Helper Functions in RLS Policies
|
|
54
|
-
|
|
55
|
-
**MUST use STABLE SECURITY DEFINER helper functions (never subqueries):**
|
|
56
|
-
|
|
57
|
-
```sql
|
|
58
|
-
-- ✅ CORRECT - Helper function (evaluated once)
|
|
59
|
-
CREATE POLICY "rbac_select_users" ON users FOR SELECT USING (
|
|
60
|
-
check_user_organisation_access(organisation_id)
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
-- ❌ WRONG - Subquery (N+1 performance issue)
|
|
64
|
-
CREATE POLICY "rbac_select_users" ON users FOR SELECT USING (
|
|
65
|
-
organisation_id IN (SELECT organisation_id FROM organisation_memberships WHERE user_id = auth.uid())
|
|
66
|
-
);
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## SHOULD: Lazy Load Heavy Components
|
|
70
|
-
|
|
71
|
-
**SHOULD lazy load heavy components:**
|
|
72
|
-
|
|
73
|
-
```tsx
|
|
74
|
-
// ✅ CORRECT - Lazy load
|
|
75
|
-
import { lazy, Suspense } from 'react';
|
|
76
|
-
const HeavyComponent = lazy(() => import('./HeavyComponent'));
|
|
77
|
-
<Suspense fallback={<Loading />}><HeavyComponent /></Suspense>
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## SHOULD: Configure TanStack Query Cache
|
|
81
|
-
|
|
82
|
-
**SHOULD configure appropriate cache times:**
|
|
83
|
-
|
|
84
|
-
```tsx
|
|
85
|
-
// ✅ CORRECT - Configure cache
|
|
86
|
-
const queryClient = new QueryClient({
|
|
87
|
-
defaultOptions: {
|
|
88
|
-
queries: {
|
|
89
|
-
staleTime: 5 * 60 * 1000,
|
|
90
|
-
cacheTime: 10 * 60 * 1000,
|
|
91
|
-
retry: 1,
|
|
92
|
-
refetchOnWindowFocus: false,
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
});
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## SHOULD: Use RPC Functions for Complex Queries
|
|
99
|
-
|
|
100
|
-
**SHOULD use RPC functions instead of complex client-side queries:**
|
|
101
|
-
|
|
102
|
-
```tsx
|
|
103
|
-
// ✅ CORRECT - RPC for complex query
|
|
104
|
-
const { data } = await supabase.rpc('data_events_list', { organisation_id: orgId });
|
|
105
|
-
|
|
106
|
-
// ❌ AVOID - Complex client-side query
|
|
107
|
-
const { data } = await supabase.from('events').select('*, users(*), organisations(*)').eq('organisation_id', orgId);
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## Decision Tree: Performance Optimization
|
|
111
|
-
|
|
112
|
-
**ALWAYS follow this decision tree:**
|
|
113
|
-
|
|
114
|
-
```
|
|
115
|
-
1. Is this expensive computation?
|
|
116
|
-
├─ YES → Use useMemo
|
|
117
|
-
└─ NO → Don't memoize (overhead not worth it)
|
|
118
|
-
|
|
119
|
-
2. Is this function passed as prop?
|
|
120
|
-
├─ YES → Use useCallback
|
|
121
|
-
└─ NO → Regular function is fine
|
|
122
|
-
|
|
123
|
-
3. Is this component expensive to render?
|
|
124
|
-
├─ YES → Use React.memo
|
|
125
|
-
└─ NO → Regular component is fine
|
|
126
|
-
|
|
127
|
-
4. Is this creating new object/array in render?
|
|
128
|
-
├─ YES → Memoize with useMemo
|
|
129
|
-
└─ NO → Continue
|
|
130
|
-
|
|
131
|
-
5. Is this RLS policy?
|
|
132
|
-
├─ YES → Use helper function (STABLE SECURITY DEFINER)
|
|
133
|
-
└─ NO → Continue
|
|
134
|
-
|
|
135
|
-
6. Is this complex query?
|
|
136
|
-
├─ YES → Use RPC function
|
|
137
|
-
└─ NO → Client-side query is fine
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## Performance Checklist
|
|
141
|
-
|
|
142
|
-
Before committing performance-sensitive code, verify:
|
|
143
|
-
|
|
144
|
-
- [ ] Expensive computations memoized
|
|
145
|
-
- [ ] Callbacks stable with useCallback
|
|
146
|
-
- [ ] Components memoized when appropriate
|
|
147
|
-
- [ ] No new objects/arrays in render
|
|
148
|
-
- [ ] Heavy components lazy loaded
|
|
149
|
-
- [ ] RLS policies use helper functions
|
|
150
|
-
- [ ] Queries use indexes appropriately
|
|
151
|
-
- [ ] No N+1 query patterns
|
|
152
|
-
- [ ] TanStack Query configured properly
|
|
153
|
-
- [ ] Bundle size optimized
|
|
154
|
-
|
|
155
|
-
## Common Performance Pitfalls
|
|
156
|
-
|
|
157
|
-
1. **Creating new objects in render** - Memoize with useMemo
|
|
158
|
-
2. **Using inline functions** - Use useCallback
|
|
159
|
-
3. **Over-memoizing** - Only memoize expensive operations
|
|
160
|
-
4. **Subqueries in RLS** - Use helper functions
|
|
161
|
-
5. **N+1 queries** - Use joins or RPC functions
|
|
162
|
-
6. **Not lazy loading** - Lazy load heavy components
|
|
163
|
-
7. **Poor cache configuration** - Configure TanStack Query properly
|
|
164
|
-
|
|
165
|
-
## Reference
|
|
166
|
-
|
|
167
|
-
- **Standard**: `packages/core/docs/standards/11-performance-optimization.md`
|
|
168
|
-
- **RLS**: See `09-rbac-compliance.mdc` for RLS performance requirements
|
|
169
|
-
- **Code Quality**: See `06-code-quality.mdc` for React patterns
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Enforce CI/CD integration patterns including automated quality checks, deployment processes, and security scanning
|
|
3
|
-
globs: [".github/workflows/**/*.yml", ".github/workflows/**/*.yaml", "package.json"]
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
paceCoreVersion: "0.6.x"
|
|
6
|
-
rulesVersion: "2025-01-28"
|
|
7
|
-
---
|
|
8
|
-
# CI/CD Integration Guide
|
|
9
|
-
|
|
10
|
-
**📚 Human-Readable Standard**: See [12-ci-cd-integration.md](../../packages/core/docs/standards/12-ci-cd-integration.md) for complete documentation.
|
|
11
|
-
|
|
12
|
-
This guide enforces CI/CD integration patterns to ensure automated quality checks and consistent deployments.
|
|
13
|
-
|
|
14
|
-
**AI Agent Instructions**: When setting up CI/CD pipelines, ALWAYS include the required checks below. Use the decision tree to determine what checks are needed.
|
|
15
|
-
|
|
16
|
-
## MUST: Include Required CI Checks
|
|
17
|
-
|
|
18
|
-
**MUST run these checks in every CI pipeline:**
|
|
19
|
-
|
|
20
|
-
```yaml
|
|
21
|
-
# ✅ CORRECT - Required checks
|
|
22
|
-
jobs:
|
|
23
|
-
quality-checks:
|
|
24
|
-
steps:
|
|
25
|
-
- name: Lint
|
|
26
|
-
run: npm run lint
|
|
27
|
-
- name: Type check
|
|
28
|
-
run: npx tsc --noEmit
|
|
29
|
-
- name: Run tests
|
|
30
|
-
run: npm run test
|
|
31
|
-
- name: Build
|
|
32
|
-
run: npm run build
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## MUST: Have Required Scripts
|
|
36
|
-
|
|
37
|
-
**MUST have these scripts in package.json:**
|
|
38
|
-
|
|
39
|
-
```json
|
|
40
|
-
// ✅ CORRECT - Required scripts
|
|
41
|
-
{
|
|
42
|
-
"scripts": {
|
|
43
|
-
"lint": "eslint .",
|
|
44
|
-
"type-check": "tsc --noEmit",
|
|
45
|
-
"test": "vitest run",
|
|
46
|
-
"build": "vite build"
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## SHOULD: Include Additional Checks
|
|
52
|
-
|
|
53
|
-
**SHOULD include these checks:**
|
|
54
|
-
|
|
55
|
-
```yaml
|
|
56
|
-
# ✅ RECOMMENDED - Additional checks
|
|
57
|
-
- name: Format check
|
|
58
|
-
run: npm run format:check
|
|
59
|
-
- name: Security scan
|
|
60
|
-
run: npm audit --audit-level=moderate
|
|
61
|
-
- name: Coverage check
|
|
62
|
-
run: npm run test:coverage
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## MUST: Use Secrets for Sensitive Data
|
|
66
|
-
|
|
67
|
-
**MUST NOT commit secrets to repository:**
|
|
68
|
-
|
|
69
|
-
```yaml
|
|
70
|
-
# ✅ CORRECT - Use secrets
|
|
71
|
-
env:
|
|
72
|
-
SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
|
|
73
|
-
VITE_SUPABASE_ANON_KEY: ${{ secrets.VITE_SUPABASE_ANON_KEY }}
|
|
74
|
-
|
|
75
|
-
# ❌ WRONG - Hardcoded secrets
|
|
76
|
-
env:
|
|
77
|
-
SUPABASE_URL: "https://hardcoded-url.supabase.co"
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## SHOULD: Deploy to Staging First
|
|
81
|
-
|
|
82
|
-
**SHOULD deploy to staging before production:**
|
|
83
|
-
|
|
84
|
-
```yaml
|
|
85
|
-
# ✅ CORRECT - Staging first
|
|
86
|
-
deploy-staging:
|
|
87
|
-
if: github.ref == 'refs/heads/develop'
|
|
88
|
-
environment: staging
|
|
89
|
-
|
|
90
|
-
deploy-production:
|
|
91
|
-
needs: deploy-staging
|
|
92
|
-
if: github.ref == 'refs/heads/main'
|
|
93
|
-
environment: production
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Decision Tree: CI/CD Setup
|
|
97
|
-
|
|
98
|
-
**ALWAYS follow this decision tree:**
|
|
99
|
-
|
|
100
|
-
```
|
|
101
|
-
1. What type of check is this?
|
|
102
|
-
├─ Lint → MUST include
|
|
103
|
-
├─ Type Check → MUST include
|
|
104
|
-
├─ Tests → MUST include
|
|
105
|
-
├─ Build → MUST include
|
|
106
|
-
├─ Compliance → MUST include
|
|
107
|
-
├─ Format → SHOULD include
|
|
108
|
-
├─ Security → SHOULD include
|
|
109
|
-
└─ Coverage → SHOULD include
|
|
110
|
-
|
|
111
|
-
2. Is this sensitive data?
|
|
112
|
-
├─ YES → Use secrets (never commit)
|
|
113
|
-
└─ NO → Can be in config
|
|
114
|
-
|
|
115
|
-
3. What environment?
|
|
116
|
-
├─ Staging → Deploy on develop branch
|
|
117
|
-
└─ Production → Deploy on main branch only
|
|
118
|
-
|
|
119
|
-
4. Are migrations needed?
|
|
120
|
-
├─ YES → Run in staging first, test in CI
|
|
121
|
-
└─ NO → Continue
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
## CI/CD Checklist
|
|
125
|
-
|
|
126
|
-
Before committing CI/CD configuration, verify:
|
|
127
|
-
|
|
128
|
-
- [ ] Lint check configured
|
|
129
|
-
- [ ] Type check configured
|
|
130
|
-
- [ ] Tests run in CI
|
|
131
|
-
- [ ] Build succeeds in CI
|
|
132
|
-
- [ ] Security scan configured (recommended)
|
|
133
|
-
- [ ] Environment variables set as secrets
|
|
134
|
-
- [ ] Staging deployment configured
|
|
135
|
-
- [ ] Production deployment configured
|
|
136
|
-
- [ ] Migration strategy defined
|
|
137
|
-
- [ ] Required scripts in package.json
|
|
138
|
-
|
|
139
|
-
## Common CI/CD Mistakes
|
|
140
|
-
|
|
141
|
-
1. **Missing required checks** - Include all MUST checks
|
|
142
|
-
2. **Hardcoded secrets** - Always use secrets
|
|
143
|
-
3. **No staging environment** - Deploy to staging first
|
|
144
|
-
4. **No rollback plan** - Document rollback process
|
|
145
|
-
|
|
146
|
-
## Reference
|
|
147
|
-
|
|
148
|
-
- **Standard**: `packages/core/docs/standards/12-ci-cd-integration.md`
|
|
149
|
-
- **Testing**: See `04-testing-standards.mdc` for test configuration
|
|
150
|
-
- **Code Quality**: See `06-code-quality.mdc` for linting
|