@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,113 +0,0 @@
1
- /**
2
- * Component usage rules
3
- * @package @jmruthers/pace-core
4
- * @module ESLintRules/rules/components
5
- */
6
-
7
- const { isPaceCoreSourceFile } = require('../utils/helpers.cjs');
8
-
9
- module.exports = {
10
- rules: {
11
- /**
12
- * Prefer pace-core Form component over plain form tags and direct react-hook-form usage
13
- */
14
- 'prefer-pace-core-form': {
15
- meta: {
16
- type: 'problem',
17
- docs: {
18
- description: 'Disallow plain <form> tags and direct react-hook-form imports. Use pace-core Form component instead.',
19
- category: 'Best Practices',
20
- recommended: true
21
- },
22
- messages: {
23
- plainFormTag: "Plain <form> tag detected. Use pace-core Form component instead.",
24
- reactHookFormImport: "Direct import from 'react-hook-form' detected: {{imports}}. Use pace-core Form component instead. useFormContext is allowed when Form is imported from pace-core."
25
- },
26
- hasSuggestions: true
27
- },
28
- create(context) {
29
- const filename = context.getFilename();
30
-
31
- // Exclude pace-core source files - these rules are for consuming apps
32
- if (isPaceCoreSourceFile(filename)) {
33
- return {};
34
- }
35
-
36
- let hasPaceCoreForm = false;
37
- const problematicImports = ['useForm', 'FormProvider', 'Controller', 'useWatch', 'useFieldArray', 'useController'];
38
-
39
- return {
40
- ImportDeclaration(node) {
41
- const importSource = node.source.value;
42
-
43
- // Check if Form is imported from pace-core
44
- if (importSource === '@jmruthers/pace-core' ||
45
- importSource === '@jmruthers/pace-core/components') {
46
- const hasForm = node.specifiers.some(spec => {
47
- if (spec.type === 'ImportSpecifier') {
48
- return spec.imported.name === 'Form';
49
- }
50
- return false;
51
- });
52
- if (hasForm) {
53
- hasPaceCoreForm = true;
54
- }
55
- }
56
-
57
- // Check for react-hook-form imports
58
- if (importSource === 'react-hook-form') {
59
- const importedItems = node.specifiers
60
- .filter(spec => spec.type === 'ImportSpecifier')
61
- .map(spec => spec.imported.name);
62
-
63
- const foundProblematic = importedItems.filter(item => problematicImports.includes(item));
64
-
65
- // Allow useFormContext when Form is imported from pace-core
66
- const isAcceptable = hasPaceCoreForm &&
67
- foundProblematic.length === 1 &&
68
- foundProblematic[0] === 'useFormContext';
69
-
70
- if (foundProblematic.length > 0 && !isAcceptable) {
71
- context.report({
72
- node: node.source,
73
- messageId: 'reactHookFormImport',
74
- data: {
75
- imports: foundProblematic.join(', ')
76
- },
77
- suggest: [{
78
- desc: 'Use pace-core Form component instead',
79
- fix(fixer) {
80
- return fixer.remove(node);
81
- }
82
- }]
83
- });
84
- }
85
- }
86
- },
87
-
88
- JSXOpeningElement(node) {
89
- // Check for plain <form> tags (lowercase, not Form component)
90
- if (node.name.type === 'JSXIdentifier') {
91
- const elementName = node.name.name;
92
- // Check if it's lowercase 'form' (not 'Form' component)
93
- if (elementName === 'form') {
94
- context.report({
95
- node,
96
- messageId: 'plainFormTag',
97
- suggest: [{
98
- desc: 'Replace with pace-core Form component',
99
- fix(fixer) {
100
- // This is complex to auto-fix, so we'll just report
101
- return null;
102
- }
103
- }]
104
- });
105
- }
106
- }
107
- }
108
- };
109
- }
110
- }
111
- }
112
- };
113
-
@@ -1,102 +0,0 @@
1
- /**
2
- * Import restriction rules
3
- * @package @jmruthers/pace-core
4
- * @module ESLintRules/rules/imports
5
- */
6
-
7
- const { getRestrictedImports } = require('../utils/manifest-loader.cjs');
8
- const { getPaceCoreAlternative, isPaceCoreSourceFile } = require('../utils/helpers.cjs');
9
-
10
- module.exports = {
11
- rules: {
12
- /**
13
- * Block direct imports of libraries wrapped by pace-core
14
- */
15
- 'no-restricted-imports': {
16
- meta: {
17
- type: 'problem',
18
- docs: {
19
- description: 'Disallow direct imports of libraries that pace-core wraps',
20
- category: 'Best Practices',
21
- recommended: true
22
- },
23
- fixable: 'code',
24
- hasSuggestions: true,
25
- messages: {
26
- restrictedImport: '{{message}} Import from {{alternative}} instead.',
27
- restrictedImportWithReason: '{{message}} {{reason}}'
28
- }
29
- },
30
- create(context) {
31
- const filename = context.getFilename();
32
-
33
- // Exclude pace-core source files - these rules are for consuming apps
34
- if (isPaceCoreSourceFile(filename)) {
35
- return {};
36
- }
37
-
38
- const restrictedImports = getRestrictedImports();
39
- const restrictedModules = restrictedImports.map(imp => imp.module);
40
-
41
- // Also catch @radix-ui/* patterns
42
- const radixPattern = /^@radix-ui\//;
43
-
44
- return {
45
- ImportDeclaration(node) {
46
- const importSource = node.source.value;
47
-
48
- // Check exact matches
49
- const restricted = restrictedImports.find(imp => imp.module === importSource);
50
- if (restricted) {
51
- context.report({
52
- node: node.source,
53
- messageId: 'restrictedImportWithReason',
54
- data: {
55
- message: `Direct import of '${importSource}' is not allowed.`,
56
- reason: restricted.reason
57
- },
58
- suggest: [{
59
- desc: `Use pace-core alternative: ${restricted.reason}`,
60
- fix(fixer) {
61
- // Suggest importing from pace-core instead
62
- const paceCoreAlternative = getPaceCoreAlternative(importSource);
63
- if (paceCoreAlternative) {
64
- return fixer.replaceText(
65
- node.source,
66
- `'@jmruthers/pace-core${paceCoreAlternative}'`
67
- );
68
- }
69
- return null;
70
- }
71
- }]
72
- });
73
- return;
74
- }
75
-
76
- // Check @radix-ui/* pattern
77
- if (radixPattern.test(importSource) && !restrictedModules.includes(importSource)) {
78
- context.report({
79
- node: node.source,
80
- messageId: 'restrictedImport',
81
- data: {
82
- message: `Direct import of '${importSource}' is not allowed.`,
83
- alternative: '@jmruthers/pace-core'
84
- },
85
- suggest: [{
86
- desc: 'Use pace-core component instead',
87
- fix(fixer) {
88
- return fixer.replaceText(
89
- node.source,
90
- "'@jmruthers/pace-core'"
91
- );
92
- }
93
- }]
94
- });
95
- }
96
- }
97
- };
98
- }
99
- }
100
- }
101
- };
102
-
@@ -1,472 +0,0 @@
1
- ---
2
- lastUpdated: 2025-11-18T17:00:00+11:00
3
- version: 0.5.181
4
- reviewedBy: documentation-standards-audit
5
- ---
6
-
7
- # Best Practices
8
-
9
- > **🎯 Build Better Apps** | [Security](#security) | [Performance](#performance) | [Testing](#testing) | [Deployment](#deployment)
10
-
11
- [← Back to Documentation](../README.md) | [↑ Table of Contents](#table-of-contents)
12
-
13
- Comprehensive best practices for building secure, performant, and maintainable applications with PACE Core.
14
-
15
- ## 📋 Table of Contents
16
-
17
- - [Security Best Practices](#-security-best-practices)
18
- - [Performance Optimization](#-performance-optimization)
19
- - [Testing Strategies](#-testing-strategies)
20
- - [Deployment Guidelines](#-deployment-guidelines)
21
- - [Code Quality](#-code-quality)
22
- - [Accessibility](#-accessibility)
23
- - [Maintenance](#-maintenance)
24
-
25
- ## Core Topics
26
-
27
- ### Security
28
- - [**Security Best Practices**](./security.md) - Security guidelines and secure coding patterns
29
-
30
- ### Accessibility
31
- - [**Accessibility Guide**](./accessibility.md) - WCAG compliance and inclusive design
32
-
33
- ### Performance
34
- - [**Performance Optimization**](./performance.md) - Comprehensive performance optimization strategies
35
-
36
- ### Testing
37
- - [**Testing Best Practices**](./testing.md) - Testing strategies and patterns
38
-
39
- ### Deployment
40
- - [**Deployment Guide**](./deployment.md) - Production deployment guidelines
41
-
42
- ---
43
-
44
- ## 🔒 Security Best Practices
45
-
46
- ### Authentication & Authorization
47
-
48
- **✅ Do:**
49
- - Always validate permissions server-side
50
- - Use the built-in RBAC system for access control
51
- - Implement proper session management
52
- - Enable MFA where possible
53
-
54
- ```tsx
55
- // ✅ Good - Server-side validation
56
- const { data, error } = await supabase
57
- .from('users')
58
- .select('*')
59
- .eq('organisation_id', user.organisation_id); // RLS handles security
60
-
61
- // ❌ Bad - Client-side only validation
62
- if (user.role === 'admin') {
63
- // This can be bypassed!
64
- }
65
- ```
66
-
67
- **✅ Do:**
68
- - Use permission guards for UI elements
69
- - Implement proper error boundaries
70
- - Sanitize all user inputs
71
-
72
- ```tsx
73
- // ✅ Good - Permission-based rendering
74
- <PermissionGuard
75
- operation="read"
76
- resource="sensitive_data"
77
- fallback={<div>Access denied</div>}
78
- >
79
- <SensitiveDataComponent />
80
- </PermissionGuard>
81
- ```
82
-
83
- ### Data Protection
84
-
85
- **✅ Do:**
86
- - Use Row Level Security (RLS) policies
87
- - Encrypt sensitive data at rest
88
- - Implement proper audit logging
89
- - Validate all inputs with Zod schemas
90
-
91
- ```tsx
92
- // ✅ Good - Input validation
93
- const userSchema = z.object({
94
- email: z.string().email(),
95
- password: z.string().min(8).regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/),
96
- });
97
-
98
- const result = userSchema.safeParse(formData);
99
- if (!result.success) {
100
- // Handle validation errors
101
- }
102
- ```
103
-
104
- For detailed security guidelines, see [Security Best Practices](./security.md).
105
-
106
- ## ⚡ Performance Optimization
107
-
108
- ### Bundle Optimization
109
-
110
- **✅ Do:**
111
- - Use tree shaking for smaller bundles
112
- - Implement code splitting
113
- - Lazy load heavy components
114
- - Optimize images and assets
115
-
116
- ```tsx
117
- // ✅ Good - Lazy loading
118
- const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
119
-
120
- function App() {
121
- return (
122
- <Suspense fallback={<LoadingSpinner />}>
123
- <HeavyComponent />
124
- </Suspense>
125
- );
126
- }
127
- ```
128
-
129
- ### Runtime Performance
130
-
131
- **✅ Do:**
132
- - Use React.memo for expensive components
133
- - Optimize callbacks with useCallback
134
- - Implement proper memoization
135
- - Use virtualization for large lists
136
-
137
- ```tsx
138
- // ✅ Good - Memoized component
139
- const ExpensiveTable = React.memo(({ data, columns }) => {
140
- return <DataTable data={data} columns={columns} />;
141
- });
142
-
143
- // ✅ Good - Memoized callback
144
- const handleDataChange = useCallback((newData) => {
145
- setData(newData);
146
- }, []);
147
- ```
148
-
149
- ### Data Management
150
-
151
- **✅ Do:**
152
- - Implement proper caching strategies
153
- - Use pagination for large datasets
154
- - Optimize database queries
155
- - Implement proper loading states
156
-
157
- ```tsx
158
- // ✅ Good - Paginated data
159
- <DataTable
160
- data={paginatedData}
161
- columns={columns}
162
- pagination={{
163
- currentPage,
164
- pageSize,
165
- totalItems: data.length,
166
- onPageChange: setCurrentPage,
167
- }}
168
- />
169
- ```
170
-
171
- For detailed performance guidelines, see [Performance Best Practices](./performance.md).
172
-
173
- ## 🧪 Testing Strategies
174
-
175
- ### Unit Testing
176
-
177
- **✅ Do:**
178
- - Test component behavior, not implementation
179
- - Use proper mocking for external dependencies
180
- - Test error states and edge cases
181
- - Maintain good test coverage
182
-
183
- ```tsx
184
- // ✅ Good - Component testing
185
- test('renders user data correctly', () => {
186
- const mockUser = { id: '1', name: 'John Doe', email: 'john@example.com' };
187
-
188
- render(<UserProfile user={mockUser} />);
189
-
190
- expect(screen.getByText('John Doe')).toBeInTheDocument();
191
- expect(screen.getByText('john@example.com')).toBeInTheDocument();
192
- });
193
- ```
194
-
195
- ### Integration Testing
196
-
197
- **✅ Do:**
198
- - Test component interactions
199
- - Test authentication flows
200
- - Test permission enforcement
201
- - Test form submissions
202
-
203
- ```tsx
204
- // ✅ Good - Integration testing
205
- test('user can submit form with valid data', async () => {
206
- const mockSubmit = jest.fn();
207
-
208
- render(<UserForm onSubmit={mockSubmit} />);
209
-
210
- await user.type(screen.getByLabelText('Name'), 'John Doe');
211
- await user.type(screen.getByLabelText('Email'), 'john@example.com');
212
- await user.click(screen.getByRole('button', { name: 'Submit' }));
213
-
214
- expect(mockSubmit).toHaveBeenCalledWith({
215
- name: 'John Doe',
216
- email: 'john@example.com'
217
- });
218
- });
219
- ```
220
-
221
- ### E2E Testing
222
-
223
- **✅ Do:**
224
- - Test critical user journeys
225
- - Test across different browsers
226
- - Test responsive behavior
227
- - Test accessibility features
228
-
229
- For detailed testing guidelines, see [Testing Best Practices](./testing.md).
230
-
231
- ## 🚀 Deployment Guidelines
232
-
233
- ### Environment Configuration
234
-
235
- **✅ Do:**
236
- - Use environment variables for configuration
237
- - Implement proper secrets management
238
- - Use different configs for different environments
239
- - Validate environment variables at startup
240
-
241
- ```tsx
242
- // ✅ Good - Environment validation
243
- const config = {
244
- supabaseUrl: process.env.VITE_SUPABASE_URL,
245
- supabaseKey: process.env.VITE_SUPABASE_PUBLISHABLE_KEY,
246
- appName: process.env.VITE_APP_NAME,
247
- };
248
-
249
- if (!config.supabaseUrl || !config.supabaseKey) {
250
- throw new Error('Missing required environment variables');
251
- }
252
- ```
253
-
254
- ### Build Optimization
255
-
256
- **✅ Do:**
257
- - Optimize bundle size
258
- - Enable compression
259
- - Use CDN for static assets
260
- - Implement proper caching headers
261
-
262
- ### Monitoring
263
-
264
- **✅ Do:**
265
- - Set up error tracking
266
- - Monitor performance metrics
267
- - Implement health checks
268
- - Set up alerts for critical issues
269
-
270
- For detailed deployment guidelines, see [Deployment Best Practices](./deployment.md).
271
-
272
- ## 📝 Code Quality
273
-
274
- ### TypeScript
275
-
276
- **✅ Do:**
277
- - Use strict TypeScript configuration
278
- - Define proper interfaces and types
279
- - Use type guards for runtime safety
280
- - Avoid `any` types
281
-
282
- ```tsx
283
- // ✅ Good - Proper typing
284
- interface User {
285
- id: string;
286
- name: string;
287
- email: string;
288
- role: 'admin' | 'user' | 'guest';
289
- }
290
-
291
- const UserCard: React.FC<{ user: User }> = ({ user }) => {
292
- return <div>{user.name}</div>;
293
- };
294
- ```
295
-
296
- ### Code Organisation
297
-
298
- **✅ Do:**
299
- - Use consistent file naming
300
- - Organize components logically
301
- - Separate concerns properly
302
- - Use proper imports and exports
303
-
304
- ```tsx
305
- // ✅ Good - Clean imports
306
- import { Button, Card, DataTable } from '@jmruthers/pace-core';
307
- import { useUnifiedAuth, useCan } from '@jmruthers/pace-core';
308
- import { z } from 'zod';
309
- ```
310
-
311
- ### Error Handling
312
-
313
- **✅ Do:**
314
- - Implement proper error boundaries
315
- - Use consistent error handling patterns
316
- - Provide meaningful error messages
317
- - Log errors appropriately
318
-
319
- ```tsx
320
- // ✅ Good - Error boundary
321
- <ErrorBoundary
322
- fallback={<ErrorFallback />}
323
- onError={(error, errorInfo) => {
324
- console.error('Error caught by boundary:', error, errorInfo);
325
- }}
326
- >
327
- <MyComponent />
328
- </ErrorBoundary>
329
- ```
330
-
331
- ## ♿ Accessibility
332
-
333
- ### WCAG Compliance
334
-
335
- **✅ Do:**
336
- - Use semantic HTML elements
337
- - Provide proper ARIA labels
338
- - Ensure keyboard navigation
339
- - Maintain color contrast ratios
340
-
341
- ```tsx
342
- // ✅ Good - Accessible component
343
- <button
344
- aria-label="Close dialog"
345
- onClick={onClose}
346
- className="p-2 rounded-md hover:bg-sec-100"
347
- >
348
- <XIcon className="h-4 w-4" />
349
- </button>
350
- ```
351
-
352
- ### Screen Reader Support
353
-
354
- **✅ Do:**
355
- - Use proper heading hierarchy
356
- - Provide alternative text for images
357
- - Use live regions for dynamic content
358
- - Test with screen readers
359
-
360
- ```tsx
361
- // ✅ Good - Live region for updates
362
- <div aria-live="polite" aria-atomic="true">
363
- {isLoading && 'Loading...'}
364
- {error && `Error: ${error.message}`}
365
- {data && `Loaded ${data.length} items`}
366
- </div>
367
- ```
368
-
369
- ## 🔧 Maintenance
370
-
371
- ### Documentation
372
-
373
- **✅ Do:**
374
- - Keep documentation up to date
375
- - Document breaking changes
376
- - Provide migration guides
377
- - Include code examples
378
-
379
- ### Dependencies
380
-
381
- **✅ Do:**
382
- - Keep dependencies updated
383
- - Use security scanning tools
384
- - Test updates in development
385
- - Pin critical dependency versions
386
-
387
- ### Monitoring
388
-
389
- **✅ Do:**
390
- - Monitor application performance
391
- - Track user behavior
392
- - Set up error alerts
393
- - Regular security audits
394
-
395
- ## 🎯 Quick Checklist
396
-
397
- ### Before Going to Production
398
-
399
- - [ ] Security audit completed
400
- - [ ] Performance testing done
401
- - [ ] Accessibility testing passed
402
- - [ ] Error handling implemented
403
- - [ ] Monitoring set up
404
- - [ ] Documentation updated
405
- - [ ] Dependencies updated
406
- - [ ] Environment variables configured
407
- - [ ] Backup strategy in place
408
- - [ ] Rollback plan ready
409
-
410
- ### Regular Maintenance
411
-
412
- - [ ] Weekly dependency updates
413
- - [ ] Monthly security reviews
414
- - [ ] Quarterly performance audits
415
- - [ ] Annual architecture reviews
416
-
417
- ## 📚 Additional Resources
418
-
419
- - [Security Best Practices](./security.md) - Detailed security guidelines
420
- - [Performance Best Practices](./performance.md) - Performance optimization
421
- - [Testing Best Practices](./testing.md) - Testing strategies
422
- - [Deployment Best Practices](./deployment.md) - Deployment guidelines
423
- - [Troubleshooting Guide](../troubleshooting/) - Common issues and solutions
424
-
425
- Remember: **Best practices are guidelines, not rules. Adapt them to your specific needs and constraints.**
426
-
427
- ## ♿ Accessibility
428
-
429
- All best practices should consider accessibility:
430
-
431
- - **WCAG 2.1 AA compliance** - Ensure all practices maintain accessibility standards
432
- - **Screen Reader Support** - Verify practices don't break screen reader functionality
433
- - **Keyboard Navigation** - Ensure practices don't affect keyboard accessibility
434
- - **Error Announcements** - Ensure error messages are accessible
435
- - **Focus Management** - Verify focus handling remains correct
436
-
437
- ### Accessibility Best Practices
438
-
439
- 1. **Test with screen readers** - Verify practices work with assistive technologies
440
- 2. **Check error announcements** - Ensure error messages are properly announced
441
- 3. **Maintain keyboard access** - Verify all interactive elements remain keyboard accessible
442
- 4. **Preserve semantic structure** - Don't break semantic HTML with optimizations
443
- 5. **Test focus management** - Ensure focus handling remains correct
444
-
445
- ## ⚠️ Edge Cases
446
-
447
- ### Best Practices Conflicts
448
-
449
- When best practices conflict:
450
- - Prioritize security over performance when necessary
451
- - Balance accessibility with design requirements
452
- - Consider trade-offs between maintainability and optimization
453
- - Document decisions when deviating from best practices
454
- - Test thoroughly when combining multiple practices
455
-
456
- ### Performance vs Accessibility
457
-
458
- When performance optimizations impact accessibility:
459
- - Ensure lazy loading doesn't break screen reader navigation
460
- - Verify code splitting maintains keyboard navigation
461
- - Check that memoization doesn't affect focus management
462
- - Test with assistive technologies after optimizations
463
- - Balance performance gains with accessibility requirements
464
-
465
- ### Security vs Usability
466
-
467
- When security practices impact usability:
468
- - Find balance between security and user experience
469
- - Provide clear error messages without exposing vulnerabilities
470
- - Implement security measures transparently
471
- - Test with real users to ensure usability
472
- - Document security decisions for future reference