@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,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
@@ -1,15 +0,0 @@
1
- export { ActionButtons, BulkOperationsDropdown, ColumnFactory, ColumnVisibilityDropdown, DataTable, DataTableCore, DataTableErrorBoundary, DataTableModals, DataTableToolbar, EditableRow, EmptyState, EnhancedPaginationControls, GroupHeader, GroupingDropdown, ImportModal, LoadingState, PaginationControls, UnifiedTableBody, announce, announceBulkOperation, announceFilterChange, announceLoadingState, announcePaginationChange, announceSearchResults, announceSelectionChange, announceSortChange, average, calculateAllDepths, calculateAllIndentation, calculateIndentation, calculateOptimalPageSize, cleanupLiveRegion, count, createHierarchicalStructure, defaultDataTableFeatures, exportToCSV, exportToCSVWithTableRows, generateCSVContent, getAriaSortValue, getCellRenderer, getColumnHeaderText, getHierarchicalSortConfig, getPageSizeOptions, getPaginationBinding, getRowDepth, getRowDescription, getRowIdSafe, getSortButtonLabel, groupHierarchicalData, hasValidRowId, initializeLiveRegion, isHierarchicalSortableColumn, max, min, normalizeDataTableFeatures, shouldShowColumnForRow, sortHierarchicalDataByStructure, sortHierarchicalDataWithSorting, sum, validateHierarchicalData, validatePaginationConfig } from './chunk-ZS5VO5JB.js';
2
- import './chunk-7TYHROIV.js';
3
- export { CircuitBreaker, DEFAULT_FALLBACK_CONFIG, DataChunkManager, DataTableError, DataTableErrorType, ErrorRecoveryManager, MemoryMonitor, SearchIndex, VisibilityTracker, chunkData, debounce, determinePaginationMode, getOptimalPageSizeOptions, safeExecute, throttle, useDataTablePerformance } from './chunk-S7DKJPLT.js';
4
- import './chunk-3O3WHILE.js';
5
- import './chunk-C7NSAPTL.js';
6
- import './chunk-FTCRZOG2.js';
7
- import './chunk-ZFYPMX46.js';
8
- import './chunk-AHU7G2R5.js';
9
- import './chunk-4SXLQIZO.js';
10
- import './chunk-3QC3KRHK.js';
11
- import './chunk-A55DK444.js';
12
- import './chunk-SD6WQY43.js';
13
- import './chunk-HF6O3O37.js';
14
- import './chunk-TTRFSOKR.js';
15
- import './chunk-3RG5ZIWI.js';
@@ -1,348 +0,0 @@
1
- /**
2
- * General compliance rules
3
- * @package @jmruthers/pace-core
4
- * @module ESLintRules/rules/compliance
5
- */
6
-
7
- const path = require('path');
8
- const { getPaceCoreComponents, getPaceCoreHooks, getPaceCoreUtils } = require('../utils/manifest-loader.cjs');
9
- const { isPaceCoreSourceFile } = require('../utils/helpers.cjs');
10
-
11
- module.exports = {
12
- rules: {
13
- /**
14
- * Prefer pace-core components over native HTML elements or custom implementations
15
- */
16
- 'prefer-pace-core-components': {
17
- meta: {
18
- type: 'suggestion',
19
- docs: {
20
- description: 'Suggest using pace-core components instead of native HTML elements',
21
- category: 'Best Practices',
22
- recommended: true
23
- },
24
- hasSuggestions: true,
25
- messages: {
26
- preferButton: "Use 'Button' component from '@jmruthers/pace-core' instead of <button>",
27
- preferInput: "Use 'Input' component from '@jmruthers/pace-core' instead of <input>",
28
- preferTextarea: "Use 'Textarea' component from '@jmruthers/pace-core' instead of <textarea>",
29
- preferLabel: "Use 'Label' component from '@jmruthers/pace-core' instead of <label>",
30
- preferForm: "Use 'Form' component from '@jmruthers/pace-core' instead of custom form implementation"
31
- }
32
- },
33
- create(context) {
34
- const filename = context.getFilename();
35
-
36
- // Exclude pace-core source files - these rules are for consuming apps
37
- if (isPaceCoreSourceFile(filename)) {
38
- return {};
39
- }
40
-
41
- const paceCoreComponents = getPaceCoreComponents();
42
-
43
- return {
44
- JSXOpeningElement(node) {
45
- const elementName = node.name.name;
46
-
47
- if (!elementName) return;
48
-
49
- // Only flag lowercase native HTML elements, not capitalized components
50
- // Native HTML: <button>, <input>, <label>, <textarea>
51
- // Components: <Button>, <Input>, <Label>, <Textarea>
52
- const isNativeHTMLElement = elementName === elementName.toLowerCase();
53
-
54
- if (!isNativeHTMLElement) {
55
- // This is a capitalized component, not a native HTML element
56
- return;
57
- }
58
-
59
- // Check for native HTML elements that have pace-core alternatives
60
- const nativeToPaceCore = {
61
- 'button': 'Button',
62
- 'input': 'Input',
63
- 'textarea': 'Textarea',
64
- 'label': 'Label'
65
- };
66
-
67
- if (nativeToPaceCore[elementName]) {
68
- const paceCoreComponent = nativeToPaceCore[elementName];
69
- if (paceCoreComponents.includes(paceCoreComponent)) {
70
- context.report({
71
- node,
72
- messageId: `prefer${paceCoreComponent}`,
73
- suggest: [{
74
- desc: `Import and use ${paceCoreComponent} from pace-core`,
75
- fix(fixer) {
76
- // This is a complex fix, so we'll just report
77
- return null;
78
- }
79
- }]
80
- });
81
- }
82
- }
83
- }
84
- };
85
- }
86
- },
87
-
88
- /**
89
- * Detect custom hooks that duplicate pace-core functionality
90
- */
91
- 'prefer-pace-core-hooks': {
92
- meta: {
93
- type: 'suggestion',
94
- docs: {
95
- description: 'Suggest using pace-core hooks instead of custom implementations',
96
- category: 'Best Practices',
97
- recommended: true
98
- },
99
- messages: {
100
- preferPaceCoreHook: "Consider using '{{hook}}' from '@jmruthers/pace-core' instead of custom hook '{{customHook}}'"
101
- }
102
- },
103
- create(context) {
104
- const filename = context.getFilename();
105
-
106
- // Exclude pace-core source files - these rules are for consuming apps
107
- if (isPaceCoreSourceFile(filename)) {
108
- return {};
109
- }
110
-
111
- const paceCoreHooks = getPaceCoreHooks();
112
- const hookPatterns = {
113
- 'useToast': ['useToast', 'useNotification', 'useSnackbar'],
114
- 'useDebounce': ['useDebounce', 'useDebounced'],
115
- 'useAuth': ['useAuth', 'useAuthentication', 'useUser'],
116
- 'useFile': ['useFile', 'useFileUpload', 'useFileReference'],
117
- 'useForm': ['useForm', 'useZodForm'],
118
- 'useTable': ['useTable', 'useDataTable']
119
- };
120
-
121
- return {
122
- FunctionDeclaration(node) {
123
- const functionName = node.id?.name;
124
- if (!functionName || !functionName.startsWith('use')) return;
125
-
126
- // Check if this looks like a hook that pace-core provides
127
- for (const [paceCoreHook, patterns] of Object.entries(hookPatterns)) {
128
- if (paceCoreHooks.includes(paceCoreHook)) {
129
- for (const pattern of patterns) {
130
- if (functionName.toLowerCase().includes(pattern.toLowerCase().replace('use', ''))) {
131
- context.report({
132
- node: node.id,
133
- messageId: 'preferPaceCoreHook',
134
- data: {
135
- hook: paceCoreHook,
136
- customHook: functionName
137
- }
138
- });
139
- return;
140
- }
141
- }
142
- }
143
- }
144
- }
145
- };
146
- }
147
- },
148
-
149
- /**
150
- * Detect utility functions that duplicate pace-core functionality
151
- */
152
- 'prefer-pace-core-utils': {
153
- meta: {
154
- type: 'suggestion',
155
- docs: {
156
- description: 'Suggest using pace-core utilities instead of custom implementations',
157
- category: 'Best Practices',
158
- recommended: true
159
- },
160
- messages: {
161
- preferPaceCoreUtil: "Consider using '{{util}}' from '@jmruthers/pace-core' instead of custom function '{{customUtil}}'"
162
- }
163
- },
164
- create(context) {
165
- const filename = context.getFilename();
166
-
167
- // Exclude pace-core source files - these rules are for consuming apps
168
- if (isPaceCoreSourceFile(filename)) {
169
- return {};
170
- }
171
-
172
- const paceCoreUtils = getPaceCoreUtils();
173
- const utilPatterns = {
174
- 'formatDate': ['formatDate', 'formatDateTime', 'dateFormat'],
175
- 'formatCurrency': ['formatCurrency', 'formatMoney', 'currencyFormat'],
176
- 'formatNumber': ['formatNumber', 'numberFormat'],
177
- 'cn': ['cn', 'classNames', 'clsx', 'mergeClasses'],
178
- 'validateUserInput': ['validateInput', 'validateUser', 'validateUserInput'],
179
- 'sanitizeUserInput': ['sanitize', 'sanitizeInput', 'sanitizeUser']
180
- };
181
-
182
- // Patterns that should NOT trigger validateUserInput warnings
183
- // These are for API/config validation, not user input validation
184
- const excludePatterns = [
185
- 'validateApi',
186
- 'validateRequest',
187
- 'validateConfig',
188
- 'validateKey',
189
- 'validateToken',
190
- 'validateAuth',
191
- 'validateRateLimit',
192
- 'validatePermission',
193
- 'validateAccess'
194
- ];
195
-
196
- return {
197
- FunctionDeclaration(node) {
198
- const functionName = node.id?.name;
199
- if (!functionName) return;
200
-
201
- // Skip if function name matches exclude patterns (API/config validation, not user input)
202
- const lowerName = functionName.toLowerCase();
203
- if (excludePatterns.some(pattern => lowerName.includes(pattern.toLowerCase()))) {
204
- return;
205
- }
206
-
207
- // Check if this looks like a util that pace-core provides
208
- for (const [paceCoreUtil, patterns] of Object.entries(utilPatterns)) {
209
- if (paceCoreUtils.includes(paceCoreUtil)) {
210
- for (const pattern of patterns) {
211
- // Only match if the pattern is a significant part of the function name
212
- // Don't match generic "validate" - it's too broad
213
- if (paceCoreUtil === 'validateUserInput' && pattern === 'validate') {
214
- // Skip generic "validate" - too many false positives
215
- continue;
216
- }
217
-
218
- if (functionName.toLowerCase().includes(pattern.toLowerCase())) {
219
- context.report({
220
- node: node.id,
221
- messageId: 'preferPaceCoreUtil',
222
- data: {
223
- util: paceCoreUtil,
224
- customUtil: functionName
225
- }
226
- });
227
- return;
228
- }
229
- }
230
- }
231
- }
232
- }
233
- };
234
- }
235
- },
236
-
237
- /**
238
- * Detect component files with names matching pace-core components
239
- */
240
- 'no-local-component-duplication': {
241
- meta: {
242
- type: 'problem',
243
- docs: {
244
- description: 'Disallow local components with names matching pace-core components',
245
- category: 'Best Practices',
246
- recommended: true
247
- },
248
- messages: {
249
- duplicateComponent: "Component '{{componentName}}' conflicts with pace-core component. Use '@jmruthers/pace-core' instead of creating a local version."
250
- }
251
- },
252
- create(context) {
253
- const filename = context.getFilename();
254
-
255
- // Exclude pace-core source files - these rules are for consuming apps
256
- if (isPaceCoreSourceFile(filename)) {
257
- return {};
258
- }
259
-
260
- const paceCoreComponents = getPaceCoreComponents();
261
-
262
- // Only check component files (components/, src/components/, etc.)
263
- if (!filename.match(/(components|Components)\//)) {
264
- return {};
265
- }
266
-
267
- // Extract component name from filename
268
- const basename = path.basename(filename, path.extname(filename));
269
- const componentName = basename.replace(/\.(test|spec)$/, '');
270
-
271
- return {
272
- Program(node) {
273
- // Check if this file exports a component with a name matching pace-core
274
- if (paceCoreComponents.includes(componentName)) {
275
- // Check if file exports this component
276
- const hasExport = node.body.some(stmt => {
277
- if (stmt.type === 'ExportNamedDeclaration') {
278
- return stmt.declaration?.id?.name === componentName ||
279
- stmt.specifiers?.some(spec => spec.exported.name === componentName);
280
- }
281
- if (stmt.type === 'ExportDefaultDeclaration') {
282
- return stmt.declaration?.id?.name === componentName ||
283
- stmt.declaration?.name === componentName;
284
- }
285
- return false;
286
- });
287
-
288
- if (hasExport) {
289
- context.report({
290
- node,
291
- messageId: 'duplicateComponent',
292
- data: {
293
- componentName
294
- }
295
- });
296
- }
297
- }
298
- }
299
- };
300
- }
301
- },
302
-
303
- /**
304
- * Disallow inline styles
305
- */
306
- 'no-inline-styles': {
307
- meta: {
308
- type: 'problem',
309
- docs: {
310
- description: 'Disallow inline styles. Use pace-core components or Tailwind classes instead.',
311
- category: 'Best Practices',
312
- recommended: true
313
- },
314
- messages: {
315
- inlineStyle: 'Inline style detected. Use pace-core components or Tailwind classes instead.'
316
- },
317
- hasSuggestions: true
318
- },
319
- create(context) {
320
- const filename = context.getFilename();
321
-
322
- // Exclude pace-core source files - these rules are for consuming apps
323
- if (isPaceCoreSourceFile(filename)) {
324
- return {};
325
- }
326
-
327
- return {
328
- JSXAttribute(node) {
329
- if (node.name && node.name.name === 'style') {
330
- context.report({
331
- node,
332
- messageId: 'inlineStyle',
333
- suggest: [{
334
- desc: 'Remove inline style and use pace-core component styling or Tailwind utility classes',
335
- fix(fixer) {
336
- // Remove the style attribute
337
- return fixer.remove(node);
338
- }
339
- }]
340
- });
341
- }
342
- }
343
- };
344
- }
345
- }
346
- }
347
- };
348
-