@jmruthers/pace-core 0.6.5 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (473) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +5 -403
  3. package/audit-tool/00-dependencies.cjs +394 -0
  4. package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
  5. package/audit-tool/audits/02-project-structure.cjs +255 -0
  6. package/audit-tool/audits/03-architecture.cjs +196 -0
  7. package/audit-tool/audits/04-code-quality.cjs +149 -0
  8. package/audit-tool/audits/05-styling.cjs +224 -0
  9. package/audit-tool/audits/06-security-rbac.cjs +544 -0
  10. package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
  11. package/audit-tool/audits/08-testing-documentation.cjs +202 -0
  12. package/audit-tool/audits/09-operations.cjs +208 -0
  13. package/audit-tool/index.cjs +291 -0
  14. package/audit-tool/utils/code-utils.cjs +218 -0
  15. package/audit-tool/utils/file-utils.cjs +230 -0
  16. package/audit-tool/utils/report-utils.cjs +241 -0
  17. package/core-usage-manifest.json +93 -0
  18. package/cursor-rules/00-standards-overview.mdc +156 -0
  19. package/cursor-rules/01-pace-core-compliance.mdc +586 -0
  20. package/cursor-rules/02-project-structure.mdc +42 -4
  21. package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +126 -10
  22. package/cursor-rules/04-code-quality.mdc +419 -0
  23. package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +104 -34
  24. package/cursor-rules/06-security-rbac.mdc +518 -0
  25. package/cursor-rules/07-api-tech-stack.mdc +377 -0
  26. package/cursor-rules/08-testing-documentation.mdc +324 -0
  27. package/cursor-rules/09-operations.mdc +365 -0
  28. package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
  29. package/dist/DataTable-7PMH7XN7.js +15 -0
  30. package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
  31. package/dist/{PublicPageProvider-QTFVrL-Z.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +33 -72
  32. package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
  33. package/dist/api-Y4MQWOFW.js +4 -0
  34. package/dist/audit-MYQXYZFU.js +3 -0
  35. package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
  36. package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
  37. package/dist/{chunk-UPPMRMYG.js → chunk-5X4QLXRG.js} +73 -151
  38. package/dist/chunk-6F3IILHI.js +62 -0
  39. package/dist/{chunk-E66EQZE6.js → chunk-6GLLNA6U.js} +3 -9
  40. package/dist/{chunk-ZSAAAMVR.js → chunk-6QYDGKQY.js} +1 -4
  41. package/dist/{chunk-FMUCXFII.js → chunk-7ILTDCL2.js} +9 -5
  42. package/dist/{chunk-M43Y4SSO.js → chunk-A3W6LW53.js} +15 -13
  43. package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
  44. package/dist/{chunk-HU2C6SSC.js → chunk-BM4CQ5P3.js} +606 -559
  45. package/dist/chunk-C7NSAPTL.js +1 -0
  46. package/dist/{chunk-J36DSWQK.js → chunk-FEJLJNWA.js} +7 -41
  47. package/dist/{chunk-IHB5DR3H.js → chunk-FTCRZOG2.js} +188 -387
  48. package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
  49. package/dist/chunk-GHYHJTYV.js +994 -0
  50. package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
  51. package/dist/{chunk-FFQEQTNW.js → chunk-IUBRCBSY.js} +134 -45
  52. package/dist/{chunk-6COVEUS7.js → chunk-JGWDVX64.js} +983 -1034
  53. package/dist/{chunk-RGAWHO7N.js → chunk-L4XMVJKY.js} +77 -222
  54. package/dist/chunk-MBADTM7L.js +64 -0
  55. package/dist/{chunk-M7MPQISP.js → chunk-OJ4SKRSV.js} +3 -16
  56. package/dist/{chunk-IVOFDYWT.js → chunk-Q7Q7V5NV.js} +2109 -1604
  57. package/dist/{chunk-JGRYX5UX.js → chunk-S7DKJPLT.js} +29 -58
  58. package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
  59. package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
  60. package/dist/{chunk-NTM7ZSB6.js → chunk-VBCS3DUA.js} +261 -168
  61. package/dist/{chunk-EFN2EIMK.js → chunk-ZFYPMX46.js} +271 -87
  62. package/dist/{chunk-L4OXEN46.js → chunk-ZKAWKYT4.js} +10 -24
  63. package/dist/components.d.ts +7 -5
  64. package/dist/components.js +46 -257
  65. package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
  66. package/dist/eslint-rules/index.cjs +35 -0
  67. package/{src/eslint-rules/pace-core-compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +234 -235
  68. package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
  69. package/dist/eslint-rules/rules/05-styling.cjs +61 -0
  70. package/dist/eslint-rules/rules/06-security-rbac.cjs +806 -0
  71. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
  72. package/dist/eslint-rules/rules/08-testing.cjs +94 -0
  73. package/dist/eslint-rules/utils/helpers.cjs +42 -0
  74. package/dist/eslint-rules/utils/manifest-loader.cjs +75 -0
  75. package/dist/hooks.d.ts +6 -6
  76. package/dist/hooks.js +62 -172
  77. package/dist/icons/index.d.ts +1 -0
  78. package/dist/icons/index.js +1 -0
  79. package/dist/index.d.ts +12 -11
  80. package/dist/index.js +67 -660
  81. package/dist/providers.d.ts +2 -2
  82. package/dist/providers.js +8 -35
  83. package/dist/rbac/eslint-rules.d.ts +46 -44
  84. package/dist/rbac/eslint-rules.js +7 -4
  85. package/dist/rbac/index.d.ts +109 -586
  86. package/dist/rbac/index.js +14 -207
  87. package/dist/styles/index.js +2 -12
  88. package/dist/theming/runtime.d.ts +14 -1
  89. package/dist/theming/runtime.js +3 -19
  90. package/dist/{timezone-CHhWg6b4.d.ts → timezone-BZe_eUxx.d.ts} +175 -1
  91. package/dist/{types-CkbwOr4Y.d.ts → types-DXstZpNI.d.ts} +4 -17
  92. package/dist/types-t9H8qKRw.d.ts +55 -0
  93. package/dist/types.d.ts +1 -1
  94. package/dist/types.js +7 -94
  95. package/dist/{usePublicRouteParams-ClnV4tnv.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +20 -20
  96. package/dist/utils.d.ts +24 -117
  97. package/dist/utils.js +54 -392
  98. package/docs/README.md +17 -7
  99. package/docs/api/README.md +4 -402
  100. package/docs/api/modules.md +301 -871
  101. package/docs/api-reference/components.md +21 -21
  102. package/docs/api-reference/deprecated.md +31 -6
  103. package/docs/api-reference/hooks.md +80 -80
  104. package/docs/api-reference/rpc-functions.md +78 -3
  105. package/docs/api-reference/types.md +1 -1
  106. package/docs/api-reference/utilities.md +1 -1
  107. package/docs/architecture/README.md +1 -1
  108. package/docs/core-concepts/events.md +3 -3
  109. package/docs/core-concepts/organisations.md +6 -6
  110. package/docs/core-concepts/permissions.md +6 -6
  111. package/docs/documentation-index.md +12 -18
  112. package/docs/getting-started/cursor-rules.md +3 -23
  113. package/docs/getting-started/dependencies.md +650 -0
  114. package/docs/getting-started/documentation-index.md +1 -1
  115. package/docs/getting-started/examples/README.md +4 -4
  116. package/docs/getting-started/examples/full-featured-app.md +1 -1
  117. package/docs/getting-started/faq.md +2 -2
  118. package/docs/getting-started/installation-guide.md +20 -7
  119. package/docs/getting-started/quick-reference.md +4 -4
  120. package/docs/getting-started/quick-start.md +23 -12
  121. package/docs/implementation-guides/authentication.md +15 -15
  122. package/docs/implementation-guides/component-styling.md +1 -1
  123. package/docs/implementation-guides/data-tables.md +126 -33
  124. package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
  125. package/docs/implementation-guides/dynamic-colors.md +3 -3
  126. package/docs/implementation-guides/file-upload-storage.md +2 -2
  127. package/docs/implementation-guides/hierarchical-datatable.md +40 -60
  128. package/docs/implementation-guides/inactivity-tracking.md +3 -3
  129. package/docs/implementation-guides/large-datasets.md +3 -2
  130. package/docs/implementation-guides/organisation-security.md +2 -2
  131. package/docs/implementation-guides/performance.md +2 -2
  132. package/docs/implementation-guides/permission-enforcement.md +5 -1
  133. package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
  134. package/docs/migration/V0.4.0_rbac-migration.md +6 -6
  135. package/docs/rbac/MIGRATION_GUIDE.md +819 -0
  136. package/docs/rbac/RBAC_CONTRACT.md +724 -0
  137. package/docs/rbac/README.md +17 -8
  138. package/docs/rbac/advanced-patterns.md +6 -6
  139. package/docs/rbac/api-reference.md +20 -20
  140. package/docs/rbac/edge-functions-guide.md +376 -0
  141. package/docs/rbac/event-based-apps.md +3 -3
  142. package/docs/rbac/examples.md +41 -41
  143. package/docs/rbac/getting-started.md +37 -37
  144. package/docs/rbac/performance.md +1 -1
  145. package/docs/rbac/quick-start.md +52 -52
  146. package/docs/rbac/secure-client-protection.md +1 -35
  147. package/docs/rbac/troubleshooting.md +1 -1
  148. package/docs/security/README.md +5 -5
  149. package/docs/standards/0-standards-overview.md +220 -0
  150. package/docs/standards/1-pace-core-compliance-standards.md +986 -0
  151. package/docs/standards/2-project-structure-standards.md +949 -0
  152. package/docs/standards/3-architecture-standards.md +606 -0
  153. package/docs/standards/4-code-quality-standards.md +728 -0
  154. package/docs/standards/5-styling-standards.md +348 -0
  155. package/docs/standards/{07-rbac-and-rls-standard.md → 6-security-rbac-standards.md} +269 -66
  156. package/docs/standards/7-api-tech-stack-standards.md +662 -0
  157. package/docs/standards/8-testing-documentation-standards.md +401 -0
  158. package/docs/standards/9-operations-standards.md +1102 -0
  159. package/docs/standards/README.md +185 -57
  160. package/docs/troubleshooting/README.md +4 -4
  161. package/docs/troubleshooting/common-issues.md +2 -2
  162. package/docs/troubleshooting/debugging.md +9 -9
  163. package/docs/troubleshooting/migration.md +4 -4
  164. package/docs/troubleshooting/organisation-context-setup.md +42 -19
  165. package/eslint-config-pace-core.cjs +33 -6
  166. package/package.json +35 -23
  167. package/scripts/install-cursor-rules.cjs +25 -6
  168. package/scripts/install-eslint-config.cjs +284 -0
  169. package/src/__tests__/fixtures/supabase.ts +1 -1
  170. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +3 -3
  171. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +1 -1
  172. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +1 -1
  173. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
  174. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +13 -13
  175. package/src/__tests__/helpers/component-test-utils.tsx +1 -1
  176. package/src/__tests__/helpers/supabaseMock.ts +2 -2
  177. package/src/__tests__/integration/UserProfile.test.tsx +14 -14
  178. package/src/__tests__/public-recipe-view.test.ts +38 -9
  179. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
  180. package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
  181. package/src/__tests__/templates/component.test.template.tsx +18 -15
  182. package/src/components/Button/Button.tsx +5 -1
  183. package/src/components/Calendar/Calendar.tsx +201 -47
  184. package/src/components/ContextSelector/ContextSelector.tsx +106 -119
  185. package/src/components/DataTable/AUDIT_REPORT.md +293 -0
  186. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
  187. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
  188. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
  189. package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
  190. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
  191. package/src/components/DataTable/components/DataTableCore.tsx +186 -13
  192. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
  193. package/src/components/DataTable/components/DataTableLayout.tsx +35 -21
  194. package/src/components/DataTable/components/EditFields.tsx +23 -3
  195. package/src/components/DataTable/components/EditableRow.tsx +12 -9
  196. package/src/components/DataTable/components/EmptyState.tsx +10 -9
  197. package/src/components/DataTable/components/FilterRow.tsx +2 -4
  198. package/src/components/DataTable/components/ImportModal.tsx +124 -126
  199. package/src/components/DataTable/components/LoadingState.tsx +5 -6
  200. package/src/components/DataTable/components/RowComponent.tsx +12 -0
  201. package/src/components/DataTable/components/SortIndicator.tsx +50 -0
  202. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
  203. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
  204. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
  205. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
  206. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
  207. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
  208. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
  209. package/src/components/DataTable/components/index.ts +2 -1
  210. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +51 -47
  211. package/src/components/DataTable/hooks/useDataTablePermissions.ts +24 -21
  212. package/src/components/DataTable/hooks/useDataTableState.ts +125 -9
  213. package/src/components/DataTable/hooks/useTableColumns.ts +40 -2
  214. package/src/components/DataTable/hooks/useTableHandlers.ts +11 -0
  215. package/src/components/DataTable/types.ts +5 -18
  216. package/src/components/DataTable/utils/a11yUtils.ts +17 -0
  217. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
  218. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
  219. package/src/components/DateTimeField/DateTimeField.tsx +10 -9
  220. package/src/components/Dialog/Dialog.test.tsx +128 -104
  221. package/src/components/Dialog/Dialog.tsx +742 -24
  222. package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
  223. package/src/components/FileDisplay/FileDisplay.test.tsx +4 -2
  224. package/src/components/FileDisplay/FileDisplay.tsx +23 -17
  225. package/src/components/FileUpload/FileUpload.test.tsx +52 -14
  226. package/src/components/FileUpload/FileUpload.tsx +112 -130
  227. package/src/components/Form/Form.test.tsx +6 -8
  228. package/src/components/Form/Form.tsx +365 -4
  229. package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
  230. package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
  231. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
  232. package/src/components/PaceAppLayout/PaceAppLayout.tsx +11 -15
  233. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
  234. package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
  235. package/src/components/Progress/Progress.tsx +2 -4
  236. package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
  237. package/src/components/Select/Select.tsx +109 -98
  238. package/src/components/Select/types.ts +4 -1
  239. package/src/components/UserMenu/UserMenu.tsx +9 -6
  240. package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
  241. package/src/hooks/__tests__/hooks.integration.test.tsx +55 -57
  242. package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
  243. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
  244. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +149 -67
  245. package/src/hooks/__tests__/usePublicEvent.test.ts +149 -79
  246. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +158 -109
  247. package/src/hooks/__tests__/useSessionDraft.test.ts +163 -0
  248. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +10 -5
  249. package/src/hooks/public/usePublicEvent.ts +67 -195
  250. package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
  251. package/src/hooks/public/usePublicEventLogo.ts +24 -14
  252. package/src/hooks/public/usePublicFileDisplay.ts +2 -2
  253. package/src/hooks/public/usePublicRouteParams.ts +5 -5
  254. package/src/hooks/useAppConfig.ts +28 -26
  255. package/src/hooks/useEventTheme.test.ts +217 -239
  256. package/src/hooks/useEventTheme.ts +16 -28
  257. package/src/hooks/useFileDisplay.ts +2 -2
  258. package/src/hooks/useOrganisationPermissions.ts +5 -7
  259. package/src/hooks/useQueryCache.ts +0 -1
  260. package/src/hooks/useSessionDraft.ts +380 -0
  261. package/src/hooks/useSessionRestoration.ts +3 -1
  262. package/src/icons/index.ts +27 -0
  263. package/src/index.ts +5 -0
  264. package/src/providers/OrganisationProvider.tsx +23 -14
  265. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
  266. package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
  267. package/src/providers/__tests__/EventProvider.test.tsx +61 -61
  268. package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
  269. package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
  270. package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
  271. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
  272. package/src/providers/services/EventServiceProvider.tsx +1 -24
  273. package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
  274. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
  275. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +13 -10
  276. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +7 -457
  277. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +33 -7
  278. package/src/rbac/adapters.tsx +7 -295
  279. package/src/rbac/api.test.ts +44 -56
  280. package/src/rbac/api.ts +10 -17
  281. package/src/rbac/cache-invalidation.ts +0 -1
  282. package/src/rbac/compliance/index.ts +10 -0
  283. package/src/rbac/compliance/pattern-detector.ts +553 -0
  284. package/src/rbac/compliance/runtime-compliance.ts +22 -0
  285. package/src/rbac/components/AccessDenied.tsx +150 -0
  286. package/src/rbac/components/NavigationGuard.tsx +12 -20
  287. package/src/rbac/components/PagePermissionGuard.tsx +4 -24
  288. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +21 -8
  289. package/src/rbac/components/index.ts +3 -41
  290. package/src/rbac/eslint-rules.js +1 -1
  291. package/src/rbac/hooks/index.ts +0 -3
  292. package/src/rbac/hooks/permissions/index.ts +0 -3
  293. package/src/rbac/hooks/permissions/useAccessLevel.ts +4 -8
  294. package/src/rbac/hooks/usePermissions.ts +0 -3
  295. package/src/rbac/hooks/useResolvedScope.test.ts +57 -47
  296. package/src/rbac/hooks/useResolvedScope.ts +58 -140
  297. package/src/rbac/hooks/useResourcePermissions.test.ts +124 -38
  298. package/src/rbac/hooks/useResourcePermissions.ts +139 -48
  299. package/src/rbac/hooks/useRoleManagement.test.ts +65 -22
  300. package/src/rbac/hooks/useRoleManagement.ts +147 -19
  301. package/src/rbac/hooks/useSecureSupabase.ts +4 -8
  302. package/src/rbac/index.ts +7 -9
  303. package/src/rbac/utils/contextValidator.ts +9 -7
  304. package/src/services/AuthService.ts +130 -18
  305. package/src/services/EventService.ts +4 -97
  306. package/src/services/InactivityService.ts +16 -0
  307. package/src/services/OrganisationService.ts +7 -44
  308. package/src/services/__tests__/OrganisationService.test.ts +26 -8
  309. package/src/services/base/BaseService.ts +0 -3
  310. package/src/styles/core.css +7 -0
  311. package/src/theming/__tests__/parseEventColours.test.ts +9 -3
  312. package/src/theming/parseEventColours.ts +22 -10
  313. package/src/types/database.generated.ts +4733 -3809
  314. package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
  315. package/src/utils/__tests__/organisationContext.unit.test.ts +9 -10
  316. package/src/utils/context/organisationContext.test.ts +13 -28
  317. package/src/utils/context/organisationContext.ts +21 -52
  318. package/src/utils/dynamic/dynamicUtils.ts +1 -1
  319. package/src/utils/file-reference/index.ts +39 -15
  320. package/src/utils/formatting/formatDateTime.test.ts +3 -2
  321. package/src/utils/google-places/loadGoogleMapsScript.ts +29 -4
  322. package/src/utils/index.ts +4 -1
  323. package/src/utils/persistence/__tests__/keyDerivation.test.ts +135 -0
  324. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +123 -0
  325. package/src/utils/persistence/keyDerivation.ts +304 -0
  326. package/src/utils/persistence/sensitiveFieldDetection.ts +212 -0
  327. package/src/utils/security/secureStorage.ts +5 -5
  328. package/src/utils/storage/README.md +1 -1
  329. package/src/utils/storage/helpers.ts +3 -3
  330. package/src/utils/supabase/createBaseClient.ts +147 -0
  331. package/src/utils/timezone/timezone.test.ts +1 -2
  332. package/src/utils/timezone/timezone.ts +1 -1
  333. package/src/utils/validation/csrf.ts +4 -4
  334. package/cursor-rules/00-pace-core-compliance.mdc +0 -331
  335. package/cursor-rules/01-standards-compliance.mdc +0 -244
  336. package/cursor-rules/04-testing-standards.mdc +0 -268
  337. package/cursor-rules/05-bug-reports-and-features.mdc +0 -246
  338. package/cursor-rules/06-code-quality.mdc +0 -309
  339. package/cursor-rules/07-tech-stack-compliance.mdc +0 -214
  340. package/cursor-rules/CHANGELOG.md +0 -119
  341. package/cursor-rules/README.md +0 -192
  342. package/dist/DataTable-AOVNCPTX.js +0 -175
  343. package/dist/DataTable-AOVNCPTX.js.map +0 -1
  344. package/dist/UnifiedAuthProvider-4SBX4LU5.js +0 -18
  345. package/dist/UnifiedAuthProvider-4SBX4LU5.js.map +0 -1
  346. package/dist/api-O6HTBX5Y.js +0 -52
  347. package/dist/api-O6HTBX5Y.js.map +0 -1
  348. package/dist/audit-V53FV5AG.js +0 -17
  349. package/dist/audit-V53FV5AG.js.map +0 -1
  350. package/dist/chunk-5DRSZLL2.js.map +0 -1
  351. package/dist/chunk-63FOKYGO.js.map +0 -1
  352. package/dist/chunk-6COVEUS7.js.map +0 -1
  353. package/dist/chunk-AFVQODI2.js +0 -263
  354. package/dist/chunk-AFVQODI2.js.map +0 -1
  355. package/dist/chunk-DGUM43GV.js.map +0 -1
  356. package/dist/chunk-E66EQZE6.js.map +0 -1
  357. package/dist/chunk-EFN2EIMK.js.map +0 -1
  358. package/dist/chunk-FFQEQTNW.js.map +0 -1
  359. package/dist/chunk-FMUCXFII.js.map +0 -1
  360. package/dist/chunk-G37KK66H.js.map +0 -1
  361. package/dist/chunk-G7QEZTYQ.js +0 -2053
  362. package/dist/chunk-G7QEZTYQ.js.map +0 -1
  363. package/dist/chunk-HU2C6SSC.js.map +0 -1
  364. package/dist/chunk-IHB5DR3H.js.map +0 -1
  365. package/dist/chunk-IVOFDYWT.js.map +0 -1
  366. package/dist/chunk-J36DSWQK.js.map +0 -1
  367. package/dist/chunk-JGRYX5UX.js.map +0 -1
  368. package/dist/chunk-KQCRWDSA.js +0 -1
  369. package/dist/chunk-KQCRWDSA.js.map +0 -1
  370. package/dist/chunk-L4OXEN46.js.map +0 -1
  371. package/dist/chunk-LMC26NLJ.js +0 -84
  372. package/dist/chunk-LMC26NLJ.js.map +0 -1
  373. package/dist/chunk-M43Y4SSO.js.map +0 -1
  374. package/dist/chunk-M7MPQISP.js.map +0 -1
  375. package/dist/chunk-NTM7ZSB6.js.map +0 -1
  376. package/dist/chunk-PWLANIRT.js.map +0 -1
  377. package/dist/chunk-QXHPKYJV.js.map +0 -1
  378. package/dist/chunk-RGAWHO7N.js.map +0 -1
  379. package/dist/chunk-UPPMRMYG.js.map +0 -1
  380. package/dist/chunk-VBXEHIUJ.js.map +0 -1
  381. package/dist/chunk-ZSAAAMVR.js.map +0 -1
  382. package/dist/components.js.map +0 -1
  383. package/dist/contextValidator-5OGXSPKS.js +0 -9
  384. package/dist/contextValidator-5OGXSPKS.js.map +0 -1
  385. package/dist/eslint-rules/pace-core-compliance.cjs +0 -510
  386. package/dist/hooks.js.map +0 -1
  387. package/dist/index.js.map +0 -1
  388. package/dist/providers.js.map +0 -1
  389. package/dist/rbac/eslint-rules.js.map +0 -1
  390. package/dist/rbac/index.js.map +0 -1
  391. package/dist/styles/index.js.map +0 -1
  392. package/dist/theming/runtime.js.map +0 -1
  393. package/dist/types.js.map +0 -1
  394. package/dist/utils.js.map +0 -1
  395. package/docs/best-practices/README.md +0 -472
  396. package/docs/best-practices/accessibility.md +0 -601
  397. package/docs/best-practices/common-patterns.md +0 -516
  398. package/docs/best-practices/deployment.md +0 -1103
  399. package/docs/best-practices/performance.md +0 -1328
  400. package/docs/best-practices/security.md +0 -940
  401. package/docs/best-practices/testing.md +0 -1034
  402. package/docs/rbac/compliance/compliance-guide.md +0 -544
  403. package/docs/standards/01-architecture-standard.md +0 -44
  404. package/docs/standards/02-api-and-rpc-standard.md +0 -39
  405. package/docs/standards/03-component-standard.md +0 -32
  406. package/docs/standards/04-code-style-standard.md +0 -32
  407. package/docs/standards/05-security-standard.md +0 -44
  408. package/docs/standards/06-testing-and-docs-standard.md +0 -29
  409. package/docs/standards/pace-core-compliance.md +0 -432
  410. package/scripts/audit/core/checks/accessibility.cjs +0 -197
  411. package/scripts/audit/core/checks/api-usage.cjs +0 -191
  412. package/scripts/audit/core/checks/bundle.cjs +0 -142
  413. package/scripts/audit/core/checks/compliance.cjs +0 -2706
  414. package/scripts/audit/core/checks/config.cjs +0 -54
  415. package/scripts/audit/core/checks/coverage.cjs +0 -84
  416. package/scripts/audit/core/checks/dependencies.cjs +0 -994
  417. package/scripts/audit/core/checks/documentation.cjs +0 -268
  418. package/scripts/audit/core/checks/environment.cjs +0 -116
  419. package/scripts/audit/core/checks/error-handling.cjs +0 -340
  420. package/scripts/audit/core/checks/forms.cjs +0 -172
  421. package/scripts/audit/core/checks/heuristics.cjs +0 -68
  422. package/scripts/audit/core/checks/hooks.cjs +0 -334
  423. package/scripts/audit/core/checks/imports.cjs +0 -244
  424. package/scripts/audit/core/checks/performance.cjs +0 -325
  425. package/scripts/audit/core/checks/routes.cjs +0 -117
  426. package/scripts/audit/core/checks/state.cjs +0 -130
  427. package/scripts/audit/core/checks/structure.cjs +0 -65
  428. package/scripts/audit/core/checks/style.cjs +0 -584
  429. package/scripts/audit/core/checks/testing.cjs +0 -122
  430. package/scripts/audit/core/checks/typescript.cjs +0 -61
  431. package/scripts/audit/core/scanner.cjs +0 -199
  432. package/scripts/audit/core/utils.cjs +0 -137
  433. package/scripts/audit/index.cjs +0 -223
  434. package/scripts/audit/reporters/console.cjs +0 -151
  435. package/scripts/audit/reporters/json.cjs +0 -54
  436. package/scripts/audit/reporters/markdown.cjs +0 -124
  437. package/scripts/audit-consuming-app.cjs +0 -86
  438. package/src/components/DataTable/components/DataTableBody.tsx +0 -454
  439. package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
  440. package/src/components/DataTable/components/ExpandButton.tsx +0 -113
  441. package/src/components/DataTable/components/GroupHeader.tsx +0 -54
  442. package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
  443. package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
  444. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
  445. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
  446. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
  447. package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
  448. package/src/components/DataTable/core/DataTableContext.tsx +0 -216
  449. package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
  450. package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
  451. package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
  452. package/src/components/DataTable/utils/debugTools.ts +0 -514
  453. package/src/eslint-rules/pace-core-compliance.js +0 -638
  454. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +0 -555
  455. package/src/rbac/components/EnhancedNavigationMenu.tsx +0 -293
  456. package/src/rbac/components/NavigationProvider.test.tsx +0 -481
  457. package/src/rbac/components/NavigationProvider.tsx +0 -345
  458. package/src/rbac/components/PagePermissionProvider.test.tsx +0 -476
  459. package/src/rbac/components/PagePermissionProvider.tsx +0 -279
  460. package/src/rbac/components/PermissionEnforcer.tsx +0 -312
  461. package/src/rbac/components/RoleBasedRouter.tsx +0 -440
  462. package/src/rbac/components/SecureDataProvider.test.tsx +0 -543
  463. package/src/rbac/components/SecureDataProvider.tsx +0 -339
  464. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -620
  465. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -726
  466. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -661
  467. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +0 -881
  468. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +0 -783
  469. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +0 -645
  470. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -659
  471. package/src/rbac/hooks/permissions/useCachedPermissions.ts +0 -79
  472. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +0 -90
  473. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +0 -90
@@ -1,44 +0,0 @@
1
- # Security Standard
2
-
3
- ## Threat Model
4
- - Multi-tenant SaaS
5
- - Untrusted browser environment
6
- - Supabase backend
7
- - Risks: RLS gaps, injection, unsafe logging, leaking PII
8
-
9
- ## Security Rules
10
- - Never bypass RLS
11
- - Validate all inputs
12
- - Sanitize logs
13
- - Never store secrets in code
14
- - Use safe error messaging
15
-
16
- ## RLS Policy Performance Rules
17
- - **NEVER use subqueries in RLS policies** - They execute for every row check and cause severe performance degradation
18
- - **ALWAYS use helper functions** - Create STABLE SECURITY DEFINER functions for lookups (e.g., `get_app_id()`, `get_form_event_id()`)
19
- - **Helper functions must be**:
20
- - `STABLE` - Results are consistent within a transaction
21
- - `SECURITY DEFINER` - Bypass RLS to avoid recursion
22
- - `SET search_path TO 'public'` - Prevent search path injection
23
- - **Test RLS policies** - Verify they don't cause query timeouts or N+1 query patterns
24
- - **Monitor performance** - Watch for slow queries after RLS policy changes
25
-
26
- **See [RBAC and RLS Standard](./07-rbac-and-rls-standard.md) for detailed RLS policy patterns and helper function documentation.**
27
-
28
- ## Logging Rules
29
- Allowed:
30
- - IDs
31
- - Non-PII metadata
32
-
33
- Forbidden:
34
- - Passwords
35
- - Tokens
36
- - Sensitive data
37
-
38
- ## Cursor Checklist
39
- - Confirm RLS is enforced
40
- - Ensure no sensitive logs
41
- - Replace raw errors with ApiError
42
- - Validate input shapes
43
- - **RLS policies use helper functions, not subqueries**
44
- - **Helper functions are STABLE and SECURITY DEFINER**
@@ -1,29 +0,0 @@
1
- # Testing & Documentation Standard
2
-
3
- ## Testing Strategy
4
- - Unit tests for utils & hooks
5
- - Integration tests for components
6
- - Few meaningful E2E tests (in consuming apps)
7
- - Coverage: ≥90% utils, ≥70% components
8
-
9
- ## Test Structure
10
- - Colocated tests (*.test.ts/tsx)
11
- - Use RTL + userEvent
12
- - Avoid unnecessary mocks
13
-
14
- ## Documentation Requirements
15
- - Component READMEs
16
- - API docs
17
- - Standards directory
18
-
19
- ## Required Sections
20
- - Overview
21
- - API/Props
22
- - Examples
23
- - A11y notes
24
- - Edge cases
25
-
26
- ## Cursor Checklist
27
- - Update docs after API changes
28
- - Ensure tests cover critical paths
29
- - Use RTL patterns only
@@ -1,432 +0,0 @@
1
- # pace-core Compliance Enforcement
2
-
3
- This guide explains how to enforce pace-core usage patterns in consuming apps to ensure consistent design, reduce duplication, and maintain high code quality.
4
-
5
- ## Overview
6
-
7
- pace-core provides a comprehensive enforcement system that includes:
8
-
9
- 1. **ESLint Rules** - Real-time linting during development
10
- 2. **Static Analysis Script** - Comprehensive codebase scanning
11
- 3. **ESLint Config Preset** - Easy setup for consuming apps
12
-
13
- ## Quick Start
14
-
15
- ### Option 1: ESLint Config Preset (Recommended)
16
-
17
- The easiest way to enable compliance checking is to use the shareable ESLint config. The config is CommonJS but works with both ES module and CommonJS ESLint configs:
18
-
19
- **For ES Module ESLint Config (eslint.config.js):**
20
- ```javascript
21
- // eslint.config.js (ES modules)
22
- import paceCoreConfig from '@jmruthers/pace-core/eslint-config';
23
-
24
- export default [
25
- ...paceCoreConfig,
26
- // your other config
27
- ];
28
- ```
29
-
30
- **For CommonJS ESLint Config (.eslintrc.js or eslint.config.cjs):**
31
- ```javascript
32
- // eslint.config.cjs (CommonJS)
33
- const paceCoreConfig = require('@jmruthers/pace-core/eslint-config');
34
-
35
- module.exports = [
36
- ...paceCoreConfig,
37
- // your other config
38
- ];
39
- ```
40
-
41
- ### Option 2: Manual ESLint Rules Setup
42
-
43
- If you prefer more control, you can import the rules directly. Note: The rules are CommonJS, so use `createRequire` in ES modules:
44
-
45
- **For ES Module ESLint Config:**
46
- ```javascript
47
- // eslint.config.js
48
- import { createRequire } from 'module';
49
- const require = createRequire(import.meta.url);
50
- const paceCoreRules = require('@jmruthers/pace-core/eslint-rules').rules;
51
-
52
- export default [
53
- {
54
- plugins: {
55
- 'pace-core-compliance': {
56
- rules: paceCoreRules
57
- }
58
- },
59
- rules: {
60
- 'pace-core-compliance/no-restricted-imports': 'error',
61
- 'pace-core-compliance/prefer-pace-core-components': 'warn',
62
- 'pace-core-compliance/prefer-pace-core-hooks': 'warn',
63
- 'pace-core-compliance/prefer-pace-core-utils': 'warn',
64
- 'pace-core-compliance/no-local-component-duplication': 'error'
65
- }
66
- }
67
- ];
68
- ```
69
-
70
- **For CommonJS ESLint Config:**
71
- ```javascript
72
- // eslint.config.cjs
73
- const paceCoreRules = require('@jmruthers/pace-core/eslint-rules').rules;
74
-
75
- module.exports = [
76
- {
77
- plugins: {
78
- 'pace-core-compliance': {
79
- rules: paceCoreRules
80
- }
81
- },
82
- rules: {
83
- 'pace-core-compliance/no-restricted-imports': 'error',
84
- 'pace-core-compliance/prefer-pace-core-components': 'warn',
85
- 'pace-core-compliance/prefer-pace-core-hooks': 'warn',
86
- 'pace-core-compliance/prefer-pace-core-utils': 'warn',
87
- 'pace-core-compliance/no-local-component-duplication': 'error'
88
- }
89
- }
90
- ];
91
- ```
92
-
93
- ## ESLint Rules
94
-
95
- ### no-restricted-imports
96
-
97
- **Severity**: Error
98
-
99
- Blocks direct imports of libraries that pace-core wraps and standardizes.
100
-
101
- **Restricted Libraries**:
102
- - `@radix-ui/*` - All Radix UI packages (use pace-core components instead)
103
- - `lucide-react` - Icons (use pace-core components that include icons)
104
- - `react-day-picker` - Use `Calendar` from pace-core
105
- - `@tanstack/react-table` - Use `DataTable` from pace-core
106
- - `react-hook-form` - Use `Form` and `useZodForm` from pace-core
107
- - `zod` - Use validation utilities from pace-core
108
-
109
- **Example Violation**:
110
- ```typescript
111
- // ❌ Bad
112
- import { Dialog } from '@radix-ui/react-dialog';
113
- import { Button } from 'lucide-react';
114
-
115
- // ✅ Good
116
- import { Dialog } from '@jmruthers/pace-core';
117
- import { Button } from '@jmruthers/pace-core';
118
- ```
119
-
120
- ### prefer-pace-core-components
121
-
122
- **Severity**: Warning
123
-
124
- Suggests using pace-core components instead of native HTML elements.
125
-
126
- **Detected Patterns**:
127
- - `<button>` → Use `Button` from pace-core
128
- - `<input>` → Use `Input` from pace-core
129
- - `<textarea>` → Use `Textarea` from pace-core
130
- - `<label>` → Use `Label` from pace-core
131
-
132
- **Example**:
133
- ```tsx
134
- // ⚠️ Warning
135
- <button onClick={handleClick}>Click me</button>
136
-
137
- // ✅ Recommended
138
- import { Button } from '@jmruthers/pace-core';
139
- <Button onClick={handleClick}>Click me</Button>
140
- ```
141
-
142
- ### prefer-pace-core-hooks
143
-
144
- **Severity**: Warning
145
-
146
- Detects custom hooks that duplicate pace-core functionality.
147
-
148
- **Common Patterns Detected**:
149
- - `useToast`, `useNotification` → Use `useToast` from pace-core
150
- - `useDebounce`, `useDebounced` → Use `useDebounce` from pace-core
151
- - `useAuth`, `useAuthentication` → Use `useUnifiedAuth` from pace-core
152
- - `useForm`, `useZodForm` → Use `useZodForm` from pace-core
153
-
154
- **Example**:
155
- ```typescript
156
- // ⚠️ Warning
157
- function useToast() {
158
- // custom implementation
159
- }
160
-
161
- // ✅ Recommended
162
- import { useToast } from '@jmruthers/pace-core';
163
- ```
164
-
165
- ### prefer-pace-core-utils
166
-
167
- **Severity**: Warning
168
-
169
- Detects utility functions that duplicate pace-core functionality.
170
-
171
- **Common Patterns Detected**:
172
- - `formatDate`, `dateFormat` → Use `formatDate` from pace-core
173
- - `formatCurrency`, `formatMoney` → Use `formatCurrency` from pace-core
174
- - `cn`, `classNames`, `clsx` → Use `cn` from pace-core
175
- - `validate`, `validateInput` → Use `validateUserInput` from pace-core
176
-
177
- **Example**:
178
- ```typescript
179
- // ⚠️ Warning
180
- function formatDate(date: Date): string {
181
- // custom implementation
182
- }
183
-
184
- // ✅ Recommended
185
- import { formatDate } from '@jmruthers/pace-core';
186
- ```
187
-
188
- ### no-local-component-duplication
189
-
190
- **Severity**: Error
191
-
192
- Prevents creating local components with names matching pace-core components.
193
-
194
- **Example Violation**:
195
- ```
196
- // ❌ Error: components/Button.tsx
197
- export function Button() { ... }
198
-
199
- // pace-core already provides Button component
200
- ```
201
-
202
- **Fix**: Remove the local component and import from pace-core:
203
- ```typescript
204
- import { Button } from '@jmruthers/pace-core';
205
- ```
206
-
207
- ## Static Analysis Script
208
-
209
- The static analysis script provides a comprehensive scan of your codebase and generates a detailed compliance report.
210
-
211
- ### Running the Script
212
-
213
- ```bash
214
- # From your consuming app root
215
- node node_modules/@jmruthers/pace-core/scripts/check-pace-core-compliance.cjs
216
- ```
217
-
218
- Or add it to your `package.json`:
219
-
220
- ```json
221
- {
222
- "scripts": {
223
- "check:pace-core": "node node_modules/@jmruthers/pace-core/scripts/check-pace-core-compliance.cjs"
224
- }
225
- }
226
- ```
227
-
228
- ### What It Checks
229
-
230
- 1. **Restricted Imports** - Scans for direct imports of wrapped libraries
231
- 2. **Duplicate Components** - Finds local components matching pace-core names
232
- 3. **Duplicate Hooks** - Finds local hooks matching pace-core hooks
233
- 4. **Duplicate Utils** - Finds local utils matching pace-core utils
234
- 5. **Suggestions** - Recommends pace-core alternatives for native HTML elements
235
-
236
- ### Report Output
237
-
238
- The script generates a color-coded terminal report showing:
239
-
240
- - ❌ **Errors** - Critical violations that must be fixed
241
- - ⚠️ **Warnings** - Issues that should be addressed
242
- - 💡 **Suggestions** - Recommendations for improvement
243
- - ✅ **Summary** - Overall compliance status
244
-
245
- Example output:
246
- ```
247
- ═══════════════════════════════════════════════════════════
248
- pace-core Compliance Report
249
- ═══════════════════════════════════════════════════════════
250
-
251
- ❌ Restricted Imports Found: 3
252
-
253
- • src/components/CustomDialog.tsx:5
254
- Import: @radix-ui/react-dialog
255
- Reason: Use Dialog component from pace-core instead
256
-
257
- Summary:
258
- Total Issues: 3
259
- - Restricted Imports: 3
260
- - Duplicate Components/Hooks/Utils: 0
261
- - Suggestions: 0
262
- ```
263
-
264
- ## Best Practices
265
-
266
- ### 1. Always Import from pace-core
267
-
268
- ```typescript
269
- // ✅ Good
270
- import { Button, Card, Dialog } from '@jmruthers/pace-core';
271
- import { useToast, useDebounce } from '@jmruthers/pace-core';
272
- import { formatDate, formatCurrency } from '@jmruthers/pace-core';
273
- ```
274
-
275
- ### 2. Use pace-core Components for UI
276
-
277
- Avoid native HTML elements when pace-core provides a component:
278
-
279
- ```tsx
280
- // ❌ Avoid
281
- <button className="btn">Click</button>
282
-
283
- // ✅ Use pace-core
284
- <Button>Click</Button>
285
- ```
286
-
287
- ### 3. Leverage pace-core Hooks
288
-
289
- Don't recreate hooks that pace-core already provides:
290
-
291
- ```typescript
292
- // ❌ Avoid
293
- const [debouncedValue, setDebouncedValue] = useState(value);
294
- useEffect(() => {
295
- const timer = setTimeout(() => setDebouncedValue(value), 500);
296
- return () => clearTimeout(timer);
297
- }, [value]);
298
-
299
- // ✅ Use pace-core
300
- import { useDebounce } from '@jmruthers/pace-core';
301
- const debouncedValue = useDebounce(value, 500);
302
- ```
303
-
304
- ### 4. Use pace-core Utilities
305
-
306
- Leverage formatting, validation, and other utilities from pace-core:
307
-
308
- ```typescript
309
- // ❌ Avoid
310
- const formatted = new Intl.DateTimeFormat('en-US').format(date);
311
-
312
- // ✅ Use pace-core
313
- import { formatDate } from '@jmruthers/pace-core';
314
- const formatted = formatDate(date);
315
- ```
316
-
317
- ### 5. Check Before Creating New Components
318
-
319
- Before creating a new component, check if pace-core already provides it:
320
-
321
- 1. Review the [pace-core documentation](https://github.com/your-org/pace-core)
322
- 2. Check `core-usage-manifest.json` for available components
323
- 3. Search pace-core exports
324
-
325
- ## Troubleshooting
326
-
327
- ### ESLint Rules Not Working
328
-
329
- 1. **Verify plugin is loaded**: Check that the config is imported correctly:
330
- ```javascript
331
- // In your eslint.config.js, add temporarily:
332
- import paceCoreConfig from '@jmruthers/pace-core/eslint-config';
333
- console.log('Config:', paceCoreConfig);
334
- console.log('Has plugins:', paceCoreConfig[0]?.plugins);
335
- ```
336
-
337
- 2. **Check rule names**: Rules must be prefixed with `pace-core-compliance/`
338
-
339
- 3. **Verify manifest exists**: Rules load from `core-usage-manifest.json` in the pace-core package
340
-
341
- 4. **CommonJS/ES Module issues**: If you're using ES modules and rules aren't loading:
342
- - Ensure you're using the config preset (Option 1) which handles this automatically
343
- - Or use `createRequire` when importing rules directly (Option 2)
344
-
345
- 5. **Verify rules are available**: Check that the rules file exists:
346
- ```bash
347
- ls node_modules/@jmruthers/pace-core/dist/eslint-rules/pace-core-compliance.cjs
348
- ```
349
-
350
- ### Static Analysis Script Errors
351
-
352
- 1. **Manifest not found**: Ensure `core-usage-manifest.json` exists in pace-core package
353
- 2. **No files scanned**: Check that you're running from the project root
354
- 3. **Permission errors**: Ensure script has read access to source files
355
-
356
- ### False Positives
357
-
358
- If you encounter false positives:
359
-
360
- 1. **Component name conflicts**: If you have a legitimate reason to create a local component with a pace-core name, consider:
361
- - Renaming your component
362
- - Using a namespace/prefix
363
- - Documenting why pace-core doesn't meet your needs
364
-
365
- 2. **Hook/Util patterns**: The pattern matching may flag similar names. Review the suggestion and decide if migration makes sense.
366
-
367
- ## Integration with CI/CD
368
-
369
- While CI/CD integration is not included in the initial release, you can easily add it:
370
-
371
- ```yaml
372
- # .github/workflows/pace-core-compliance.yml
373
- name: pace-core Compliance
374
-
375
- on: [push, pull_request]
376
-
377
- jobs:
378
- compliance:
379
- runs-on: ubuntu-latest
380
- steps:
381
- - uses: actions/checkout@v3
382
- - uses: actions/setup-node@v3
383
- - run: npm ci
384
- - run: npm run check:pace-core
385
- - run: npm run lint
386
- ```
387
-
388
- ## Verification
389
-
390
- After setting up the ESLint config, verify it's working:
391
-
392
- 1. **Check ESLint can load the config**:
393
- ```bash
394
- npx eslint --print-config src/App.tsx
395
- ```
396
- Look for `pace-core-compliance` in the plugins section.
397
-
398
- 2. **Test with a violation**: Create a test file that imports a restricted library:
399
- ```typescript
400
- // test-violation.ts
401
- import { Dialog } from '@radix-ui/react-dialog'; // Should trigger error
402
- ```
403
- Run ESLint and verify it reports the violation.
404
-
405
- 3. **Run static analysis**: Use the compliance script to get a full report:
406
- ```bash
407
- npm run check:pace-core
408
- ```
409
-
410
- ## Getting Help
411
-
412
- - **Documentation**: See [pace-core docs](../README.md)
413
- - **Issues**: Report false positives or rule issues
414
- - **Manifest**: Check `core-usage-manifest.json` for available exports
415
- - **ESLint Config**: The config file is at `@jmruthers/pace-core/eslint-config` (CommonJS)
416
- - **ESLint Rules**: The rules are at `@jmruthers/pace-core/eslint-rules` (CommonJS)
417
-
418
- ## File Locations
419
-
420
- When installed in a consuming app, the compliance tools are available at:
421
-
422
- - **ESLint Config**: `node_modules/@jmruthers/pace-core/eslint-config-pace-core.cjs`
423
- - **ESLint Rules**: `node_modules/@jmruthers/pace-core/dist/eslint-rules/pace-core-compliance.cjs`
424
- - **Static Analysis Script**: `node_modules/@jmruthers/pace-core/scripts/check-pace-core-compliance.cjs`
425
- - **Manifest**: `node_modules/@jmruthers/pace-core/core-usage-manifest.json`
426
-
427
- ## Related Documentation
428
-
429
- - [Component Standards](./03-component-standard.md)
430
- - [API & RPC Standards](./02-api-and-rpc-standard.md)
431
- - [Getting Started Guide](../getting-started/README.md)
432
-
@@ -1,197 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Accessibility Check Module
5
- * @package @jmruthers/pace-core
6
- * @module Audit/Checks/Accessibility
7
- *
8
- * Checks for:
9
- * - Missing aria-* attributes
10
- * - Missing keyboard navigation
11
- * - Missing focus management
12
- * - Missing alt text on images
13
- */
14
-
15
- const fs = require('fs');
16
- const { getRelativePath, getLineNumber } = require('../utils.cjs');
17
-
18
- const accessibilityCheck = {
19
- name: 'accessibility',
20
- description: 'Accessibility checks (aria attributes, keyboard navigation, alt text)',
21
- severity: 'warning',
22
-
23
- async run(context) {
24
- const { projectRoot, files } = context;
25
- const issues = [];
26
- const warnings = [];
27
- const suggestions = [];
28
-
29
- if (!files || files.length === 0) {
30
- return { issues, warnings, suggestions };
31
- }
32
-
33
- for (const filePath of files) {
34
- try {
35
- // Only check React component files
36
- if (!filePath.match(/\.(tsx|jsx)$/)) {
37
- continue;
38
- }
39
-
40
- const content = fs.readFileSync(filePath, 'utf8');
41
- const relativePath = getRelativePath(filePath, projectRoot);
42
- const normalizedPath = relativePath.replace(/\\/g, '/');
43
-
44
- // Skip root-level src directory - in pace-core repository, this is a demo/showcase app
45
- // Note: We DO check packages/core/ files because accessibility issues (missing alt attributes, missing form labels) are real issues that should be fixed
46
- const isRootSrc = normalizedPath.startsWith('src/') && !normalizedPath.includes('packages/');
47
- if (isRootSrc) {
48
- continue; // Skip demo app files
49
- }
50
-
51
- // Skip scripts directory - utility scripts don't need accessibility validation
52
- const isScript = normalizedPath.startsWith('scripts/') || normalizedPath.includes('/scripts/');
53
- if (isScript) {
54
- continue; // Skip script files
55
- }
56
-
57
- // Skip pace-core library components and examples - these are designed to accept accessibility props
58
- // Library components accept id, aria-label, etc. via props spread
59
- // Examples are demonstration code, not production code
60
- const isPaceCorePackage = normalizedPath.includes('packages/core/') || normalizedPath.startsWith('packages/core/');
61
- const isExample = normalizedPath.includes('/examples/');
62
- const isLibraryComponent = isPaceCorePackage && !isExample;
63
-
64
- // Check for images without alt text
65
- // Skip library components - they accept alt as a prop
66
- if (!isLibraryComponent) {
67
- const imgPattern = /<img[^>]*>/g;
68
- let imgMatch;
69
- while ((imgMatch = imgPattern.exec(content)) !== null) {
70
- const imgTag = imgMatch[0];
71
- // Check for alt attribute, including React props (alt=, alt =, alt={)
72
- const hasAlt = imgTag.includes('alt=') || imgTag.includes('alt =') || imgTag.includes('alt={');
73
- if (!hasAlt) {
74
- warnings.push({
75
- type: 'missing-alt-text',
76
- file: relativePath,
77
- line: getLineNumber(content, imgMatch.index),
78
- message: 'Image element missing alt attribute',
79
- recommendation: 'Add alt text to all images for accessibility: <img alt="description" ... />'
80
- });
81
- }
82
- }
83
- }
84
-
85
- // Check for buttons/clickable elements without aria-label or accessible text
86
- const buttonPattern = /<(button|a|div)\s+[^>]*(onClick|role=["']button["'])[^>]*>/g;
87
- let buttonMatch;
88
- while ((buttonMatch = buttonPattern.exec(content)) !== null) {
89
- const buttonTag = buttonMatch[0];
90
- const hasAriaLabel = buttonTag.includes('aria-label=') || buttonTag.includes('ariaLabel=');
91
- const hasAccessibleText = buttonTag.includes('>') && content.substring(buttonMatch.index).match(/<[^>]*>([^<]+)</);
92
-
93
- if (!hasAriaLabel && !hasAccessibleText) {
94
- warnings.push({
95
- type: 'missing-aria-label',
96
- file: relativePath,
97
- line: getLineNumber(content, buttonMatch.index),
98
- message: 'Interactive element missing accessible label',
99
- recommendation: 'Add aria-label or ensure element contains accessible text content'
100
- });
101
- }
102
- }
103
-
104
- // Check for form inputs without labels
105
- // Skip library components - they accept id, aria-label, etc. via props spread
106
- // Skip examples - they're demonstration code
107
- if (!isLibraryComponent && !isExample) {
108
- const inputPattern = /<input[^>]*>/g;
109
- let inputMatch;
110
- while ((inputMatch = inputPattern.exec(content)) !== null) {
111
- // Get the full input tag including multi-line attributes
112
- const inputStart = inputMatch.index;
113
- const afterInput = content.substring(inputStart, Math.min(content.length, inputStart + 500));
114
- const inputTagEnd = afterInput.indexOf('>');
115
- const fullInputTag = inputTagEnd !== -1 ? afterInput.substring(0, inputTagEnd + 1) : inputMatch[0];
116
-
117
- // Check for id (including React props)
118
- const hasId = /id=["']([^"']+)["']|id=\{/.test(fullInputTag);
119
- // Check for aria-label (including React props)
120
- const hasAriaLabel = /aria-label=["']|ariaLabel=|aria-label=\{/.test(fullInputTag);
121
-
122
- if (hasId) {
123
- const idMatch = fullInputTag.match(/id=["']([^"']+)["']/);
124
- if (idMatch) {
125
- const id = idMatch[1];
126
- // Check if there's a corresponding label
127
- const beforeInput = content.substring(Math.max(0, inputMatch.index - 200), inputMatch.index);
128
- const hasLabel = new RegExp(`<label[^>]*for=["']${id}["']`, 'i').test(beforeInput);
129
-
130
- if (!hasLabel && !hasAriaLabel) {
131
- warnings.push({
132
- type: 'missing-input-label',
133
- file: relativePath,
134
- line: getLineNumber(content, inputMatch.index),
135
- message: 'Form input missing associated label',
136
- recommendation: 'Add a <label> element with for attribute matching input id, or use aria-label'
137
- });
138
- }
139
- }
140
- } else if (!hasAriaLabel) {
141
- warnings.push({
142
- type: 'missing-input-label',
143
- file: relativePath,
144
- line: getLineNumber(content, inputMatch.index),
145
- message: 'Form input missing id and label',
146
- recommendation: 'Add id to input and corresponding label, or use aria-label'
147
- });
148
- }
149
- }
150
- }
151
-
152
- // Check for missing focus management in modals/dialogs
153
- const dialogPattern = /<Dialog|<dialog/gi;
154
- if (dialogPattern.test(content)) {
155
- // Skip Dialog.tsx itself - it IS the Dialog component
156
- if (normalizedPath.includes('/Dialog/Dialog.tsx') || normalizedPath.includes('/Dialog/Dialog.jsx')) {
157
- continue; // Skip the Dialog component file itself
158
- }
159
-
160
- // Check if Dialog from pace-core is used (which handles focus automatically)
161
- // Check for both published package import and relative imports (within pace-core repo)
162
- const usesPaceCoreDialog = content.includes('from \'@jmruthers/pace-core\'') ||
163
- content.includes('from "@jmruthers/pace-core"') ||
164
- content.includes('from \'../Dialog') ||
165
- content.includes('from "../Dialog') ||
166
- content.includes('from \'../../Dialog') ||
167
- content.includes('from "../../Dialog') ||
168
- content.includes('from \'../../../Dialog') ||
169
- content.includes('from "../../../Dialog') ||
170
- content.includes('from \'./Dialog') ||
171
- content.includes('from "./Dialog');
172
-
173
- if (!usesPaceCoreDialog) {
174
- suggestions.push({
175
- type: 'dialog-focus-management',
176
- file: relativePath,
177
- message: 'Custom dialog implementation detected',
178
- recommendation: 'Use Dialog component from @jmruthers/pace-core which handles focus management automatically'
179
- });
180
- }
181
- }
182
-
183
- // Check for color contrast issues (heuristic - check for color props without sufficient contrast)
184
- const colorPattern = /(?:color|bg-|text-)=["']([^"']+)["']/g;
185
- // This is a simplified check - full implementation would need color contrast calculation
186
- // For now, just suggest using pace-core components which handle contrast
187
-
188
- } catch (error) {
189
- // Skip files with errors
190
- }
191
- }
192
-
193
- return { issues, warnings, suggestions };
194
- }
195
- };
196
-
197
- module.exports = accessibilityCheck;