@jmruthers/pace-core 0.6.6 → 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.
Files changed (246) hide show
  1. package/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +12 -13
  2. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  3. package/audit-tool/audits/02-project-structure.cjs +255 -0
  4. package/audit-tool/audits/03-architecture.cjs +196 -0
  5. package/audit-tool/audits/04-code-quality.cjs +149 -0
  6. package/audit-tool/audits/05-styling.cjs +224 -0
  7. package/audit-tool/audits/06-security-rbac.cjs +544 -0
  8. package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
  9. package/audit-tool/audits/08-testing-documentation.cjs +202 -0
  10. package/audit-tool/audits/09-operations.cjs +208 -0
  11. package/audit-tool/index.cjs +291 -0
  12. package/audit-tool/utils/code-utils.cjs +218 -0
  13. package/audit-tool/utils/file-utils.cjs +230 -0
  14. package/audit-tool/utils/report-utils.cjs +241 -0
  15. package/cursor-rules/00-standards-overview.mdc +156 -0
  16. package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
  17. package/cursor-rules/02-project-structure.mdc +37 -5
  18. package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
  19. package/cursor-rules/04-code-quality.mdc +419 -0
  20. package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
  21. package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
  22. package/cursor-rules/07-api-tech-stack.mdc +377 -0
  23. package/cursor-rules/08-testing-documentation.mdc +324 -0
  24. package/cursor-rules/09-operations.mdc +365 -0
  25. package/dist/DataTable-7PMH7XN7.js +15 -0
  26. package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
  27. package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +26 -16
  28. package/dist/{chunk-FENMYN2U.js → chunk-5X4QLXRG.js} +1 -3
  29. package/dist/{chunk-4T7OBVTU.js → chunk-6F3IILHI.js} +1 -1
  30. package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
  31. package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
  32. package/dist/{chunk-7TYHROIV.js → chunk-BM4CQ5P3.js} +50 -8
  33. package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
  34. package/dist/{chunk-OHIK3MIO.js → chunk-GHYHJTYV.js} +2 -2
  35. package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
  36. package/dist/{chunk-LAZMKTTF.js → chunk-JGWDVX64.js} +281 -347
  37. package/dist/{chunk-MAGBIDNS.js → chunk-L4XMVJKY.js} +2 -2
  38. package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
  39. package/dist/{chunk-ZS5VO5JB.js → chunk-Q7Q7V5NV.js} +406 -451
  40. package/dist/{chunk-3O3WHILE.js → chunk-VBCS3DUA.js} +236 -60
  41. package/dist/{chunk-BVP2BCJF.js → chunk-ZKAWKYT4.js} +8 -8
  42. package/dist/components.d.ts +5 -4
  43. package/dist/components.js +27 -32
  44. package/dist/eslint-rules/index.cjs +22 -9
  45. package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
  46. package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
  47. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  48. package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +26 -10
  49. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
  50. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  51. package/dist/hooks.d.ts +5 -5
  52. package/dist/hooks.js +6 -6
  53. package/dist/index.d.ts +6 -6
  54. package/dist/index.js +18 -17
  55. package/dist/rbac/index.js +6 -6
  56. package/dist/theming/runtime.d.ts +14 -1
  57. package/dist/theming/runtime.js +1 -1
  58. package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
  59. package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
  60. package/dist/utils.d.ts +2 -2
  61. package/dist/utils.js +8 -8
  62. package/docs/README.md +1 -1
  63. package/docs/api/modules.md +47 -31
  64. package/docs/api-reference/components.md +18 -20
  65. package/docs/api-reference/hooks.md +80 -80
  66. package/docs/api-reference/types.md +1 -1
  67. package/docs/api-reference/utilities.md +1 -1
  68. package/docs/architecture/README.md +1 -1
  69. package/docs/core-concepts/events.md +3 -3
  70. package/docs/core-concepts/organisations.md +6 -6
  71. package/docs/core-concepts/permissions.md +6 -6
  72. package/docs/documentation-index.md +12 -18
  73. package/docs/getting-started/documentation-index.md +1 -1
  74. package/docs/getting-started/examples/README.md +4 -4
  75. package/docs/getting-started/examples/full-featured-app.md +1 -1
  76. package/docs/getting-started/faq.md +2 -2
  77. package/docs/getting-started/quick-reference.md +4 -4
  78. package/docs/implementation-guides/authentication.md +15 -15
  79. package/docs/implementation-guides/component-styling.md +1 -1
  80. package/docs/implementation-guides/data-tables.md +126 -33
  81. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  82. package/docs/implementation-guides/dynamic-colors.md +3 -3
  83. package/docs/implementation-guides/file-upload-storage.md +2 -2
  84. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  85. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  86. package/docs/implementation-guides/large-datasets.md +3 -2
  87. package/docs/implementation-guides/organisation-security.md +2 -2
  88. package/docs/implementation-guides/performance.md +2 -2
  89. package/docs/implementation-guides/permission-enforcement.md +1 -1
  90. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  91. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  92. package/docs/rbac/README.md +5 -5
  93. package/docs/rbac/advanced-patterns.md +6 -6
  94. package/docs/rbac/api-reference.md +20 -20
  95. package/docs/rbac/event-based-apps.md +3 -3
  96. package/docs/rbac/examples.md +41 -41
  97. package/docs/rbac/getting-started.md +37 -37
  98. package/docs/rbac/performance.md +1 -1
  99. package/docs/rbac/quick-start.md +52 -52
  100. package/docs/rbac/secure-client-protection.md +1 -1
  101. package/docs/rbac/troubleshooting.md +1 -1
  102. package/docs/security/README.md +5 -5
  103. package/docs/standards/0-standards-overview.md +220 -0
  104. package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +204 -185
  105. package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
  106. package/docs/standards/3-architecture-standards.md +606 -0
  107. package/docs/standards/4-code-quality-standards.md +728 -0
  108. package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
  109. package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
  110. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  111. package/docs/standards/8-testing-documentation-standards.md +401 -0
  112. package/docs/standards/9-operations-standards.md +1102 -0
  113. package/docs/standards/README.md +203 -104
  114. package/docs/troubleshooting/README.md +4 -4
  115. package/docs/troubleshooting/common-issues.md +2 -2
  116. package/docs/troubleshooting/debugging.md +9 -9
  117. package/docs/troubleshooting/migration.md +4 -4
  118. package/eslint-config-pace-core.cjs +21 -10
  119. package/package.json +6 -5
  120. package/scripts/install-cursor-rules.cjs +11 -243
  121. package/scripts/install-eslint-config.cjs +284 -0
  122. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
  123. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  124. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +10 -10
  125. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  126. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  127. package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
  128. package/src/__tests__/templates/component.test.template.tsx +18 -15
  129. package/src/components/Calendar/Calendar.tsx +201 -47
  130. package/src/components/ContextSelector/ContextSelector.tsx +137 -153
  131. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  132. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
  133. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
  134. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  135. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  136. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  137. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  138. package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
  139. package/src/components/DataTable/components/EditableRow.tsx +5 -7
  140. package/src/components/DataTable/components/EmptyState.tsx +10 -9
  141. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  142. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  143. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  144. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  145. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  146. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  147. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  148. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  149. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  150. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
  151. package/src/components/DataTable/components/index.ts +2 -1
  152. package/src/components/DataTable/types.ts +0 -18
  153. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  154. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
  155. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  156. package/src/components/DateTimeField/DateTimeField.tsx +7 -8
  157. package/src/components/Dialog/Dialog.test.tsx +1 -0
  158. package/src/components/Dialog/Dialog.tsx +25 -8
  159. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  160. package/src/components/FileUpload/FileUpload.test.tsx +52 -14
  161. package/src/components/FileUpload/FileUpload.tsx +112 -130
  162. package/src/components/Progress/Progress.tsx +2 -4
  163. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  164. package/src/components/Select/Select.tsx +86 -77
  165. package/src/components/Select/types.ts +3 -0
  166. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  167. package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
  168. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
  169. package/src/hooks/public/usePublicEvent.ts +5 -5
  170. package/src/hooks/public/usePublicEventLogo.ts +5 -5
  171. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  172. package/src/hooks/public/usePublicRouteParams.ts +5 -5
  173. package/src/hooks/useAppConfig.ts +2 -2
  174. package/src/hooks/useEventTheme.test.ts +7 -7
  175. package/src/hooks/useEventTheme.ts +1 -4
  176. package/src/hooks/useFileDisplay.ts +2 -2
  177. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  178. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  179. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  180. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  181. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  182. package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
  183. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  184. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  185. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
  186. package/src/styles/core.css +7 -0
  187. package/src/theming/__tests__/parseEventColours.test.ts +9 -3
  188. package/src/theming/parseEventColours.ts +22 -10
  189. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  190. package/src/utils/storage/README.md +1 -1
  191. package/cursor-rules/01-standards-compliance.mdc +0 -285
  192. package/cursor-rules/04-testing-standards.mdc +0 -270
  193. package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
  194. package/cursor-rules/06-code-quality.mdc +0 -311
  195. package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
  196. package/cursor-rules/10-error-handling-patterns.mdc +0 -179
  197. package/cursor-rules/11-performance-optimization.mdc +0 -169
  198. package/cursor-rules/12-ci-cd-integration.mdc +0 -150
  199. package/dist/DataTable-LRJL4IRV.js +0 -15
  200. package/dist/eslint-rules/rules/compliance.cjs +0 -348
  201. package/dist/eslint-rules/rules/components.cjs +0 -113
  202. package/dist/eslint-rules/rules/imports.cjs +0 -102
  203. package/docs/best-practices/README.md +0 -472
  204. package/docs/best-practices/accessibility.md +0 -604
  205. package/docs/best-practices/common-patterns.md +0 -516
  206. package/docs/best-practices/deployment.md +0 -1103
  207. package/docs/best-practices/performance.md +0 -1328
  208. package/docs/best-practices/security.md +0 -940
  209. package/docs/best-practices/testing.md +0 -1034
  210. package/docs/rbac/compliance/compliance-guide.md +0 -544
  211. package/docs/standards/01-standards-compliance.md +0 -188
  212. package/docs/standards/03-solid-principles.md +0 -39
  213. package/docs/standards/04-testing-standards.md +0 -36
  214. package/docs/standards/05-bug-reports-and-features.md +0 -27
  215. package/docs/standards/06-code-quality.md +0 -34
  216. package/docs/standards/07-tech-stack-compliance.md +0 -30
  217. package/docs/standards/10-error-handling-patterns.md +0 -401
  218. package/docs/standards/11-performance-optimization.md +0 -348
  219. package/docs/standards/12-ci-cd-integration.md +0 -370
  220. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
  221. package/scripts/audit/audit-compliance.cjs +0 -1295
  222. package/scripts/audit/audit-components.cjs +0 -260
  223. package/scripts/audit/audit-rbac.cjs +0 -954
  224. package/scripts/audit/audit-standards.cjs +0 -1268
  225. package/scripts/audit/index.cjs +0 -1927
  226. package/src/components/DataTable/components/DataTableBody.tsx +0 -478
  227. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  228. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  229. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  230. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  231. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  232. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  233. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  234. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  235. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  236. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  237. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  238. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  239. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  240. package/src/components/DataTable/utils/debugTools.ts +0 -514
  241. package/src/eslint-rules/index.cjs +0 -22
  242. package/src/eslint-rules/rules/components.cjs +0 -113
  243. package/src/eslint-rules/rules/imports.cjs +0 -102
  244. package/src/eslint-rules/rules/rbac.cjs +0 -790
  245. package/src/eslint-rules/utils/helpers.cjs +0 -42
  246. package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
@@ -1,311 +0,0 @@
1
- ---
2
- description: Enforce code quality standards including TypeScript, ESLint, formatting, performance, and accessibility
3
- globs: ["src/**/*.{ts,tsx,js,jsx}"]
4
- alwaysApply: false
5
- paceCoreVersion: "0.6.x"
6
- rulesVersion: "2025-01-28"
7
- ---
8
- # Code Quality Guide
9
-
10
- **📚 Human-Readable Standard**: See [06-code-quality.md](../../packages/core/docs/standards/06-code-quality.md) for complete documentation.
11
-
12
- This guide enforces code quality standards to ensure maintainable, performant, and accessible code.
13
-
14
- ## TypeScript Standards
15
-
16
- ### MUST: Use Strict Mode
17
-
18
- **TypeScript MUST use strict mode:**
19
-
20
- ```json
21
- // tsconfig.json
22
- {
23
- "compilerOptions": {
24
- "strict": true,
25
- "noImplicitAny": true,
26
- "strictNullChecks": true,
27
- "strictFunctionTypes": true,
28
- "strictBindCallApply": true,
29
- "strictPropertyInitialization": true,
30
- "noImplicitThis": true,
31
- "alwaysStrict": true
32
- }
33
- }
34
- ```
35
-
36
- ### MUST NOT: Use `any`
37
-
38
- **MUST NOT use `any` type. Use `unknown` if type is truly unknown:**
39
-
40
- ```tsx
41
- // ❌ WRONG: Using any
42
- function processData(data: any) { return data.value; }
43
-
44
- // ✅ CORRECT: Using unknown with type guard or proper types
45
- function processData(data: unknown) {
46
- if (typeof data === 'object' && data !== null && 'value' in data) {
47
- return (data as { value: string }).value;
48
- }
49
- throw new Error('Invalid data');
50
- }
51
- // Or: interface Data { value: string; } function processData(data: Data) { return data.value; }
52
- ```
53
-
54
- ### MUST: Use Discriminated Unions
55
-
56
- **MUST use discriminated unions instead of boolean flags:**
57
-
58
- ```tsx
59
- // ❌ WRONG: Boolean flags (confusing: what if both are true?)
60
- interface User { isAdmin: boolean; isGuest: boolean; }
61
-
62
- // ✅ CORRECT: Discriminated union
63
- type User = { type: 'admin'; permissions: Permission[] } | { type: 'guest'; limitedAccess: boolean } | { type: 'user'; role: UserRole };
64
- ```
65
-
66
- ### SHOULD: Use ReadonlyArray
67
-
68
- **SHOULD use ReadonlyArray for immutable arrays:**
69
-
70
- ```tsx
71
- // ✅ CORRECT - ReadonlyArray
72
- function processItems(items: ReadonlyArray<Item>) {
73
- // Can't mutate items
74
- return items.map(item => transform(item));
75
- }
76
- ```
77
-
78
- ## ESLint Configuration
79
-
80
- ### MUST: Use pace-core ESLint Config
81
-
82
- **MUST extend pace-core ESLint configuration:**
83
-
84
- ```javascript
85
- // eslint.config.js
86
- import paceCoreConfig from '@jmruthers/pace-core/eslint-config';
87
-
88
- export default [
89
- ...paceCoreConfig,
90
- // Your additional config
91
- ];
92
- ```
93
-
94
- ### MUST: Fix ESLint Errors
95
-
96
- **MUST fix all ESLint errors before committing:**
97
-
98
- ```bash
99
- npm run lint
100
- npm run lint:fix # Auto-fix where possible
101
- ```
102
-
103
- ## Code Formatting
104
-
105
- ### MUST: Use Consistent Formatting
106
-
107
- **MUST use Prettier or equivalent for consistent formatting:**
108
-
109
- ```json
110
- // .prettierrc
111
- {
112
- "semi": true,
113
- "singleQuote": true,
114
- "tabWidth": 2,
115
- "trailingComma": "es5",
116
- "printWidth": 100
117
- }
118
- ```
119
-
120
- ### MUST: Format Before Committing
121
-
122
- **MUST format code before committing:**
123
-
124
- ```bash
125
- npm run format
126
- # Or use pre-commit hook
127
- ```
128
-
129
- ## Performance Considerations
130
-
131
- ### SHOULD: Optimize Re-renders
132
-
133
- **SHOULD use React.memo, useMemo, useCallback appropriately:**
134
-
135
- ```tsx
136
- // ✅ CORRECT: Memoize expensive computations, callbacks, and components
137
- const expensiveValue = useMemo(() => computeExpensiveValue(data), [data]);
138
- const handleClick = useCallback(() => doSomething(id), [id]);
139
- const ExpensiveComponent = React.memo(({ data }) => <div>{/* ... */}</div>);
140
- ```
141
-
142
- ### SHOULD: Avoid Unnecessary Re-renders
143
-
144
- **SHOULD avoid causing unnecessary re-renders:**
145
-
146
- ```tsx
147
- // ❌ WRONG: New object on every render (causes unnecessary re-renders)
148
- function Component({ items }) { const config = { items, enabled: true }; return <Child config={config} />; }
149
-
150
- // ✅ CORRECT: Memoize object
151
- function Component({ items }) {
152
- const config = useMemo(() => ({ items, enabled: true }), [items]);
153
- return <Child config={config} />;
154
- }
155
- ```
156
-
157
- ### SHOULD: Lazy Load Heavy Components
158
-
159
- **SHOULD lazy load heavy components:**
160
-
161
- ```tsx
162
- // ✅ CORRECT: Lazy load heavy components
163
- import { lazy, Suspense } from 'react';
164
- const HeavyComponent = lazy(() => import('./HeavyComponent'));
165
- function App() {
166
- return <Suspense fallback={<Loading />}><HeavyComponent /></Suspense>;
167
- }
168
- ```
169
-
170
- ## Accessibility Requirements
171
-
172
- ### MUST: Use Semantic HTML
173
-
174
- **MUST use semantic HTML elements:**
175
-
176
- ```tsx
177
- // ❌ WRONG: Non-semantic (<div onClick={...}>)
178
- // ✅ CORRECT: Semantic HTML (<button onClick={...}>)
179
- ```
180
-
181
- ### MUST: Provide ARIA Labels
182
-
183
- **MUST provide ARIA labels for interactive elements:**
184
-
185
- ```tsx
186
- // ✅ CORRECT: Provide ARIA labels for interactive elements
187
- <button aria-label="Close dialog">×</button>
188
- <input aria-label="Search" type="search" />
189
- ```
190
-
191
- ### MUST: Ensure Keyboard Navigation
192
-
193
- **MUST ensure all interactive elements are keyboard accessible:**
194
-
195
- ```tsx
196
- // ✅ CORRECT: Ensure keyboard navigation (Enter or Space key)
197
- <button onClick={handleClick} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') handleClick(); }}>Click me</button>
198
- ```
199
-
200
- ### MUST: Provide Focus Indicators
201
-
202
- **MUST provide visible focus indicators:**
203
-
204
- ```tsx
205
- // ✅ CORRECT: Provide visible focus indicators
206
- <button className="focus:outline-none focus:ring-2 focus:ring-main-500">Click me</button>
207
- ```
208
-
209
- ## Code Review Checklist
210
-
211
- **Before submitting code for review, verify:**
212
-
213
- - [ ] TypeScript strict mode enabled
214
- - [ ] No `any` types used
215
- - [ ] ESLint passes with no errors
216
- - [ ] Code is formatted consistently
217
- - [ ] Performance optimizations applied where needed
218
- - [ ] Accessibility requirements met
219
- - [ ] Semantic HTML used
220
- - [ ] ARIA labels provided
221
- - [ ] Keyboard navigation works
222
- - [ ] Focus indicators visible
223
- - [ ] Code is readable and maintainable
224
- - [ ] Comments explain "why", not "what"
225
-
226
- ## Code Complexity
227
-
228
- ### SHOULD: Keep Functions Small
229
-
230
- **Functions SHOULD be small and focused:**
231
-
232
- ```tsx
233
- // ❌ WRONG: Large function (100+ lines, multiple responsibilities)
234
- function processUserData(user) { /* 100+ lines of logic */ }
235
-
236
- // ✅ CORRECT: Small, focused functions
237
- function validateUser(user: User): ValidationResult { /* Validation logic */ }
238
- function transformUser(user: User): TransformedUser { /* Transformation logic */ }
239
- function processUserData(user: User) {
240
- const validation = validateUser(user);
241
- if (!validation.valid) return validation;
242
- return transformUser(user);
243
- }
244
- ```
245
-
246
- ### SHOULD: Limit Cyclomatic Complexity
247
-
248
- **Functions SHOULD have low cyclomatic complexity (< 10):**
249
-
250
- ```tsx
251
- // ❌ WRONG: High complexity (many nested conditions)
252
- function processData(data) { if (condition1) { if (condition2) { if (condition3) { /* ... */ } } } }
253
-
254
- // ✅ CORRECT: Lower complexity (early returns)
255
- function processData(data) { if (!condition1) return; if (!condition2) return; if (!condition3) return; /* Process */ }
256
- ```
257
-
258
- ## Error Handling
259
-
260
- ### MUST: Handle Errors Gracefully
261
-
262
- **MUST handle errors and provide user feedback:**
263
-
264
- ```tsx
265
- // ✅ CORRECT: Handle errors gracefully with user feedback
266
- try {
267
- const data = await fetchData();
268
- setData(data);
269
- } catch (error) {
270
- logger.error('Failed to fetch data', error);
271
- toast.error('Failed to load data. Please try again.');
272
- }
273
- ```
274
-
275
- ### MUST: Use Type-Safe Error Handling
276
-
277
- **MUST use type-safe error handling:**
278
-
279
- ```tsx
280
- // ✅ CORRECT: Type-safe error handling
281
- function isApiError(error: unknown): error is ApiError {
282
- return typeof error === 'object' && error !== null && 'code' in error && 'message' in error;
283
- }
284
- try {
285
- await apiCall();
286
- } catch (error) {
287
- if (isApiError(error)) handleApiError(error);
288
- else handleUnknownError(error);
289
- }
290
- ```
291
-
292
- ## Code Quality Checklist
293
-
294
- Before committing, verify:
295
- - [ ] TypeScript strict mode enabled
296
- - [ ] No `any` types
297
- - [ ] ESLint passes
298
- - [ ] Code formatted
299
- - [ ] Performance optimized
300
- - [ ] Accessible (semantic HTML, ARIA, keyboard)
301
- - [ ] Functions are small and focused
302
- - [ ] Error handling in place
303
- - [ ] Code is readable
304
- - [ ] Comments explain "why"
305
-
306
- ## Reference
307
-
308
- - TypeScript Handbook: https://www.typescriptlang.org/docs/
309
- - ESLint Rules: pace-core eslint-config
310
- - React Performance: https://react.dev/learn/render-and-commit
311
- - Web Accessibility: https://www.w3.org/WAI/
@@ -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