@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,638 +0,0 @@
1
- /**
2
- * ESLint Rules for pace-core Compliance Enforcement
3
- * @package @jmruthers/pace-core
4
- * @module ESLintRules/pace-core-compliance
5
- * @since 1.0.0
6
- *
7
- * This module provides ESLint rules to enforce pace-core usage patterns
8
- * and prevent consuming apps from creating local alternatives.
9
- */
10
-
11
- const fs = require('fs');
12
- const path = require('path');
13
-
14
- // Load manifest data
15
- let manifestData = null;
16
- try {
17
- const manifestPath = path.join(__dirname, '../../core-usage-manifest.json');
18
- if (fs.existsSync(manifestPath)) {
19
- manifestData = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
20
- }
21
- } catch (error) {
22
- // If manifest can't be loaded, rules will use hardcoded defaults
23
- console.warn('Warning: Could not load core-usage-manifest.json, using defaults');
24
- }
25
-
26
- // Get restricted imports from manifest or use defaults
27
- const getRestrictedImports = () => {
28
- if (manifestData && manifestData.restrictedImports) {
29
- return manifestData.restrictedImports;
30
- }
31
- // Fallback defaults
32
- return [
33
- { module: '@radix-ui/react-avatar', reason: 'Use Avatar component from pace-core instead' },
34
- { module: '@radix-ui/react-checkbox', reason: 'Use Checkbox component from pace-core instead' },
35
- { module: '@radix-ui/react-dialog', reason: 'Use Dialog component from pace-core instead' },
36
- { module: '@radix-ui/react-label', reason: 'Use Label component from pace-core instead' },
37
- { module: '@radix-ui/react-slot', reason: 'Use Button component from pace-core which handles slot composition' },
38
- { module: '@radix-ui/react-switch', reason: 'Use Switch component from pace-core instead' },
39
- { module: '@radix-ui/react-tabs', reason: 'Use Tabs component from pace-core instead' },
40
- { module: '@radix-ui/react-toast', reason: 'Use Toast component and useToast hook from pace-core instead' },
41
- { module: '@radix-ui/react-tooltip', reason: 'Use Tooltip component from pace-core instead' },
42
- { module: 'react-day-picker', reason: 'Use Calendar component from pace-core instead' },
43
- { module: '@tanstack/react-table', reason: 'Use DataTable component and related hooks from pace-core instead. DataTable wraps and standardizes table functionality' },
44
- { module: 'react-hook-form', reason: 'Use Form component and useZodForm hook from pace-core instead' },
45
- { module: 'zod', reason: 'Use validation utilities and schemas from pace-core instead. pace-core provides standardized validation helpers' }
46
- ];
47
- };
48
-
49
- // Get pace-core components from manifest or use defaults
50
- const getPaceCoreComponents = () => {
51
- if (manifestData && manifestData.components) {
52
- return manifestData.components;
53
- }
54
- return ['Button', 'Card', 'Dialog', 'Input', 'Form', 'Select', 'Alert', 'Badge', 'Checkbox', 'Switch', 'Textarea', 'Label', 'Table', 'DataTable', 'Toast', 'Tooltip', 'Tabs', 'Calendar', 'Avatar', 'Progress'];
55
- };
56
-
57
- // Get pace-core hooks from manifest or use defaults
58
- const getPaceCoreHooks = () => {
59
- if (manifestData && manifestData.hooks) {
60
- return manifestData.hooks;
61
- }
62
- return ['useToast', 'useDebounce', 'useUnifiedAuth', 'useEvents', 'useOrganisations', 'useFileReference', 'useStorage', 'useZodForm', 'useRBAC', 'usePermissions'];
63
- };
64
-
65
- // Get pace-core utils from manifest or use defaults
66
- const getPaceCoreUtils = () => {
67
- if (manifestData && manifestData.utils) {
68
- return manifestData.utils;
69
- }
70
- return ['formatDate', 'formatCurrency', 'formatNumber', 'formatTime', 'formatDateTime', 'cn', 'validateUserInput', 'sanitizeUserInput', 'hasPermission', 'getAppConfig'];
71
- };
72
-
73
- module.exports = {
74
- rules: {
75
- /**
76
- * Block direct imports of libraries wrapped by pace-core
77
- */
78
- 'no-restricted-imports': {
79
- meta: {
80
- type: 'problem',
81
- docs: {
82
- description: 'Disallow direct imports of libraries that pace-core wraps',
83
- category: 'Best Practices',
84
- recommended: true
85
- },
86
- fixable: 'code',
87
- messages: {
88
- restrictedImport: '{{message}} Import from {{alternative}} instead.',
89
- restrictedImportWithReason: '{{message}} {{reason}}'
90
- }
91
- },
92
- create(context) {
93
- const restrictedImports = getRestrictedImports();
94
- const restrictedModules = restrictedImports.map(imp => imp.module);
95
-
96
- // Also catch @radix-ui/* patterns
97
- const radixPattern = /^@radix-ui\//;
98
-
99
- return {
100
- ImportDeclaration(node) {
101
- const importSource = node.source.value;
102
-
103
- // Check exact matches
104
- const restricted = restrictedImports.find(imp => imp.module === importSource);
105
- if (restricted) {
106
- context.report({
107
- node: node.source,
108
- messageId: 'restrictedImportWithReason',
109
- data: {
110
- message: `Direct import of '${importSource}' is not allowed.`,
111
- reason: restricted.reason
112
- },
113
- suggest: [{
114
- desc: `Use pace-core alternative: ${restricted.reason}`,
115
- fix(fixer) {
116
- // Suggest importing from pace-core instead
117
- const paceCoreAlternative = getPaceCoreAlternative(importSource);
118
- if (paceCoreAlternative) {
119
- return fixer.replaceText(
120
- node.source,
121
- `'@jmruthers/pace-core${paceCoreAlternative}'`
122
- );
123
- }
124
- return null;
125
- }
126
- }]
127
- });
128
- return;
129
- }
130
-
131
- // Check @radix-ui/* pattern
132
- if (radixPattern.test(importSource) && !restrictedModules.includes(importSource)) {
133
- context.report({
134
- node: node.source,
135
- messageId: 'restrictedImport',
136
- data: {
137
- message: `Direct import of '${importSource}' is not allowed.`,
138
- alternative: '@jmruthers/pace-core'
139
- },
140
- suggest: [{
141
- desc: 'Use pace-core component instead',
142
- fix(fixer) {
143
- return fixer.replaceText(
144
- node.source,
145
- "'@jmruthers/pace-core'"
146
- );
147
- }
148
- }]
149
- });
150
- }
151
- }
152
- };
153
- }
154
- },
155
-
156
- /**
157
- * Prefer pace-core components over native HTML elements or custom implementations
158
- */
159
- 'prefer-pace-core-components': {
160
- meta: {
161
- type: 'suggestion',
162
- docs: {
163
- description: 'Suggest using pace-core components instead of native HTML elements',
164
- category: 'Best Practices',
165
- recommended: true
166
- },
167
- messages: {
168
- preferButton: "Use 'Button' component from '@jmruthers/pace-core' instead of <button>",
169
- preferInput: "Use 'Input' component from '@jmruthers/pace-core' instead of <input>",
170
- preferTextarea: "Use 'Textarea' component from '@jmruthers/pace-core' instead of <textarea>",
171
- preferLabel: "Use 'Label' component from '@jmruthers/pace-core' instead of <label>",
172
- preferForm: "Use 'Form' component from '@jmruthers/pace-core' instead of custom form implementation"
173
- }
174
- },
175
- create(context) {
176
- const paceCoreComponents = getPaceCoreComponents();
177
-
178
- return {
179
- JSXOpeningElement(node) {
180
- const elementName = node.name.name;
181
-
182
- if (!elementName) return;
183
-
184
- // Check for native HTML elements that have pace-core alternatives
185
- const nativeToPaceCore = {
186
- 'button': 'Button',
187
- 'input': 'Input',
188
- 'textarea': 'Textarea',
189
- 'label': 'Label'
190
- };
191
-
192
- if (nativeToPaceCore[elementName.toLowerCase()]) {
193
- const paceCoreComponent = nativeToPaceCore[elementName.toLowerCase()];
194
- if (paceCoreComponents.includes(paceCoreComponent)) {
195
- context.report({
196
- node,
197
- messageId: `prefer${paceCoreComponent}`,
198
- suggest: [{
199
- desc: `Import and use ${paceCoreComponent} from pace-core`,
200
- fix(fixer) {
201
- // This is a complex fix, so we'll just report
202
- return null;
203
- }
204
- }]
205
- });
206
- }
207
- }
208
- }
209
- };
210
- }
211
- },
212
-
213
- /**
214
- * Detect custom hooks that duplicate pace-core functionality
215
- */
216
- 'prefer-pace-core-hooks': {
217
- meta: {
218
- type: 'suggestion',
219
- docs: {
220
- description: 'Suggest using pace-core hooks instead of custom implementations',
221
- category: 'Best Practices',
222
- recommended: true
223
- },
224
- messages: {
225
- preferPaceCoreHook: "Consider using '{{hook}}' from '@jmruthers/pace-core' instead of custom hook '{{customHook}}'"
226
- }
227
- },
228
- create(context) {
229
- const paceCoreHooks = getPaceCoreHooks();
230
- const hookPatterns = {
231
- 'useToast': ['useToast', 'useNotification', 'useSnackbar'],
232
- 'useDebounce': ['useDebounce', 'useDebounced'],
233
- 'useAuth': ['useAuth', 'useAuthentication', 'useUser'],
234
- 'useFile': ['useFile', 'useFileUpload', 'useFileReference'],
235
- 'useForm': ['useForm', 'useZodForm'],
236
- 'useTable': ['useTable', 'useDataTable']
237
- };
238
-
239
- return {
240
- FunctionDeclaration(node) {
241
- const functionName = node.id?.name;
242
- if (!functionName || !functionName.startsWith('use')) return;
243
-
244
- // Check if this looks like a hook that pace-core provides
245
- for (const [paceCoreHook, patterns] of Object.entries(hookPatterns)) {
246
- if (paceCoreHooks.includes(paceCoreHook)) {
247
- for (const pattern of patterns) {
248
- if (functionName.toLowerCase().includes(pattern.toLowerCase().replace('use', ''))) {
249
- context.report({
250
- node: node.id,
251
- messageId: 'preferPaceCoreHook',
252
- data: {
253
- hook: paceCoreHook,
254
- customHook: functionName
255
- }
256
- });
257
- return;
258
- }
259
- }
260
- }
261
- }
262
- }
263
- };
264
- }
265
- },
266
-
267
- /**
268
- * Detect utility functions that duplicate pace-core functionality
269
- */
270
- 'prefer-pace-core-utils': {
271
- meta: {
272
- type: 'suggestion',
273
- docs: {
274
- description: 'Suggest using pace-core utilities instead of custom implementations',
275
- category: 'Best Practices',
276
- recommended: true
277
- },
278
- messages: {
279
- preferPaceCoreUtil: "Consider using '{{util}}' from '@jmruthers/pace-core' instead of custom function '{{customUtil}}'"
280
- }
281
- },
282
- create(context) {
283
- const paceCoreUtils = getPaceCoreUtils();
284
- const utilPatterns = {
285
- 'formatDate': ['formatDate', 'formatDateTime', 'dateFormat'],
286
- 'formatCurrency': ['formatCurrency', 'formatMoney', 'currencyFormat'],
287
- 'formatNumber': ['formatNumber', 'numberFormat'],
288
- 'cn': ['cn', 'classNames', 'clsx', 'mergeClasses'],
289
- 'validateUserInput': ['validate', 'validateInput', 'validateUser'],
290
- 'sanitizeUserInput': ['sanitize', 'sanitizeInput', 'sanitizeUser']
291
- };
292
-
293
- return {
294
- FunctionDeclaration(node) {
295
- const functionName = node.id?.name;
296
- if (!functionName) return;
297
-
298
- // Check if this looks like a util that pace-core provides
299
- for (const [paceCoreUtil, patterns] of Object.entries(utilPatterns)) {
300
- if (paceCoreUtils.includes(paceCoreUtil)) {
301
- for (const pattern of patterns) {
302
- if (functionName.toLowerCase().includes(pattern.toLowerCase())) {
303
- context.report({
304
- node: node.id,
305
- messageId: 'preferPaceCoreUtil',
306
- data: {
307
- util: paceCoreUtil,
308
- customUtil: functionName
309
- }
310
- });
311
- return;
312
- }
313
- }
314
- }
315
- }
316
- }
317
- };
318
- }
319
- },
320
-
321
- /**
322
- * Disallow custom auth/rbac/permission implementations
323
- */
324
- 'no-custom-auth-code': {
325
- meta: {
326
- type: 'problem',
327
- docs: {
328
- description: 'Disallow custom auth/rbac/permission implementations. Must use pace-core exclusively.',
329
- category: 'Best Practices',
330
- recommended: true
331
- },
332
- messages: {
333
- customAuthCode: "Custom {{type}} '{{name}}' detected. Use pace-core's {{name}} from '@jmruthers/pace-core' instead."
334
- }
335
- },
336
- create(context) {
337
- const authRbacPatterns = [
338
- { name: 'useAuth', type: 'hook' },
339
- { name: 'useLogin', type: 'hook' },
340
- { name: 'useLogout', type: 'hook' },
341
- { name: 'useSession', type: 'hook' },
342
- { name: 'useUser', type: 'hook' },
343
- { name: 'useAuthentication', type: 'hook' },
344
- { name: 'usePermissions', type: 'hook' },
345
- { name: 'useCan', type: 'hook' },
346
- { name: 'useAccessLevel', type: 'hook' },
347
- { name: 'useRole', type: 'hook' },
348
- { name: 'PermissionGuard', type: 'component' },
349
- { name: 'AuthGuard', type: 'component' },
350
- { name: 'RoleGuard', type: 'component' },
351
- { name: 'AccessGuard', type: 'component' },
352
- { name: 'checkPermission', type: 'util' },
353
- { name: 'hasPermission', type: 'util' },
354
- { name: 'hasAccess', type: 'util' },
355
- { name: 'canAccess', type: 'util' },
356
- { name: 'isPermitted', type: 'util' }
357
- ];
358
-
359
- let hasPaceCoreImport = false;
360
-
361
- return {
362
- ImportDeclaration(node) {
363
- const importSource = node.source.value;
364
- if (importSource === '@jmruthers/pace-core' ||
365
- importSource.startsWith('@jmruthers/pace-core/')) {
366
- hasPaceCoreImport = true;
367
- }
368
- },
369
- FunctionDeclaration(node) {
370
- const functionName = node.id?.name;
371
- if (!functionName) return;
372
-
373
- const pattern = authRbacPatterns.find(p => p.name === functionName);
374
- if (pattern && !hasPaceCoreImport) {
375
- context.report({
376
- node: node.id,
377
- messageId: 'customAuthCode',
378
- data: {
379
- name: functionName,
380
- type: pattern.type
381
- }
382
- });
383
- }
384
- },
385
- VariableDeclarator(node) {
386
- if (node.id.type === 'Identifier') {
387
- const varName = node.id.name;
388
- const pattern = authRbacPatterns.find(p => p.name === varName);
389
- if (pattern && !hasPaceCoreImport) {
390
- // Check if it's a function expression
391
- if (node.init && (node.init.type === 'FunctionExpression' || node.init.type === 'ArrowFunctionExpression')) {
392
- context.report({
393
- node: node.id,
394
- messageId: 'customAuthCode',
395
- data: {
396
- name: varName,
397
- type: pattern.type
398
- }
399
- });
400
- }
401
- }
402
- }
403
- }
404
- };
405
- }
406
- },
407
-
408
- /**
409
- * Disallow multiple Supabase client configurations
410
- */
411
- 'no-duplicate-supabase-config': {
412
- meta: {
413
- type: 'problem',
414
- docs: {
415
- description: 'Disallow multiple Supabase client configurations. Consolidate to a single configuration.',
416
- category: 'Best Practices',
417
- recommended: true
418
- },
419
- messages: {
420
- duplicateConfig: 'Multiple Supabase client instantiations found. Consolidate to a single client configuration.'
421
- }
422
- },
423
- create(context) {
424
- let createClientCount = 0;
425
-
426
- return {
427
- CallExpression(node) {
428
- if (node.callee.type === 'Identifier' && node.callee.name === 'createClient') {
429
- createClientCount++;
430
- if (createClientCount > 1) {
431
- context.report({
432
- node,
433
- messageId: 'duplicateConfig'
434
- });
435
- }
436
- }
437
- }
438
- };
439
- }
440
- },
441
-
442
- /**
443
- * Require PagePermissionGuard on all pages/routes
444
- */
445
- 'require-page-permission-guard': {
446
- meta: {
447
- type: 'problem',
448
- docs: {
449
- description: 'Require PagePermissionGuard on all pages/routes for proper RBAC enforcement.',
450
- category: 'Best Practices',
451
- recommended: true
452
- },
453
- messages: {
454
- missingGuard: 'Route/page found without PagePermissionGuard. All routes should be protected with PagePermissionGuard from pace-core.'
455
- }
456
- },
457
- create(context) {
458
- let hasRoute = false;
459
- let hasPagePermissionGuard = false;
460
- let hasPaceCoreRBACImport = false;
461
-
462
- return {
463
- ImportDeclaration(node) {
464
- const importSource = node.source.value;
465
- if (importSource === '@jmruthers/pace-core/rbac' ||
466
- importSource.startsWith('@jmruthers/pace-core/rbac/')) {
467
- hasPaceCoreRBACImport = true;
468
- }
469
- if (node.specifiers.some(spec =>
470
- spec.type === 'ImportSpecifier' && spec.imported.name === 'PagePermissionGuard'
471
- )) {
472
- hasPagePermissionGuard = true;
473
- }
474
- },
475
- JSXOpeningElement(node) {
476
- if (node.name.name === 'Route') {
477
- hasRoute = true;
478
- }
479
- if (node.name.name === 'PagePermissionGuard') {
480
- hasPagePermissionGuard = true;
481
- }
482
- },
483
- CallExpression(node) {
484
- if (node.callee.type === 'Identifier') {
485
- if (node.callee.name === 'createBrowserRouter' ||
486
- node.callee.name === 'createRoutesFromElements') {
487
- hasRoute = true;
488
- }
489
- }
490
- },
491
- 'Program:exit'(node) {
492
- if (hasRoute && !hasPagePermissionGuard && !hasPaceCoreRBACImport) {
493
- context.report({
494
- node,
495
- messageId: 'missingGuard'
496
- });
497
- }
498
- }
499
- };
500
- }
501
- },
502
-
503
- /**
504
- * Disallow direct Supabase auth usage
505
- */
506
- 'no-direct-supabase-auth': {
507
- meta: {
508
- type: 'problem',
509
- docs: {
510
- description: 'Disallow direct Supabase auth usage. Use UnifiedAuthProvider and useUnifiedAuth from pace-core instead.',
511
- category: 'Best Practices',
512
- recommended: true
513
- },
514
- messages: {
515
- directAuth: 'Direct Supabase auth usage detected. Use UnifiedAuthProvider and useUnifiedAuth from pace-core instead.'
516
- }
517
- },
518
- create(context) {
519
- let hasUnifiedAuth = false;
520
-
521
- return {
522
- ImportDeclaration(node) {
523
- const importSource = node.source.value;
524
- if (importSource === '@jmruthers/pace-core' ||
525
- importSource.startsWith('@jmruthers/pace-core/')) {
526
- if (node.specifiers.some(spec =>
527
- (spec.type === 'ImportSpecifier' &&
528
- (spec.imported.name === 'UnifiedAuthProvider' || spec.imported.name === 'useUnifiedAuth'))
529
- )) {
530
- hasUnifiedAuth = true;
531
- }
532
- }
533
- },
534
- MemberExpression(node) {
535
- if (node.property &&
536
- (node.property.name === 'signIn' ||
537
- node.property.name === 'signUp' ||
538
- node.property.name === 'signOut' ||
539
- node.property.name === 'getSession' ||
540
- node.property.name === 'getUser')) {
541
- if (node.object.type === 'MemberExpression' &&
542
- node.object.property &&
543
- node.object.property.name === 'auth') {
544
- if (!hasUnifiedAuth) {
545
- context.report({
546
- node,
547
- messageId: 'directAuth'
548
- });
549
- }
550
- }
551
- }
552
- }
553
- };
554
- }
555
- },
556
-
557
- /**
558
- * Detect component files with names matching pace-core components
559
- */
560
- 'no-local-component-duplication': {
561
- meta: {
562
- type: 'problem',
563
- docs: {
564
- description: 'Disallow local components with names matching pace-core components',
565
- category: 'Best Practices',
566
- recommended: true
567
- },
568
- messages: {
569
- duplicateComponent: "Component '{{componentName}}' conflicts with pace-core component. Use '@jmruthers/pace-core' instead of creating a local version."
570
- }
571
- },
572
- create(context) {
573
- const paceCoreComponents = getPaceCoreComponents();
574
- const filename = context.getFilename();
575
-
576
- // Only check component files (components/, src/components/, etc.)
577
- if (!filename.match(/(components|Components)\//)) {
578
- return {};
579
- }
580
-
581
- // Extract component name from filename
582
- const basename = path.basename(filename, path.extname(filename));
583
- const componentName = basename.replace(/\.(test|spec)$/, '');
584
-
585
- return {
586
- Program(node) {
587
- // Check if this file exports a component with a name matching pace-core
588
- if (paceCoreComponents.includes(componentName)) {
589
- // Check if file exports this component
590
- const hasExport = node.body.some(stmt => {
591
- if (stmt.type === 'ExportNamedDeclaration') {
592
- return stmt.declaration?.id?.name === componentName ||
593
- stmt.specifiers?.some(spec => spec.exported.name === componentName);
594
- }
595
- if (stmt.type === 'ExportDefaultDeclaration') {
596
- return stmt.declaration?.id?.name === componentName ||
597
- stmt.declaration?.name === componentName;
598
- }
599
- return false;
600
- });
601
-
602
- if (hasExport) {
603
- context.report({
604
- node,
605
- messageId: 'duplicateComponent',
606
- data: {
607
- componentName
608
- }
609
- });
610
- }
611
- }
612
- }
613
- };
614
- }
615
- }
616
- }
617
- };
618
-
619
- // Helper function to get pace-core alternative for restricted imports
620
- function getPaceCoreAlternative(importSource) {
621
- const alternatives = {
622
- '@radix-ui/react-avatar': '/components',
623
- '@radix-ui/react-checkbox': '/components',
624
- '@radix-ui/react-dialog': '/components',
625
- '@radix-ui/react-label': '/components',
626
- '@radix-ui/react-switch': '/components',
627
- '@radix-ui/react-tabs': '/components',
628
- '@radix-ui/react-toast': '/components',
629
- '@radix-ui/react-tooltip': '/components',
630
- 'react-day-picker': '/components',
631
- '@tanstack/react-table': '/components',
632
- 'react-hook-form': '/components',
633
- 'zod': '/utils'
634
- };
635
-
636
- return alternatives[importSource] || '';
637
- }
638
-