@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
@@ -77,21 +77,21 @@ const DebouncedSearch = () => {
77
77
  }, [debouncedSearchTerm]);
78
78
 
79
79
  return (
80
- <div>
80
+ <section>
81
81
  <Input
82
82
  data-testid="search-input"
83
83
  value={searchTerm}
84
84
  onChange={(e) => setSearchTerm(e.target.value)}
85
85
  placeholder="Search..."
86
86
  />
87
- <div data-testid="search-term">Current: {searchTerm}</div>
88
- <div data-testid="debounced-term">Debounced: {debouncedSearchTerm}</div>
89
- <div data-testid="results">
87
+ <p data-testid="search-term">Current: {searchTerm}</p>
88
+ <p data-testid="debounced-term">Debounced: {debouncedSearchTerm}</p>
89
+ <section data-testid="results">
90
90
  {searchResults.map((result, index) => (
91
- <div key={index} data-testid={`result-${index}`}>{result}</div>
91
+ <p key={index} data-testid={`result-${index}`}>{result}</p>
92
92
  ))}
93
- </div>
94
- </div>
93
+ </section>
94
+ </section>
95
95
  );
96
96
  };
97
97
 
@@ -100,17 +100,17 @@ const ResponsiveComponent = () => {
100
100
  const isMobile = useIsMobile();
101
101
 
102
102
  return (
103
- <div>
104
- <div data-testid="device-type">
103
+ <section>
104
+ <p data-testid="device-type">
105
105
  {isMobile ? 'Mobile' : 'Desktop'}
106
- </div>
106
+ </p>
107
107
  <Button
108
108
  data-testid="responsive-button"
109
109
  className={isMobile ? 'mobile-button' : 'desktop-button'}
110
110
  >
111
111
  {isMobile ? 'Mobile Action' : 'Desktop Action'}
112
112
  </Button>
113
- </div>
113
+ </section>
114
114
  );
115
115
  };
116
116
 
@@ -138,7 +138,7 @@ const ValidatedForm = ({ onSubmit }: ValidatedFormProps = {}) => {
138
138
  onSubmit={handleSubmit}
139
139
  >
140
140
  {(methods) => (
141
- <ValidatedFormFields methods={methods} />
141
+ <ValidatedFormFields methods={methods as any} />
142
142
  )}
143
143
  </Form>
144
144
  );
@@ -151,27 +151,27 @@ const ValidatedFormFields = ({ methods }: { methods: ReturnType<typeof useForm>
151
151
 
152
152
  return (
153
153
  <>
154
- <div>
154
+ <section>
155
155
  <Input
156
156
  {...methods.register('name')}
157
157
  data-testid="name-input"
158
158
  placeholder="Name"
159
159
  />
160
160
  {errors.name && (
161
- <div data-testid="name-error">{errors.name.message}</div>
161
+ <p data-testid="name-error">{String(errors.name.message)}</p>
162
162
  )}
163
- </div>
164
- <div>
163
+ </section>
164
+ <section>
165
165
  <Input
166
166
  {...methods.register('email')}
167
167
  data-testid="email-input"
168
168
  placeholder="Email"
169
169
  />
170
170
  {errors.email && (
171
- <div data-testid="email-error">{errors.email.message}</div>
171
+ <p data-testid="email-error">{String(errors.email.message)}</p>
172
172
  )}
173
- </div>
174
- <div>
173
+ </section>
174
+ <section>
175
175
  <Input
176
176
  {...methods.register('age', { valueAsNumber: true })}
177
177
  data-testid="age-input"
@@ -179,9 +179,9 @@ const ValidatedFormFields = ({ methods }: { methods: ReturnType<typeof useForm>
179
179
  placeholder="Age"
180
180
  />
181
181
  {errors.age && (
182
- <div data-testid="age-error">{errors.age.message}</div>
182
+ <p data-testid="age-error">{String(errors.age.message)}</p>
183
183
  )}
184
- </div>
184
+ </section>
185
185
  <Button type="submit" data-testid="submit-button">
186
186
  Submit
187
187
  </Button>
@@ -211,20 +211,20 @@ const KeyboardShortcutsComponent = () => {
211
211
  useKeyboardShortcuts(shortcuts);
212
212
 
213
213
  return (
214
- <div>
214
+ <section>
215
215
  <Button onClick={() => setIsModalOpen(true)} data-testid="open-modal">
216
216
  Open Modal
217
217
  </Button>
218
218
  {isModalOpen && (
219
- <div data-testid="modal">
220
- <div>Modal Content</div>
219
+ <section data-testid="modal">
220
+ <p>Modal Content</p>
221
221
  <Button onClick={() => setIsModalOpen(false)} data-testid="close-modal">
222
222
  Close
223
223
  </Button>
224
- </div>
224
+ </section>
225
225
  )}
226
- <div data-testid="saved-status">{savedData}</div>
227
- </div>
226
+ <p data-testid="saved-status">{savedData}</p>
227
+ </section>
228
228
  );
229
229
  };
230
230
 
@@ -238,13 +238,13 @@ const FocusManagementComponent = () => {
238
238
  });
239
239
 
240
240
  return (
241
- <div ref={focusManager.containerRef}>
241
+ <section ref={focusManager.containerRef}>
242
242
  <Button data-testid="first-button">First Button</Button>
243
243
  <Input data-testid="first-input" placeholder="First Input" />
244
244
  <Button data-testid="second-button">Second Button</Button>
245
245
  <Input data-testid="second-input" placeholder="Second Input" />
246
246
  <Button data-testid="last-button">Last Button</Button>
247
- </div>
247
+ </section>
248
248
  );
249
249
  };
250
250
 
@@ -257,10 +257,10 @@ const PerformanceTestComponent = () => {
257
257
  });
258
258
 
259
259
  return (
260
- <div data-testid="performance-component">
260
+ <section data-testid="performance-component">
261
261
  <h1>Performance Test Component</h1>
262
262
  <p>This component is being monitored for performance.</p>
263
- </div>
263
+ </section>
264
264
  );
265
265
  };
266
266
 
@@ -269,19 +269,19 @@ const DataTableStateComponent = () => {
269
269
  const tableState = useDataTableState({ initialPageSize: 10, data: [] });
270
270
 
271
271
  return (
272
- <div>
273
- <div data-testid="sorting-state">
272
+ <section>
273
+ <p data-testid="sorting-state">
274
274
  Sorting: {JSON.stringify(tableState.state.sorting)}
275
- </div>
276
- <div data-testid="filters-state">
275
+ </p>
276
+ <p data-testid="filters-state">
277
277
  Filters: {JSON.stringify(tableState.state.columnFilters)}
278
- </div>
279
- <div data-testid="page-state">
278
+ </p>
279
+ <p data-testid="page-state">
280
280
  Page: {tableState.state.pageIndex + 1} of {Math.ceil(100 / tableState.state.pageSize)}
281
- </div>
282
- <div data-testid="selected-rows">
281
+ </p>
282
+ <p data-testid="selected-rows">
283
283
  Selected: {tableState.state.selectedRows.length} rows
284
- </div>
284
+ </p>
285
285
  <Button
286
286
  onClick={() => tableState.actions.setSorting([{ id: 'name', desc: false }])}
287
287
  data-testid="sort-name"
@@ -294,7 +294,7 @@ const DataTableStateComponent = () => {
294
294
  >
295
295
  Filter Active
296
296
  </Button>
297
- </div>
297
+ </section>
298
298
  );
299
299
  };
300
300
 
@@ -332,7 +332,7 @@ describe('Hooks Integration', () => {
332
332
  await user.type(searchInput, 'abc');
333
333
 
334
334
  // Should not show results immediately
335
- expect(screen.queryByTestId('result-0')).not.toBeInTheDocument();
335
+ expect(screen.queryByTestId('result-0')).toBeNull();
336
336
 
337
337
  // Wait for final debounced value
338
338
  await waitFor(() => {
@@ -402,11 +402,11 @@ describe('Hooks Integration', () => {
402
402
  const emailError = screen.queryByTestId('email-error');
403
403
  const ageError = screen.queryByTestId('age-error');
404
404
 
405
- expect(nameError).toBeInTheDocument();
405
+ expect(nameError).toBeDefined();
406
406
  expect(nameError).toHaveTextContent('Name must be at least 2 characters');
407
- expect(emailError).toBeInTheDocument();
407
+ expect(emailError).toBeDefined();
408
408
  expect(emailError).toHaveTextContent('Invalid email address');
409
- expect(ageError).toBeInTheDocument();
409
+ expect(ageError).toBeDefined();
410
410
  expect(ageError).toHaveTextContent('Must be at least 18 years old');
411
411
  }, { timeout: 5000 });
412
412
  });
@@ -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
  });
@@ -453,13 +451,13 @@ describe('Hooks Integration', () => {
453
451
  const openButton = screen.getByTestId('open-modal');
454
452
  fireEvent.click(openButton);
455
453
 
456
- expect(screen.getByTestId('modal')).toBeInTheDocument();
454
+ expect(screen.getByTestId('modal')).toBeDefined();
457
455
 
458
456
  // Test Escape key
459
457
  fireEvent.keyDown(document, { key: 'Escape' });
460
458
 
461
459
  await waitFor(() => {
462
- expect(screen.queryByTestId('modal')).not.toBeInTheDocument();
460
+ expect(screen.queryByTestId('modal')).toBeNull();
463
461
  });
464
462
  });
465
463
 
@@ -514,7 +512,7 @@ describe('Hooks Integration', () => {
514
512
 
515
513
  renderWithProviders(<PerformanceTestComponent />);
516
514
 
517
- expect(screen.getByTestId('performance-component')).toBeInTheDocument();
515
+ expect(screen.getByTestId('performance-component')).toBeDefined();
518
516
 
519
517
  // Simulate slow render
520
518
  mockPerformance.now.mockReturnValueOnce(0);
@@ -531,7 +529,7 @@ describe('Hooks Integration', () => {
531
529
  // Note: This test may need to be updated based on how useComponentPerformance is used
532
530
  // The Logger mock should be checked if logging is enabled
533
531
  // For now, we verify the component renders without errors
534
- expect(screen.getByTestId('performance-component')).toBeInTheDocument();
532
+ expect(screen.getByTestId('performance-component')).toBeDefined();
535
533
  });
536
534
  });
537
535
 
@@ -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
  });