@jmruthers/pace-core 0.6.4 → 0.6.6

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 (387) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +5 -403
  3. package/core-usage-manifest.json +93 -0
  4. package/cursor-rules/00-pace-core-compliance.mdc +128 -26
  5. package/cursor-rules/01-standards-compliance.mdc +49 -8
  6. package/cursor-rules/02-project-structure.mdc +6 -0
  7. package/cursor-rules/03-solid-principles.mdc +2 -0
  8. package/cursor-rules/04-testing-standards.mdc +2 -0
  9. package/cursor-rules/05-bug-reports-and-features.mdc +2 -0
  10. package/cursor-rules/06-code-quality.mdc +2 -0
  11. package/cursor-rules/07-tech-stack-compliance.mdc +2 -0
  12. package/cursor-rules/08-markup-quality.mdc +52 -27
  13. package/cursor-rules/09-rbac-compliance.mdc +462 -0
  14. package/cursor-rules/10-error-handling-patterns.mdc +179 -0
  15. package/cursor-rules/11-performance-optimization.mdc +169 -0
  16. package/cursor-rules/12-ci-cd-integration.mdc +150 -0
  17. package/dist/{AuthService-Cb34EQs3.d.ts → AuthService-DmfO5rGS.d.ts} +10 -0
  18. package/dist/{DataTable-BMRU8a1j.d.ts → DataTable-2N_tqbfq.d.ts} +1 -1
  19. package/dist/DataTable-LRJL4IRV.js +15 -0
  20. package/dist/{PublicPageProvider-DEMpysFR.d.ts → PublicPageProvider-BBH6Vqg7.d.ts} +72 -139
  21. package/dist/UnifiedAuthProvider-ZT6TIGM7.js +7 -0
  22. package/dist/api-Y4MQWOFW.js +4 -0
  23. package/dist/audit-MYQXYZFU.js +3 -0
  24. package/dist/{chunk-J36DSWQK.js → chunk-2HGJFNAH.js} +8 -28
  25. package/dist/{chunk-OEWDTMG7.js → chunk-3O3WHILE.js} +38 -121
  26. package/dist/{chunk-M43Y4SSO.js → chunk-3QC3KRHK.js} +1 -14
  27. package/dist/{chunk-DGUM43GV.js → chunk-3RG5ZIWI.js} +1 -4
  28. package/dist/{chunk-QXHPKYJV.js → chunk-4SXLQIZO.js} +1 -26
  29. package/dist/chunk-4T7OBVTU.js +62 -0
  30. package/dist/{chunk-E66EQZE6.js → chunk-6GLLNA6U.js} +3 -9
  31. package/dist/{chunk-ZSAAAMVR.js → chunk-6QYDGKQY.js} +1 -4
  32. package/dist/{chunk-NN6WWZ5U.js → chunk-7TYHROIV.js} +579 -563
  33. package/dist/{chunk-M7MPQISP.js → chunk-A55DK444.js} +9 -16
  34. package/dist/{chunk-63FOKYGO.js → chunk-AHU7G2R5.js} +2 -11
  35. package/dist/{chunk-L4OXEN46.js → chunk-BVP2BCJF.js} +2 -16
  36. package/dist/chunk-C7NSAPTL.js +1 -0
  37. package/dist/{chunk-YKRAFF5K.js → chunk-FENMYN2U.js} +73 -149
  38. package/dist/{chunk-AVMLPIM7.js → chunk-FTCRZOG2.js} +284 -432
  39. package/dist/{chunk-G37KK66H.js → chunk-FYHN4DD5.js} +60 -19
  40. package/dist/{chunk-VBXEHIUJ.js → chunk-HF6O3O37.js} +6 -88
  41. package/dist/{chunk-I6DAQMWX.js → chunk-LAZMKTTF.js} +930 -891
  42. package/dist/{chunk-5EC5MEWX.js → chunk-MAGBIDNS.js} +77 -222
  43. package/dist/chunk-MBADTM7L.js +64 -0
  44. package/dist/chunk-OHIK3MIO.js +994 -0
  45. package/dist/{chunk-6SOIHG6Z.js → chunk-S7DKJPLT.js} +115 -44
  46. package/dist/{chunk-FMUCXFII.js → chunk-SD6WQY43.js} +1 -5
  47. package/dist/{chunk-PWLANIRT.js → chunk-TTRFSOKR.js} +1 -7
  48. package/dist/{chunk-5DRSZLL2.js → chunk-UH3NTO3F.js} +1 -6
  49. package/dist/{chunk-FFQEQTNW.js → chunk-UIYSCEV7.js} +134 -45
  50. package/dist/{chunk-3LPHPB62.js → chunk-ZFYPMX46.js} +271 -87
  51. package/dist/{chunk-7JPAB3T5.js → chunk-ZS5VO5JB.js} +1989 -1283
  52. package/dist/components.d.ts +6 -6
  53. package/dist/components.js +57 -267
  54. package/dist/{database.generated-CzIvgcPu.d.ts → database.generated-CcnC_DRc.d.ts} +4795 -3691
  55. package/dist/eslint-rules/index.cjs +22 -0
  56. package/dist/eslint-rules/rules/compliance.cjs +348 -0
  57. package/dist/eslint-rules/rules/components.cjs +113 -0
  58. package/dist/eslint-rules/rules/imports.cjs +102 -0
  59. package/dist/eslint-rules/rules/rbac.cjs +790 -0
  60. package/dist/eslint-rules/utils/helpers.cjs +42 -0
  61. package/dist/eslint-rules/utils/manifest-loader.cjs +75 -0
  62. package/dist/hooks.d.ts +5 -5
  63. package/dist/hooks.js +62 -270
  64. package/dist/icons/index.d.ts +1 -0
  65. package/dist/icons/index.js +1 -0
  66. package/dist/index.d.ts +36 -26
  67. package/dist/index.js +87 -690
  68. package/dist/providers.d.ts +2 -2
  69. package/dist/providers.js +8 -35
  70. package/dist/rbac/eslint-rules.d.ts +46 -44
  71. package/dist/rbac/eslint-rules.js +7 -4
  72. package/dist/rbac/index.d.ts +124 -594
  73. package/dist/rbac/index.js +14 -207
  74. package/dist/styles/index.js +2 -12
  75. package/dist/theming/runtime.js +3 -19
  76. package/dist/{timezone-CHhWg6b4.d.ts → timezone-BZe_eUxx.d.ts} +175 -1
  77. package/dist/{types-CkbwOr4Y.d.ts → types-B-K_5VnO.d.ts} +4 -0
  78. package/dist/types-t9H8qKRw.d.ts +55 -0
  79. package/dist/types.d.ts +1 -1
  80. package/dist/types.js +7 -94
  81. package/dist/{usePublicRouteParams-i3qtoBgg.d.ts → usePublicRouteParams-COZ28Mvq.d.ts} +9 -9
  82. package/dist/utils.d.ts +24 -117
  83. package/dist/utils.js +54 -392
  84. package/docs/README.md +16 -6
  85. package/docs/api/README.md +4 -402
  86. package/docs/api/modules.md +454 -930
  87. package/docs/api-reference/components.md +3 -1
  88. package/docs/api-reference/deprecated.md +31 -6
  89. package/docs/api-reference/rpc-functions.md +78 -3
  90. package/docs/best-practices/accessibility.md +6 -3
  91. package/docs/getting-started/cursor-rules.md +3 -23
  92. package/docs/getting-started/dependencies.md +650 -0
  93. package/docs/getting-started/installation-guide.md +20 -7
  94. package/docs/getting-started/quick-start.md +23 -12
  95. package/docs/implementation-guides/permission-enforcement.md +4 -0
  96. package/docs/rbac/MIGRATION_GUIDE.md +819 -0
  97. package/docs/rbac/RBAC_CONTRACT.md +724 -0
  98. package/docs/rbac/README.md +12 -3
  99. package/docs/rbac/edge-functions-guide.md +376 -0
  100. package/docs/rbac/secure-client-protection.md +0 -34
  101. package/docs/standards/00-pace-core-compliance.md +967 -0
  102. package/docs/standards/01-standards-compliance.md +188 -0
  103. package/docs/standards/02-project-structure.md +985 -0
  104. package/docs/standards/03-solid-principles.md +39 -0
  105. package/docs/standards/04-testing-standards.md +36 -0
  106. package/docs/standards/05-bug-reports-and-features.md +27 -0
  107. package/docs/standards/{04-code-style-standard.md → 06-code-quality.md} +2 -0
  108. package/docs/standards/07-tech-stack-compliance.md +30 -0
  109. package/docs/standards/08-markup-quality.md +345 -0
  110. package/docs/standards/{07-rbac-and-rls-standard.md → 09-rbac-compliance.md} +149 -54
  111. package/docs/standards/10-error-handling-patterns.md +401 -0
  112. package/docs/standards/11-performance-optimization.md +348 -0
  113. package/docs/standards/12-ci-cd-integration.md +370 -0
  114. package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +192 -0
  115. package/docs/standards/README.md +62 -33
  116. package/docs/troubleshooting/organisation-context-setup.md +42 -19
  117. package/eslint-config-pace-core.cjs +20 -4
  118. package/package.json +31 -21
  119. package/scripts/audit/audit-compliance.cjs +1295 -0
  120. package/scripts/audit/audit-components.cjs +260 -0
  121. package/scripts/audit/audit-dependencies.cjs +395 -0
  122. package/scripts/audit/audit-rbac.cjs +954 -0
  123. package/scripts/audit/audit-standards.cjs +1268 -0
  124. package/scripts/audit/index.cjs +1898 -194
  125. package/scripts/install-cursor-rules.cjs +259 -8
  126. package/scripts/validate-master.js +1 -1
  127. package/src/__tests__/fixtures/supabase.ts +1 -1
  128. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +1 -1
  129. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +1 -1
  130. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +1 -1
  131. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +3 -3
  132. package/src/__tests__/helpers/component-test-utils.tsx +1 -1
  133. package/src/__tests__/helpers/supabaseMock.ts +2 -2
  134. package/src/__tests__/public-recipe-view.test.ts +38 -9
  135. package/src/components/Button/Button.tsx +5 -1
  136. package/src/components/ContextSelector/ContextSelector.tsx +42 -39
  137. package/src/components/DataTable/__tests__/keyboard.test.tsx +15 -2
  138. package/src/components/DataTable/components/DataTableBody.tsx +55 -31
  139. package/src/components/DataTable/components/DataTableCore.tsx +186 -13
  140. package/src/components/DataTable/components/DataTableLayout.tsx +30 -5
  141. package/src/components/DataTable/components/EditFields.tsx +23 -3
  142. package/src/components/DataTable/components/EditableRow.tsx +7 -2
  143. package/src/components/DataTable/components/ImportModal.tsx +4 -6
  144. package/src/components/DataTable/components/RowComponent.tsx +12 -0
  145. package/src/components/DataTable/components/ViewRowModal.tsx +4 -4
  146. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +455 -96
  147. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +122 -58
  148. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -4
  149. package/src/components/DataTable/core/DataTableContext.tsx +1 -1
  150. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +51 -47
  151. package/src/components/DataTable/hooks/useDataTablePermissions.ts +24 -21
  152. package/src/components/DataTable/hooks/useDataTableState.ts +125 -9
  153. package/src/components/DataTable/hooks/useTableColumns.ts +40 -2
  154. package/src/components/DataTable/hooks/useTableHandlers.ts +11 -0
  155. package/src/components/DataTable/types.ts +5 -0
  156. package/src/components/DateTimeField/DateTimeField.tsx +20 -20
  157. package/src/components/DateTimeField/README.md +5 -2
  158. package/src/components/Dialog/Dialog.test.tsx +361 -318
  159. package/src/components/Dialog/Dialog.tsx +1154 -323
  160. package/src/components/Dialog/index.ts +3 -3
  161. package/src/components/FileDisplay/FileDisplay.test.tsx +45 -2
  162. package/src/components/FileDisplay/FileDisplay.tsx +28 -22
  163. package/src/components/Form/Form.test.tsx +9 -10
  164. package/src/components/Form/Form.tsx +369 -9
  165. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +28 -28
  166. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +40 -54
  167. package/src/components/LoginForm/LoginForm.tsx +2 -2
  168. package/src/components/NavigationMenu/NavigationMenu.test.tsx +14 -13
  169. package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
  170. package/src/components/NavigationMenu/useNavigationFiltering.ts +11 -21
  171. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +6 -4
  172. package/src/components/PaceAppLayout/PaceAppLayout.tsx +30 -41
  173. package/src/components/PaceAppLayout/README.md +10 -9
  174. package/src/components/PaceAppLayout/test-setup.tsx +40 -31
  175. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +108 -61
  176. package/src/components/PaceLoginPage/PaceLoginPage.tsx +27 -3
  177. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +61 -0
  178. package/src/components/PasswordChange/PasswordChangeForm.tsx +20 -13
  179. package/src/components/PublicLayout/PublicLayout.test.tsx +7 -3
  180. package/src/components/PublicLayout/PublicPageLayout.tsx +5 -8
  181. package/src/components/Select/Select.tsx +23 -21
  182. package/src/components/Select/types.ts +1 -1
  183. package/src/components/UserMenu/UserMenu.test.tsx +38 -6
  184. package/src/components/UserMenu/UserMenu.tsx +39 -34
  185. package/src/components/index.ts +3 -4
  186. package/src/eslint-rules/index.cjs +22 -0
  187. package/src/eslint-rules/rules/compliance.cjs +348 -0
  188. package/src/eslint-rules/rules/components.cjs +113 -0
  189. package/src/eslint-rules/rules/imports.cjs +102 -0
  190. package/src/eslint-rules/rules/rbac.cjs +790 -0
  191. package/src/eslint-rules/utils/helpers.cjs +42 -0
  192. package/src/eslint-rules/utils/manifest-loader.cjs +75 -0
  193. package/src/hooks/__tests__/hooks.integration.test.tsx +6 -8
  194. package/src/hooks/__tests__/useAppConfig.unit.test.ts +129 -67
  195. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +149 -67
  196. package/src/hooks/__tests__/usePublicEvent.test.ts +149 -79
  197. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +158 -109
  198. package/src/hooks/__tests__/useSessionDraft.test.ts +163 -0
  199. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +10 -5
  200. package/src/hooks/public/usePublicEvent.ts +62 -190
  201. package/src/hooks/public/usePublicEventLogo.test.ts +70 -17
  202. package/src/hooks/public/usePublicEventLogo.ts +19 -9
  203. package/src/hooks/useAppConfig.ts +26 -24
  204. package/src/hooks/useEventTheme.test.ts +211 -233
  205. package/src/hooks/useEventTheme.ts +19 -28
  206. package/src/hooks/useEvents.ts +11 -7
  207. package/src/hooks/useKeyboardShortcuts.ts +1 -1
  208. package/src/hooks/useOrganisationPermissions.ts +9 -11
  209. package/src/hooks/useOrganisations.ts +13 -7
  210. package/src/hooks/useQueryCache.ts +0 -1
  211. package/src/hooks/useSessionDraft.ts +380 -0
  212. package/src/hooks/useSessionRestoration.ts +3 -1
  213. package/src/icons/index.ts +27 -0
  214. package/src/index.ts +16 -1
  215. package/src/providers/OrganisationProvider.tsx +23 -14
  216. package/src/providers/services/EventServiceProvider.tsx +1 -24
  217. package/src/providers/services/UnifiedAuthProvider.tsx +5 -48
  218. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +3 -0
  219. package/src/rbac/README.md +20 -20
  220. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +7 -457
  221. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +33 -7
  222. package/src/rbac/adapters.tsx +7 -295
  223. package/src/rbac/api.test.ts +44 -56
  224. package/src/rbac/api.ts +10 -17
  225. package/src/rbac/cache-invalidation.ts +0 -1
  226. package/src/rbac/compliance/index.ts +10 -0
  227. package/src/rbac/compliance/pattern-detector.ts +553 -0
  228. package/src/rbac/compliance/runtime-compliance.ts +22 -0
  229. package/src/rbac/components/AccessDenied.tsx +150 -0
  230. package/src/rbac/components/NavigationGuard.tsx +12 -20
  231. package/src/rbac/components/PagePermissionGuard.tsx +4 -24
  232. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +21 -8
  233. package/src/rbac/components/index.ts +3 -41
  234. package/src/rbac/eslint-rules.js +1 -1
  235. package/src/rbac/hooks/index.ts +0 -3
  236. package/src/rbac/hooks/permissions/index.ts +0 -3
  237. package/src/rbac/hooks/permissions/useAccessLevel.ts +4 -8
  238. package/src/rbac/hooks/usePermissions.ts +0 -3
  239. package/src/rbac/hooks/useRBAC.test.ts +21 -3
  240. package/src/rbac/hooks/useRBAC.ts +4 -3
  241. package/src/rbac/hooks/useResolvedScope.test.ts +57 -47
  242. package/src/rbac/hooks/useResolvedScope.ts +58 -140
  243. package/src/rbac/hooks/useResourcePermissions.test.ts +241 -60
  244. package/src/rbac/hooks/useResourcePermissions.ts +182 -63
  245. package/src/rbac/hooks/useRoleManagement.test.ts +65 -22
  246. package/src/rbac/hooks/useRoleManagement.ts +147 -19
  247. package/src/rbac/hooks/useSecureSupabase.ts +4 -8
  248. package/src/rbac/index.ts +7 -9
  249. package/src/rbac/permissions.ts +17 -17
  250. package/src/rbac/utils/contextValidator.ts +45 -7
  251. package/src/services/AuthService.ts +132 -23
  252. package/src/services/EventService.ts +4 -97
  253. package/src/services/InactivityService.ts +155 -58
  254. package/src/services/OrganisationService.ts +7 -44
  255. package/src/services/__tests__/OrganisationService.test.ts +26 -8
  256. package/src/services/base/BaseService.ts +0 -3
  257. package/src/styles/core.css +4 -0
  258. package/src/types/database.generated.ts +4733 -3809
  259. package/src/utils/__tests__/organisationContext.unit.test.ts +9 -10
  260. package/src/utils/context/organisationContext.test.ts +13 -28
  261. package/src/utils/context/organisationContext.ts +21 -52
  262. package/src/utils/dynamic/dynamicUtils.ts +1 -1
  263. package/src/utils/file-reference/index.ts +39 -15
  264. package/src/utils/formatting/formatDateTime.test.ts +3 -2
  265. package/src/utils/formatting/formatTime.test.ts +3 -2
  266. package/src/utils/google-places/loadGoogleMapsScript.ts +29 -4
  267. package/src/utils/index.ts +4 -1
  268. package/src/utils/persistence/__tests__/keyDerivation.test.ts +135 -0
  269. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +123 -0
  270. package/src/utils/persistence/keyDerivation.ts +304 -0
  271. package/src/utils/persistence/sensitiveFieldDetection.ts +212 -0
  272. package/src/utils/security/secureStorage.ts +5 -5
  273. package/src/utils/storage/helpers.ts +3 -3
  274. package/src/utils/supabase/createBaseClient.ts +147 -0
  275. package/src/utils/timezone/timezone.test.ts +1 -2
  276. package/src/utils/timezone/timezone.ts +1 -1
  277. package/src/utils/validation/csrf.ts +4 -4
  278. package/cursor-rules/CHANGELOG.md +0 -119
  279. package/cursor-rules/README.md +0 -192
  280. package/dist/DataTable-E7YQZD7D.js +0 -175
  281. package/dist/DataTable-E7YQZD7D.js.map +0 -1
  282. package/dist/UnifiedAuthProvider-QPXO24B4.js +0 -18
  283. package/dist/UnifiedAuthProvider-QPXO24B4.js.map +0 -1
  284. package/dist/api-6LVZTHDS.js +0 -52
  285. package/dist/api-6LVZTHDS.js.map +0 -1
  286. package/dist/audit-V53FV5AG.js +0 -17
  287. package/dist/audit-V53FV5AG.js.map +0 -1
  288. package/dist/chunk-36LVWXB2.js +0 -227
  289. package/dist/chunk-36LVWXB2.js.map +0 -1
  290. package/dist/chunk-3LPHPB62.js.map +0 -1
  291. package/dist/chunk-5DRSZLL2.js.map +0 -1
  292. package/dist/chunk-5EC5MEWX.js.map +0 -1
  293. package/dist/chunk-63FOKYGO.js.map +0 -1
  294. package/dist/chunk-6SOIHG6Z.js.map +0 -1
  295. package/dist/chunk-7JPAB3T5.js.map +0 -1
  296. package/dist/chunk-ATKZM7RX.js +0 -2053
  297. package/dist/chunk-ATKZM7RX.js.map +0 -1
  298. package/dist/chunk-AVMLPIM7.js.map +0 -1
  299. package/dist/chunk-DGUM43GV.js.map +0 -1
  300. package/dist/chunk-E66EQZE6.js.map +0 -1
  301. package/dist/chunk-FFQEQTNW.js.map +0 -1
  302. package/dist/chunk-FMUCXFII.js.map +0 -1
  303. package/dist/chunk-G37KK66H.js.map +0 -1
  304. package/dist/chunk-I6DAQMWX.js.map +0 -1
  305. package/dist/chunk-J36DSWQK.js.map +0 -1
  306. package/dist/chunk-KQCRWDSA.js +0 -1
  307. package/dist/chunk-KQCRWDSA.js.map +0 -1
  308. package/dist/chunk-L4OXEN46.js.map +0 -1
  309. package/dist/chunk-LMC26NLJ.js +0 -84
  310. package/dist/chunk-LMC26NLJ.js.map +0 -1
  311. package/dist/chunk-M43Y4SSO.js.map +0 -1
  312. package/dist/chunk-M7MPQISP.js.map +0 -1
  313. package/dist/chunk-NN6WWZ5U.js.map +0 -1
  314. package/dist/chunk-OEWDTMG7.js.map +0 -1
  315. package/dist/chunk-PWLANIRT.js.map +0 -1
  316. package/dist/chunk-QXHPKYJV.js.map +0 -1
  317. package/dist/chunk-VBXEHIUJ.js.map +0 -1
  318. package/dist/chunk-YKRAFF5K.js.map +0 -1
  319. package/dist/chunk-ZSAAAMVR.js.map +0 -1
  320. package/dist/components.js.map +0 -1
  321. package/dist/contextValidator-OOPCLPZW.js +0 -9
  322. package/dist/contextValidator-OOPCLPZW.js.map +0 -1
  323. package/dist/eslint-rules/pace-core-compliance.cjs +0 -510
  324. package/dist/hooks.js.map +0 -1
  325. package/dist/index.js.map +0 -1
  326. package/dist/providers.js.map +0 -1
  327. package/dist/rbac/eslint-rules.js.map +0 -1
  328. package/dist/rbac/index.js.map +0 -1
  329. package/dist/styles/index.js.map +0 -1
  330. package/dist/theming/runtime.js.map +0 -1
  331. package/dist/types.js.map +0 -1
  332. package/dist/utils.js.map +0 -1
  333. package/docs/standards/01-architecture-standard.md +0 -44
  334. package/docs/standards/02-api-and-rpc-standard.md +0 -39
  335. package/docs/standards/03-component-standard.md +0 -32
  336. package/docs/standards/05-security-standard.md +0 -44
  337. package/docs/standards/06-testing-and-docs-standard.md +0 -29
  338. package/docs/standards/pace-core-compliance.md +0 -432
  339. package/scripts/audit/core/checks/accessibility.cjs +0 -197
  340. package/scripts/audit/core/checks/api-usage.cjs +0 -191
  341. package/scripts/audit/core/checks/bundle.cjs +0 -142
  342. package/scripts/audit/core/checks/compliance.cjs +0 -2706
  343. package/scripts/audit/core/checks/config.cjs +0 -54
  344. package/scripts/audit/core/checks/coverage.cjs +0 -84
  345. package/scripts/audit/core/checks/dependencies.cjs +0 -994
  346. package/scripts/audit/core/checks/documentation.cjs +0 -268
  347. package/scripts/audit/core/checks/environment.cjs +0 -116
  348. package/scripts/audit/core/checks/error-handling.cjs +0 -340
  349. package/scripts/audit/core/checks/forms.cjs +0 -172
  350. package/scripts/audit/core/checks/heuristics.cjs +0 -68
  351. package/scripts/audit/core/checks/hooks.cjs +0 -334
  352. package/scripts/audit/core/checks/imports.cjs +0 -244
  353. package/scripts/audit/core/checks/performance.cjs +0 -325
  354. package/scripts/audit/core/checks/routes.cjs +0 -117
  355. package/scripts/audit/core/checks/state.cjs +0 -130
  356. package/scripts/audit/core/checks/structure.cjs +0 -65
  357. package/scripts/audit/core/checks/style.cjs +0 -584
  358. package/scripts/audit/core/checks/testing.cjs +0 -122
  359. package/scripts/audit/core/checks/typescript.cjs +0 -61
  360. package/scripts/audit/core/scanner.cjs +0 -199
  361. package/scripts/audit/core/utils.cjs +0 -137
  362. package/scripts/audit/reporters/console.cjs +0 -151
  363. package/scripts/audit/reporters/json.cjs +0 -54
  364. package/scripts/audit/reporters/markdown.cjs +0 -124
  365. package/scripts/audit-consuming-app.cjs +0 -86
  366. package/src/eslint-rules/pace-core-compliance.cjs +0 -510
  367. package/src/eslint-rules/pace-core-compliance.js +0 -638
  368. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +0 -555
  369. package/src/rbac/components/EnhancedNavigationMenu.tsx +0 -293
  370. package/src/rbac/components/NavigationProvider.test.tsx +0 -481
  371. package/src/rbac/components/NavigationProvider.tsx +0 -345
  372. package/src/rbac/components/PagePermissionProvider.test.tsx +0 -476
  373. package/src/rbac/components/PagePermissionProvider.tsx +0 -279
  374. package/src/rbac/components/PermissionEnforcer.tsx +0 -312
  375. package/src/rbac/components/RoleBasedRouter.tsx +0 -440
  376. package/src/rbac/components/SecureDataProvider.test.tsx +0 -543
  377. package/src/rbac/components/SecureDataProvider.tsx +0 -339
  378. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +0 -620
  379. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +0 -726
  380. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +0 -661
  381. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +0 -881
  382. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +0 -783
  383. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +0 -645
  384. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +0 -659
  385. package/src/rbac/hooks/permissions/useCachedPermissions.ts +0 -79
  386. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +0 -90
  387. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +0 -90
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Shared helper functions for ESLint rules
3
+ * @package @jmruthers/pace-core
4
+ * @module ESLintRules/utils/helpers
5
+ */
6
+
7
+ // Helper function to get pace-core alternative for restricted imports
8
+ function getPaceCoreAlternative(importSource) {
9
+ const alternatives = {
10
+ '@radix-ui/react-avatar': '/components',
11
+ '@radix-ui/react-checkbox': '/components',
12
+ '@radix-ui/react-dialog': '/components',
13
+ '@radix-ui/react-label': '/components',
14
+ '@radix-ui/react-switch': '/components',
15
+ '@radix-ui/react-tabs': '/components',
16
+ '@radix-ui/react-toast': '/components',
17
+ '@radix-ui/react-tooltip': '/components',
18
+ 'react-day-picker': '/components',
19
+ '@tanstack/react-table': '/components',
20
+ 'react-hook-form': '/components',
21
+ 'zod': '/utils',
22
+ 'lucide-react': '/icons'
23
+ };
24
+
25
+ return alternatives[importSource] || '';
26
+ }
27
+
28
+ /**
29
+ * Check if a file is in the pace-core source directory
30
+ * @param {string} filename - The file path to check
31
+ * @returns {boolean} - True if the file is in packages/core/src
32
+ */
33
+ function isPaceCoreSourceFile(filename) {
34
+ // Check for both Unix and Windows path separators
35
+ return filename.includes('packages/core/src') || filename.includes('packages\\core\\src');
36
+ }
37
+
38
+ module.exports = {
39
+ getPaceCoreAlternative,
40
+ isPaceCoreSourceFile,
41
+ };
42
+
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Shared utility for loading core-usage-manifest.json
3
+ * @package @jmruthers/pace-core
4
+ * @module ESLintRules/utils/manifest-loader
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ // Load manifest data
11
+ let manifestData = null;
12
+ try {
13
+ const manifestPath = path.join(__dirname, '../../../core-usage-manifest.json');
14
+ if (fs.existsSync(manifestPath)) {
15
+ manifestData = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
16
+ }
17
+ } catch (error) {
18
+ // If manifest can't be loaded, rules will use hardcoded defaults
19
+ console.warn('Warning: Could not load core-usage-manifest.json, using defaults');
20
+ }
21
+
22
+ // Get restricted imports from manifest or use defaults
23
+ const getRestrictedImports = () => {
24
+ if (manifestData && manifestData.restrictedImports) {
25
+ return manifestData.restrictedImports;
26
+ }
27
+ // Fallback defaults
28
+ return [
29
+ { module: '@radix-ui/react-avatar', reason: 'Use Avatar component from pace-core instead' },
30
+ { module: '@radix-ui/react-checkbox', reason: 'Use Checkbox component from pace-core instead' },
31
+ { module: '@radix-ui/react-dialog', reason: 'Use Dialog component from pace-core instead' },
32
+ { module: '@radix-ui/react-label', reason: 'Use Label component from pace-core instead' },
33
+ { module: '@radix-ui/react-slot', reason: 'Use Button component from pace-core which handles slot composition' },
34
+ { module: '@radix-ui/react-switch', reason: 'Use Switch component from pace-core instead' },
35
+ { module: '@radix-ui/react-tabs', reason: 'Use Tabs component from pace-core instead' },
36
+ { module: '@radix-ui/react-toast', reason: 'Use Toast component and useToast hook from pace-core instead' },
37
+ { module: '@radix-ui/react-tooltip', reason: 'Use Tooltip component from pace-core instead' },
38
+ { module: 'react-day-picker', reason: 'Use Calendar component from pace-core instead' },
39
+ { module: '@tanstack/react-table', reason: 'Use DataTable component and related hooks from pace-core instead. DataTable wraps and standardizes table functionality' },
40
+ { module: 'react-hook-form', reason: 'Use Form component and useZodForm hook from pace-core instead' },
41
+ { module: 'zod', reason: 'Use validation utilities and schemas from pace-core instead. pace-core provides standardized validation helpers' }
42
+ ];
43
+ };
44
+
45
+ // Get pace-core components from manifest or use defaults
46
+ const getPaceCoreComponents = () => {
47
+ if (manifestData && manifestData.components) {
48
+ return manifestData.components;
49
+ }
50
+ return ['Button', 'Card', 'Dialog', 'Input', 'Form', 'Select', 'Alert', 'Badge', 'Checkbox', 'Switch', 'Textarea', 'Label', 'Table', 'DataTable', 'Toast', 'Tooltip', 'Tabs', 'Calendar', 'Avatar', 'Progress'];
51
+ };
52
+
53
+ // Get pace-core hooks from manifest or use defaults
54
+ const getPaceCoreHooks = () => {
55
+ if (manifestData && manifestData.hooks) {
56
+ return manifestData.hooks;
57
+ }
58
+ return ['useToast', 'useDebounce', 'useUnifiedAuth', 'useEvents', 'useOrganisations', 'useFileReference', 'useStorage', 'useZodForm', 'useRBAC', 'usePermissions'];
59
+ };
60
+
61
+ // Get pace-core utils from manifest or use defaults
62
+ const getPaceCoreUtils = () => {
63
+ if (manifestData && manifestData.utils) {
64
+ return manifestData.utils;
65
+ }
66
+ return ['formatDate', 'formatCurrency', 'formatNumber', 'formatTime', 'formatDateTime', 'cn', 'validateUserInput', 'sanitizeUserInput', 'hasPermission', 'getAppConfig'];
67
+ };
68
+
69
+ module.exports = {
70
+ getRestrictedImports,
71
+ getPaceCoreComponents,
72
+ getPaceCoreHooks,
73
+ getPaceCoreUtils,
74
+ };
75
+
@@ -433,15 +433,13 @@ describe('Hooks Integration', () => {
433
433
  });
434
434
 
435
435
  // Assert that onSubmit was called with the correct form data
436
+ // Note: Form component only passes data, not methods (react-hook-form behavior)
436
437
  await waitFor(() => {
437
- expect(mockOnSubmit).toHaveBeenCalledWith(
438
- {
439
- name: 'John Doe',
440
- email: 'john@example.com',
441
- age: 25,
442
- },
443
- expect.any(Object) // Form methods object
444
- );
438
+ expect(mockOnSubmit).toHaveBeenCalledWith({
439
+ name: 'John Doe',
440
+ email: 'john@example.com',
441
+ age: 25,
442
+ });
445
443
  });
446
444
  });
447
445
  });
@@ -2,18 +2,87 @@ import { renderHook } from '@testing-library/react';
2
2
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
3
3
  import React from 'react';
4
4
  import { useAppConfig } from '../useAppConfig';
5
+ import { UnifiedAuthContext } from '../../providers/services/UnifiedAuthProvider';
5
6
 
6
7
  // Declare mock functions
7
8
  const mockUseIsPublicPage = vi.fn();
8
9
  const mockUseUnifiedAuthFn = vi.fn();
9
10
 
10
- vi.mock('../../providers/services/UnifiedAuthProvider', () => {
11
- return {
12
- useUnifiedAuth: () => mockUseUnifiedAuthFn(),
13
- UnifiedAuthProvider: ({ children }: { children: React.ReactNode }) => React.createElement(React.Fragment, null, children),
14
- };
11
+ // Helper to create a minimal auth context value
12
+ const createAuthValue = (overrides: any = {}) => ({
13
+ appName: 'PACE',
14
+ user: null,
15
+ session: null,
16
+ isAuthenticated: false,
17
+ authLoading: false,
18
+ authError: null,
19
+ supabase: null,
20
+ appId: undefined,
21
+ selectedOrganisation: null,
22
+ selectedOrganisationId: null,
23
+ organisations: [],
24
+ userMemberships: [],
25
+ organisationLoading: false,
26
+ organisationError: null,
27
+ hasValidOrganisationContext: false,
28
+ isContextReady: false,
29
+ switchOrganisation: vi.fn(),
30
+ getUserRole: vi.fn(),
31
+ validateOrganisationAccess: vi.fn(),
32
+ refreshOrganisations: vi.fn(),
33
+ ensureOrganisationContext: vi.fn(),
34
+ isOrganisationSecure: vi.fn(),
35
+ getPrimaryOrganisation: vi.fn(),
36
+ events: [],
37
+ selectedEvent: null,
38
+ selectedEventId: null,
39
+ eventLoading: false,
40
+ eventError: null,
41
+ setSelectedEvent: vi.fn(),
42
+ refreshEvents: vi.fn(),
43
+ showInactivityWarning: false,
44
+ inactivityTimeRemaining: 0,
45
+ isIdle: false,
46
+ timeRemaining: 0,
47
+ showWarning: false,
48
+ isTracking: false,
49
+ resetActivity: vi.fn(),
50
+ startTracking: vi.fn(),
51
+ stopTracking: vi.fn(),
52
+ handleIdleLogout: vi.fn(),
53
+ handleStaySignedIn: vi.fn(),
54
+ handleSignOutNow: vi.fn(),
55
+ signIn: vi.fn(),
56
+ signUp: vi.fn(),
57
+ signOut: vi.fn(),
58
+ resetPassword: vi.fn(),
59
+ updatePassword: vi.fn(),
60
+ refreshSession: vi.fn(),
61
+ isLoading: false,
62
+ hasErrors: false,
63
+ sessionRestoration: {
64
+ isRestoring: false,
65
+ restorationComplete: false,
66
+ restorationError: null,
67
+ },
68
+ sessionRestorationTimedOut: false,
69
+ sessionRestorationTimeoutMs: 0,
70
+ ...overrides,
15
71
  });
16
72
 
73
+ // Helper to create a wrapper component that provides UnifiedAuthContext
74
+ const createAuthWrapper = (authValue: any) => {
75
+ return ({ children }: { children: React.ReactNode }) => {
76
+ return React.createElement(
77
+ UnifiedAuthContext.Provider,
78
+ {
79
+ value: authValue,
80
+ },
81
+ children
82
+ );
83
+ };
84
+ };
85
+
17
86
  vi.mock('../../components/PublicLayout/PublicPageProvider', async (importOriginal) => {
18
87
  const actual = await importOriginal<typeof import('../../components/PublicLayout/PublicPageProvider')>();
19
88
  return {
@@ -22,7 +91,6 @@ vi.mock('../../components/PublicLayout/PublicPageProvider', async (importOrigina
22
91
  };
23
92
  });
24
93
 
25
- import { useUnifiedAuth as actualUseUnifiedAuth } from '../../providers/services/UnifiedAuthProvider';
26
94
  import { useIsPublicPage as actualUseIsPublicPage } from '../../components/PublicLayout/PublicPageProvider';
27
95
  import { PublicPageContext } from '../../components/PublicLayout/PublicPageProvider';
28
96
 
@@ -31,25 +99,28 @@ describe('useAppConfig Hook', () => {
31
99
  const originalUseContext = React.useContext;
32
100
  const originalEnv = import.meta.env;
33
101
 
102
+ // Store the real UnifiedAuthContext for comparison
103
+ const realUnifiedAuthContext = UnifiedAuthContext;
104
+
34
105
  beforeEach(() => {
35
106
  // Set up the mocks to use our mock functions
36
107
  vi.mocked(actualUseIsPublicPage).mockImplementation(mockUseIsPublicPage);
37
108
 
38
- // Mock useContext to return undefined for PublicPageContext (no appName from context)
39
- // This ensures the hook falls back to env vars or default 'PACE'
109
+ // Mock useContext to return values for UnifiedAuthContext and PublicPageContext
110
+ // This ensures the hook gets the correct values
40
111
  vi.spyOn(React, 'useContext').mockImplementation((context) => {
41
- // Check if this is the PublicPageContext by comparing the context object
42
- // We can't directly compare, so we check if it's a context created by React.createContext
43
- if (context && typeof context === 'object' && 'Provider' in context && 'Consumer' in context) {
44
- // This is likely PublicPageContext - return undefined to simulate no provider
45
- try {
46
- // Try to access the context to see if it throws (no provider) or returns a value
47
- // If it's PublicPageContext and there's no provider, return undefined
48
- return undefined;
49
- } catch {
50
- return undefined;
51
- }
112
+ // Check if this is the UnifiedAuthContext (use the real one from the import)
113
+ if (context === realUnifiedAuthContext) {
114
+ // Return the value from mockUseUnifiedAuthFn if it's set, otherwise return null
115
+ const mockValue = mockUseUnifiedAuthFn();
116
+ return mockValue !== undefined ? mockValue : null;
117
+ }
118
+ // Check if this is the PublicPageContext
119
+ if (context === PublicPageContext) {
120
+ // Return undefined to simulate no provider
121
+ return undefined;
52
122
  }
123
+ // For other contexts, use original implementation
53
124
  return originalUseContext(context);
54
125
  });
55
126
 
@@ -136,21 +207,23 @@ describe('useAppConfig Hook', () => {
136
207
 
137
208
  it('should return configuration from UnifiedAuthProvider when available', () => {
138
209
  const mockAppName = 'AuthApp';
210
+
211
+ // Ensure we're not in public page mode
212
+ mockUseIsPublicPage.mockReturnValue(false);
139
213
 
140
- mockUseUnifiedAuthFn.mockReturnValue({
141
- appName: mockAppName,
142
- } as any);
143
-
144
- const { result } = renderHook(() => useAppConfig());
214
+ // Use wrapper to provide UnifiedAuthContext
215
+ const authValue = createAuthValue({ appName: mockAppName });
216
+ const wrapper = createAuthWrapper(authValue);
217
+ const { result } = renderHook(() => useAppConfig(), { wrapper });
145
218
 
146
219
  expect(result.current.isLoading).toBe(false);
147
220
  expect(result.current.appName).toBe('AuthApp');
148
221
  });
149
222
 
150
223
  it('should handle UnifiedAuthProvider error and return fallback', () => {
151
- mockUseUnifiedAuthFn.mockImplementation(() => {
152
- throw new Error('Provider not available');
153
- });
224
+ // Since useAppConfig now uses useContext directly, missing provider returns null
225
+ // Mock useContext to return null for UnifiedAuthContext (simulating missing provider)
226
+ mockUseUnifiedAuthFn.mockReturnValue(null as any);
154
227
 
155
228
  const { result } = renderHook(() => useAppConfig());
156
229
 
@@ -159,9 +232,9 @@ describe('useAppConfig Hook', () => {
159
232
  });
160
233
 
161
234
  it('should handle different types of errors from UnifiedAuthProvider', () => {
162
- mockUseUnifiedAuthFn.mockImplementation(() => {
163
- throw new Error('Network error');
164
- });
235
+ // Since useAppConfig now uses useContext directly, missing provider returns null
236
+ // Mock useContext to return null for UnifiedAuthContext (simulating missing provider)
237
+ mockUseUnifiedAuthFn.mockReturnValue(null as any);
165
238
 
166
239
  const { result } = renderHook(() => useAppConfig());
167
240
 
@@ -170,9 +243,9 @@ describe('useAppConfig Hook', () => {
170
243
  });
171
244
 
172
245
  it('should handle non-Error exceptions from UnifiedAuthProvider', () => {
173
- mockUseUnifiedAuthFn.mockImplementation(() => {
174
- throw 'String error';
175
- });
246
+ // Since useAppConfig now uses useContext directly, missing provider returns null
247
+ // Mock useContext to return null for UnifiedAuthContext (simulating missing provider)
248
+ mockUseUnifiedAuthFn.mockReturnValue(null as any);
176
249
 
177
250
  const { result } = renderHook(() => useAppConfig());
178
251
 
@@ -197,52 +270,43 @@ describe('useAppConfig Hook', () => {
197
270
  it('should memoize authenticated configuration based on dependencies', () => {
198
271
  mockUseIsPublicPage.mockReturnValue(false);
199
272
 
200
- const mockAppName = 'TestApp';
201
-
202
- mockUseUnifiedAuthFn.mockReturnValue({
203
- appName: mockAppName,
204
- } as any);
205
-
206
- const { result, rerender } = renderHook(() => useAppConfig());
273
+ const authValue1 = createAuthValue({ appName: 'TestApp' });
274
+ const wrapper1 = createAuthWrapper(authValue1);
275
+ const { result, rerender } = renderHook(() => useAppConfig(), { wrapper: wrapper1 });
207
276
 
208
277
  const firstResult = result.current;
278
+ expect(firstResult.appName).toBe('TestApp');
209
279
 
210
280
  // Rerender with same props
211
281
  rerender();
212
-
213
282
  expect(result.current).toBe(firstResult);
214
283
 
215
- // Rerender with different appName
216
- mockUseUnifiedAuthFn.mockReturnValue({
217
- appName: 'DifferentApp',
218
- } as any);
284
+ // Rerender with different appName - need new wrapper with new value
285
+ const authValue2 = createAuthValue({ appName: 'DifferentApp' });
286
+ const wrapper2 = createAuthWrapper(authValue2);
287
+ const { result: result2 } = renderHook(() => useAppConfig(), { wrapper: wrapper2 });
219
288
 
220
- rerender();
221
-
222
- expect(result.current).not.toBe(firstResult);
223
- expect(result.current.appName).toBe('DifferentApp');
289
+ expect(result2.current).not.toBe(firstResult);
290
+ expect(result2.current.appName).toBe('DifferentApp');
224
291
  });
225
292
 
226
293
  it('should memoize authenticated configuration based on appName changes', () => {
227
294
  mockUseIsPublicPage.mockReturnValue(false);
228
295
 
229
- mockUseUnifiedAuthFn.mockReturnValue({
230
- appName: 'App1',
231
- } as any);
232
-
233
- const { result, rerender } = renderHook(() => useAppConfig());
296
+ const authValue1 = createAuthValue({ appName: 'App1' });
297
+ const wrapper1 = createAuthWrapper(authValue1);
298
+ const { result, rerender } = renderHook(() => useAppConfig(), { wrapper: wrapper1 });
234
299
 
235
300
  const firstResult = result.current;
301
+ expect(firstResult.appName).toBe('App1');
236
302
 
237
- // Rerender with different appName
238
- mockUseUnifiedAuthFn.mockReturnValue({
239
- appName: 'App2',
240
- } as any);
303
+ // Rerender with different appName - need new wrapper with new value
304
+ const authValue2 = createAuthValue({ appName: 'App2' });
305
+ const wrapper2 = createAuthWrapper(authValue2);
306
+ const { result: result2 } = renderHook(() => useAppConfig(), { wrapper: wrapper2 });
241
307
 
242
- rerender();
243
-
244
- expect(result.current).not.toBe(firstResult);
245
- expect(result.current.appName).toBe('App2');
308
+ expect(result2.current).not.toBe(firstResult);
309
+ expect(result2.current.appName).toBe('App2');
246
310
  });
247
311
  });
248
312
 
@@ -259,11 +323,9 @@ describe('useAppConfig Hook', () => {
259
323
 
260
324
  // Test authenticated page context separately
261
325
  mockUseIsPublicPage.mockReturnValue(false);
262
- mockUseUnifiedAuthFn.mockReturnValue({
263
- appName: 'AuthApp',
264
- } as any);
265
-
266
- const { result: authResult } = renderHook(() => useAppConfig());
326
+ const authValue = createAuthValue({ appName: 'AuthApp' });
327
+ const authWrapper = createAuthWrapper(authValue);
328
+ const { result: authResult } = renderHook(() => useAppConfig(), { wrapper: authWrapper });
267
329
 
268
330
  expect(authResult.current.appName).toBe('AuthApp');
269
331
  });