@jmruthers/pace-core 0.5.193 → 0.6.2

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 (577) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +7 -1
  3. package/cursor-rules/00-pace-core-compliance.mdc +299 -0
  4. package/cursor-rules/01-standards-compliance.mdc +244 -0
  5. package/cursor-rules/02-project-structure.mdc +200 -0
  6. package/cursor-rules/03-solid-principles.mdc +222 -0
  7. package/cursor-rules/04-testing-standards.mdc +268 -0
  8. package/cursor-rules/05-bug-reports-and-features.mdc +246 -0
  9. package/cursor-rules/06-code-quality.mdc +309 -0
  10. package/cursor-rules/07-tech-stack-compliance.mdc +214 -0
  11. package/cursor-rules/08-markup-quality.mdc +452 -0
  12. package/cursor-rules/CHANGELOG.md +119 -0
  13. package/cursor-rules/README.md +192 -0
  14. package/dist/{AuthService-DjnJHDtC.d.ts → AuthService-BPvc3Ka0.d.ts} +54 -0
  15. package/dist/{DataTable-Be6dH_dR.d.ts → DataTable-BMRU8a1j.d.ts} +34 -2
  16. package/dist/{DataTable-5FU7IESH.js → DataTable-TPTKCX4D.js} +10 -9
  17. package/dist/{PublicPageProvider-C0Sm_e5k.d.ts → PublicPageProvider-DC6kCaqf.d.ts} +385 -261
  18. package/dist/{UnifiedAuthProvider-RGJTDE2C.js → UnifiedAuthProvider-CH6Z342H.js} +3 -3
  19. package/dist/{UnifiedAuthProvider-185Ih4dj.d.ts → UnifiedAuthProvider-CVcTjx-d.d.ts} +29 -0
  20. package/dist/{api-N774RPUA.js → api-MVVQZLJI.js} +2 -2
  21. package/dist/{chunk-KNC55RTG.js → chunk-24UVZUZG.js} +90 -54
  22. package/dist/chunk-24UVZUZG.js.map +1 -0
  23. package/dist/{chunk-HWIIPPNI.js → chunk-2UOI2FG5.js} +20 -20
  24. package/dist/chunk-2UOI2FG5.js.map +1 -0
  25. package/dist/{chunk-E3SPN4VZ 5.js → chunk-3XC4CPTD.js} +4345 -3986
  26. package/dist/chunk-3XC4CPTD.js.map +1 -0
  27. package/dist/{chunk-7EQTDTTJ.js → chunk-6J4GEEJR.js} +172 -45
  28. package/dist/chunk-6J4GEEJR.js.map +1 -0
  29. package/dist/{chunk-6C4YBBJM 5.js → chunk-6SOIHG6Z.js} +1 -1
  30. package/dist/chunk-6SOIHG6Z.js.map +1 -0
  31. package/dist/{chunk-7FLMSG37.js → chunk-EHMR7VYL.js} +25 -25
  32. package/dist/chunk-EHMR7VYL.js.map +1 -0
  33. package/dist/{chunk-I7PSE6JW.js → chunk-F2IMUDXZ.js} +2 -75
  34. package/dist/chunk-F2IMUDXZ.js.map +1 -0
  35. package/dist/{chunk-QWWZ5CAQ.js → chunk-FFQEQTNW.js} +7 -9
  36. package/dist/chunk-FFQEQTNW.js.map +1 -0
  37. package/dist/chunk-FMUCXFII.js +76 -0
  38. package/dist/chunk-FMUCXFII.js.map +1 -0
  39. package/dist/{chunk-HW3OVDUF.js → chunk-J36DSWQK.js} +1 -1
  40. package/dist/{chunk-HW3OVDUF.js.map → chunk-J36DSWQK.js.map} +1 -1
  41. package/dist/{chunk-SQGMNID3.js → chunk-L4OXEN46.js} +4 -5
  42. package/dist/chunk-L4OXEN46.js.map +1 -0
  43. package/dist/{chunk-R77UEZ4E 3.js → chunk-M43Y4SSO.js} +1 -1
  44. package/dist/chunk-M43Y4SSO.js.map +1 -0
  45. package/dist/{chunk-IIELH4DL.js → chunk-MMZ7JXPU.js} +60 -223
  46. package/dist/chunk-MMZ7JXPU.js.map +1 -0
  47. package/dist/{chunk-NOAYCWCX 5.js → chunk-NECFR5MM.js} +394 -312
  48. package/dist/chunk-NECFR5MM.js.map +1 -0
  49. package/dist/{chunk-BC4IJKSL.js → chunk-SFZUDBL5.js} +40 -4
  50. package/dist/chunk-SFZUDBL5.js.map +1 -0
  51. package/dist/{chunk-XNXXZ43G.js → chunk-XWQCNGTQ.js} +748 -364
  52. package/dist/chunk-XWQCNGTQ.js.map +1 -0
  53. package/dist/components.d.ts +6 -6
  54. package/dist/components.js +15 -12
  55. package/dist/components.js.map +1 -1
  56. package/dist/{functions-D_kgHktt.d.ts → functions-DHebl8-F.d.ts} +1 -1
  57. package/dist/hooks.d.ts +59 -126
  58. package/dist/hooks.js +19 -28
  59. package/dist/hooks.js.map +1 -1
  60. package/dist/index.d.ts +63 -16
  61. package/dist/index.js +23 -24
  62. package/dist/index.js.map +1 -1
  63. package/dist/providers.d.ts +21 -3
  64. package/dist/providers.js +2 -2
  65. package/dist/rbac/index.d.ts +146 -115
  66. package/dist/rbac/index.js +8 -11
  67. package/dist/theming/runtime.d.ts +1 -13
  68. package/dist/theming/runtime.js +1 -1
  69. package/dist/{timezone-_pgH8qrY.d.ts → timezone-CHhWg6b4.d.ts} +3 -10
  70. package/dist/{types-UU913iLA.d.ts → types-BeoeWV5I.d.ts} +8 -0
  71. package/dist/{types-CEpcvwwF.d.ts → types-CkbwOr4Y.d.ts} +6 -0
  72. package/dist/types.d.ts +2 -2
  73. package/dist/{usePublicRouteParams-TZe0gy-4.d.ts → usePublicRouteParams-1oMokgLF.d.ts} +34 -4
  74. package/dist/{useToast-C8gR5ir4.d.ts → useToast-AyaT-x7p.d.ts} +2 -2
  75. package/dist/utils.d.ts +4 -5
  76. package/dist/utils.js +15 -15
  77. package/dist/utils.js.map +1 -1
  78. package/docs/api/README.md +7 -1
  79. package/docs/api/classes/ColumnFactory.md +8 -8
  80. package/docs/api/classes/InvalidScopeError.md +4 -4
  81. package/docs/api/classes/Logger.md +1 -1
  82. package/docs/api/classes/MissingUserContextError.md +4 -4
  83. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  84. package/docs/api/classes/PermissionDeniedError.md +4 -4
  85. package/docs/api/classes/RBACAuditManager.md +1 -1
  86. package/docs/api/classes/RBACCache.md +1 -1
  87. package/docs/api/classes/RBACEngine.md +1 -1
  88. package/docs/api/classes/RBACError.md +4 -4
  89. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  90. package/docs/api/classes/SecureSupabaseClient.md +18 -15
  91. package/docs/api/classes/StorageUtils.md +1 -1
  92. package/docs/api/enums/FileCategory.md +1 -1
  93. package/docs/api/enums/LogLevel.md +1 -1
  94. package/docs/api/enums/RBACErrorCode.md +1 -1
  95. package/docs/api/enums/RPCFunction.md +1 -1
  96. package/docs/api/interfaces/AddressFieldProps.md +1 -1
  97. package/docs/api/interfaces/AddressFieldRef.md +1 -1
  98. package/docs/api/interfaces/AggregateConfig.md +4 -4
  99. package/docs/api/interfaces/AutocompleteOptions.md +1 -1
  100. package/docs/api/interfaces/AvatarProps.md +1 -1
  101. package/docs/api/interfaces/BadgeProps.md +9 -2
  102. package/docs/api/interfaces/ButtonProps.md +7 -4
  103. package/docs/api/interfaces/CalendarProps.md +8 -5
  104. package/docs/api/interfaces/CardProps.md +8 -5
  105. package/docs/api/interfaces/ColorPalette.md +1 -1
  106. package/docs/api/interfaces/ColorShade.md +1 -1
  107. package/docs/api/interfaces/ComplianceResult.md +1 -1
  108. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  109. package/docs/api/interfaces/DataRecord.md +1 -1
  110. package/docs/api/interfaces/DataTableAction.md +24 -21
  111. package/docs/api/interfaces/DataTableColumn.md +31 -31
  112. package/docs/api/interfaces/DataTableProps.md +1 -1
  113. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  114. package/docs/api/interfaces/DatabaseComplianceResult.md +1 -1
  115. package/docs/api/interfaces/DatabaseIssue.md +1 -1
  116. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  117. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  118. package/docs/api/interfaces/ErrorBoundaryProps.md +147 -0
  119. package/docs/api/interfaces/ErrorBoundaryProviderProps.md +36 -0
  120. package/docs/api/interfaces/ErrorBoundaryState.md +75 -0
  121. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  122. package/docs/api/interfaces/ExportColumn.md +1 -1
  123. package/docs/api/interfaces/ExportOptions.md +8 -8
  124. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  125. package/docs/api/interfaces/FileMetadata.md +1 -1
  126. package/docs/api/interfaces/FileReference.md +1 -1
  127. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  128. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  129. package/docs/api/interfaces/FileUploadProps.md +26 -23
  130. package/docs/api/interfaces/FooterProps.md +10 -8
  131. package/docs/api/interfaces/FormFieldProps.md +10 -10
  132. package/docs/api/interfaces/FormProps.md +1 -1
  133. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  134. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  135. package/docs/api/interfaces/InputProps.md +7 -4
  136. package/docs/api/interfaces/LabelProps.md +1 -1
  137. package/docs/api/interfaces/LoggerConfig.md +1 -1
  138. package/docs/api/interfaces/LoginFormProps.md +14 -11
  139. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  140. package/docs/api/interfaces/NavigationContextType.md +1 -1
  141. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  142. package/docs/api/interfaces/NavigationItem.md +11 -11
  143. package/docs/api/interfaces/NavigationMenuProps.md +15 -15
  144. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  145. package/docs/api/interfaces/Organisation.md +1 -1
  146. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  147. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  148. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  149. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  150. package/docs/api/interfaces/PaceAppLayoutProps.md +30 -27
  151. package/docs/api/interfaces/PaceLoginPageProps.md +6 -4
  152. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  153. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  154. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  155. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  156. package/docs/api/interfaces/PaletteData.md +1 -1
  157. package/docs/api/interfaces/ParsedAddress.md +1 -1
  158. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  159. package/docs/api/interfaces/ProgressProps.md +1 -1
  160. package/docs/api/interfaces/ProtectedRouteProps.md +7 -26
  161. package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
  162. package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
  163. package/docs/api/interfaces/PublicPageLayoutProps.md +7 -20
  164. package/docs/api/interfaces/QuickFix.md +1 -1
  165. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  166. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  167. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  168. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  169. package/docs/api/interfaces/RBACConfig.md +1 -1
  170. package/docs/api/interfaces/RBACContext.md +1 -1
  171. package/docs/api/interfaces/RBACLogger.md +1 -1
  172. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  173. package/docs/api/interfaces/RBACPerformanceMetrics.md +1 -1
  174. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  175. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  176. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  177. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  178. package/docs/api/interfaces/RBACResult.md +1 -1
  179. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  180. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  181. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  182. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  183. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  184. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  185. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  186. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  187. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  188. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  189. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  190. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  191. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  192. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  193. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  194. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  195. package/docs/api/interfaces/RouteConfig.md +1 -1
  196. package/docs/api/interfaces/RuntimeComplianceResult.md +1 -1
  197. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  198. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  199. package/docs/api/interfaces/SessionRestorationLoaderProps.md +3 -3
  200. package/docs/api/interfaces/SetupIssue.md +1 -1
  201. package/docs/api/interfaces/StorageConfig.md +1 -1
  202. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  203. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  204. package/docs/api/interfaces/StorageListOptions.md +1 -1
  205. package/docs/api/interfaces/StorageListResult.md +1 -1
  206. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  207. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  208. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  209. package/docs/api/interfaces/StyleImport.md +1 -1
  210. package/docs/api/interfaces/SwitchProps.md +1 -1
  211. package/docs/api/interfaces/TabsContentProps.md +1 -1
  212. package/docs/api/interfaces/TabsListProps.md +1 -1
  213. package/docs/api/interfaces/TabsProps.md +1 -1
  214. package/docs/api/interfaces/TabsTriggerProps.md +3 -3
  215. package/docs/api/interfaces/TextareaProps.md +1 -1
  216. package/docs/api/interfaces/ToastActionElement.md +4 -1
  217. package/docs/api/interfaces/ToastProps.md +1 -1
  218. package/docs/api/interfaces/UnifiedAuthContextType.md +58 -55
  219. package/docs/api/interfaces/UnifiedAuthProviderProps.md +15 -13
  220. package/docs/api/interfaces/UseFormDialogOptions.md +1 -1
  221. package/docs/api/interfaces/UseFormDialogReturn.md +1 -1
  222. package/docs/api/interfaces/UseInactivityTrackerOptions.md +11 -9
  223. package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
  224. package/docs/api/interfaces/UsePublicEventLogoOptions.md +6 -6
  225. package/docs/api/interfaces/UsePublicEventLogoReturn.md +9 -6
  226. package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
  227. package/docs/api/interfaces/UsePublicEventReturn.md +8 -5
  228. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
  229. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +12 -9
  230. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +10 -7
  231. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  232. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  233. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  234. package/docs/api/interfaces/UserEventAccess.md +14 -11
  235. package/docs/api/interfaces/UserMenuProps.md +8 -6
  236. package/docs/api/interfaces/UserProfile.md +1 -1
  237. package/docs/api/modules.md +575 -634
  238. package/docs/architecture/database-schema-requirements.md +161 -0
  239. package/docs/core-concepts/rbac-system.md +3 -3
  240. package/docs/documentation-index.md +2 -4
  241. package/docs/getting-started/cursor-rules.md +263 -0
  242. package/docs/getting-started/installation-guide.md +6 -1
  243. package/docs/getting-started/quick-start.md +6 -1
  244. package/docs/migration/DOCUMENTATION_STRUCTURE.md +441 -0
  245. package/docs/migration/MIGRATION_GUIDE.md +6 -28
  246. package/docs/migration/README.md +52 -6
  247. package/docs/migration/V0.5.190_TO_V0.6.1_MIGRATION.md +1153 -0
  248. package/docs/migration/V0.6.0_REACT_19_MIGRATION.md +227 -0
  249. package/docs/migration/database-changes-december-2025.md +3 -3
  250. package/docs/rbac/event-based-apps.md +1 -1
  251. package/docs/rbac/getting-started.md +1 -1
  252. package/docs/rbac/quick-start.md +1 -1
  253. package/docs/standards/README.md +40 -0
  254. package/docs/troubleshooting/migration.md +4 -4
  255. package/examples/PublicPages/PublicEventPage.tsx +1 -1
  256. package/package.json +12 -6
  257. package/scripts/audit/core/checks/accessibility.cjs +197 -0
  258. package/scripts/audit/core/checks/api-usage.cjs +191 -0
  259. package/scripts/audit/core/checks/bundle.cjs +142 -0
  260. package/scripts/{check-pace-core-compliance.cjs → audit/core/checks/compliance.cjs} +737 -691
  261. package/scripts/audit/core/checks/config.cjs +54 -0
  262. package/scripts/audit/core/checks/coverage.cjs +84 -0
  263. package/scripts/audit/core/checks/dependencies.cjs +454 -0
  264. package/scripts/audit/core/checks/documentation.cjs +203 -0
  265. package/scripts/audit/core/checks/environment.cjs +128 -0
  266. package/scripts/audit/core/checks/error-handling.cjs +299 -0
  267. package/scripts/audit/core/checks/forms.cjs +172 -0
  268. package/scripts/audit/core/checks/heuristics.cjs +68 -0
  269. package/scripts/audit/core/checks/hooks.cjs +334 -0
  270. package/scripts/audit/core/checks/imports.cjs +244 -0
  271. package/scripts/audit/core/checks/performance.cjs +325 -0
  272. package/scripts/audit/core/checks/routes.cjs +117 -0
  273. package/scripts/audit/core/checks/state.cjs +130 -0
  274. package/scripts/audit/core/checks/structure.cjs +65 -0
  275. package/scripts/audit/core/checks/style.cjs +584 -0
  276. package/scripts/audit/core/checks/testing.cjs +122 -0
  277. package/scripts/audit/core/checks/typescript.cjs +61 -0
  278. package/scripts/audit/core/scanner.cjs +199 -0
  279. package/scripts/audit/core/utils.cjs +137 -0
  280. package/scripts/audit/index.cjs +223 -0
  281. package/scripts/audit/reporters/console.cjs +151 -0
  282. package/scripts/audit/reporters/json.cjs +54 -0
  283. package/scripts/audit/reporters/markdown.cjs +124 -0
  284. package/scripts/audit-consuming-app.cjs +86 -0
  285. package/scripts/build-docs/build-decision.js +240 -0
  286. package/scripts/build-docs/cache-utils.js +105 -0
  287. package/scripts/build-docs/content-normalization.js +150 -0
  288. package/scripts/build-docs/file-utils.js +105 -0
  289. package/scripts/build-docs/git-utils.js +86 -0
  290. package/scripts/build-docs/hash-utils.js +116 -0
  291. package/scripts/build-docs/typedoc-runner.js +220 -0
  292. package/scripts/build-docs-incremental.js +77 -913
  293. package/scripts/install-cursor-rules.cjs +236 -0
  294. package/scripts/utils/command-runner.js +16 -11
  295. package/scripts/validate-formats.js +61 -56
  296. package/scripts/validate-master.js +74 -69
  297. package/scripts/validate-pre-publish.js +70 -65
  298. package/src/__tests__/helpers/test-providers.tsx +1 -1
  299. package/src/__tests__/helpers/test-utils.tsx +1 -1
  300. package/src/__tests__/hooks/usePermissions.test.ts +2 -2
  301. package/src/components/Alert/Alert.test.tsx +12 -18
  302. package/src/components/Alert/Alert.tsx +5 -7
  303. package/src/components/Avatar/Avatar.test.tsx +4 -4
  304. package/src/components/Badge/Badge.tsx +16 -4
  305. package/src/components/Button/Button.tsx +27 -4
  306. package/src/components/Calendar/Calendar.tsx +9 -3
  307. package/src/components/Card/Card.tsx +4 -0
  308. package/src/components/Checkbox/Checkbox.test.tsx +12 -12
  309. package/src/components/Checkbox/Checkbox.tsx +2 -2
  310. package/src/components/DataTable/DataTable.test.tsx +57 -93
  311. package/src/components/DataTable/DataTable.tsx +40 -6
  312. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +5 -6
  313. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +29 -7
  314. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +12 -12
  315. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +2 -3
  316. package/src/components/DataTable/components/AccessDeniedPage.tsx +17 -26
  317. package/src/components/DataTable/components/ActionButtons.tsx +10 -7
  318. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +2 -2
  319. package/src/components/DataTable/components/ColumnFilter.tsx +10 -0
  320. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +12 -0
  321. package/src/components/DataTable/components/DataTableBody.tsx +8 -0
  322. package/src/components/DataTable/components/DataTableCore.tsx +200 -561
  323. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +11 -0
  324. package/src/components/DataTable/components/DataTableLayout.tsx +559 -0
  325. package/src/components/DataTable/components/DataTableModals.tsx +9 -1
  326. package/src/components/DataTable/components/DataTableToolbar.tsx +8 -0
  327. package/src/components/DataTable/components/DraggableColumnHeader.tsx +12 -0
  328. package/src/components/DataTable/components/EditFields.tsx +307 -0
  329. package/src/components/DataTable/components/EditableRow.tsx +9 -1
  330. package/src/components/DataTable/components/EmptyState.tsx +10 -0
  331. package/src/components/DataTable/components/FilterRow.tsx +12 -0
  332. package/src/components/DataTable/components/GroupHeader.tsx +12 -0
  333. package/src/components/DataTable/components/GroupingDropdown.tsx +12 -0
  334. package/src/components/DataTable/components/ImportModal.tsx +7 -0
  335. package/src/components/DataTable/components/LoadingState.tsx +6 -0
  336. package/src/components/DataTable/components/PaginationControls.tsx +16 -1
  337. package/src/components/DataTable/components/RowComponent.tsx +391 -0
  338. package/src/components/DataTable/components/UnifiedTableBody.tsx +62 -852
  339. package/src/components/DataTable/components/VirtualizedDataTable.tsx +16 -4
  340. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +4 -2
  341. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +23 -23
  342. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +11 -11
  343. package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +36 -36
  344. package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +27 -27
  345. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +39 -39
  346. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +33 -33
  347. package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +29 -29
  348. package/src/components/DataTable/components/cellValueUtils.ts +40 -0
  349. package/src/components/DataTable/components/hooks/useImportModalFocus.ts +53 -0
  350. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +126 -0
  351. package/src/components/DataTable/context/DataTableContext.tsx +50 -0
  352. package/src/components/DataTable/core/ColumnFactory.ts +31 -0
  353. package/src/components/DataTable/core/DataTableContext.tsx +32 -1
  354. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +10 -0
  355. package/src/components/DataTable/hooks/useColumnReordering.ts +14 -2
  356. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +10 -0
  357. package/src/components/DataTable/hooks/useDataTableDataPipeline.ts +16 -0
  358. package/src/components/DataTable/hooks/useDataTablePermissions.ts +124 -32
  359. package/src/components/DataTable/hooks/useDataTableState.ts +35 -1
  360. package/src/components/DataTable/hooks/useEffectiveColumnOrder.ts +12 -0
  361. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +2 -2
  362. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +11 -0
  363. package/src/components/DataTable/hooks/useTableColumns.ts +8 -0
  364. package/src/components/DataTable/hooks/useTableHandlers.ts +14 -0
  365. package/src/components/DataTable/styles.ts +6 -6
  366. package/src/components/DataTable/types.ts +6 -10
  367. package/src/components/DataTable/utils/a11yUtils.ts +7 -0
  368. package/src/components/DataTable/utils/debugTools.ts +18 -113
  369. package/src/components/DataTable/utils/errorHandling.ts +12 -0
  370. package/src/components/DataTable/utils/exportUtils.ts +9 -0
  371. package/src/components/DataTable/utils/flexibleImport.ts +12 -48
  372. package/src/components/DataTable/utils/paginationUtils.ts +8 -0
  373. package/src/components/DataTable/utils/performanceUtils.ts +5 -1
  374. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +8 -14
  375. package/src/components/Dialog/Dialog.tsx +8 -7
  376. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +180 -1
  377. package/src/components/ErrorBoundary/ErrorBoundary.tsx +46 -6
  378. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +129 -0
  379. package/src/components/ErrorBoundary/index.ts +27 -2
  380. package/src/components/EventSelector/EventSelector.tsx +4 -1
  381. package/src/components/FileDisplay/FileDisplay.test.tsx +2 -2
  382. package/src/components/FileDisplay/FileDisplay.tsx +32 -18
  383. package/src/components/FileUpload/FileUpload.tsx +22 -2
  384. package/src/components/Footer/Footer.test.tsx +16 -16
  385. package/src/components/Footer/Footer.tsx +15 -12
  386. package/src/components/Form/Form.test.tsx +36 -15
  387. package/src/components/Form/Form.tsx +31 -26
  388. package/src/components/Header/Header.tsx +22 -11
  389. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +40 -40
  390. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +1 -1
  391. package/src/components/Input/Input.test.tsx +2 -2
  392. package/src/components/Input/Input.tsx +36 -34
  393. package/src/components/Label/Label.tsx +1 -1
  394. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +4 -4
  395. package/src/components/LoadingSpinner/LoadingSpinner.tsx +1 -1
  396. package/src/components/LoginForm/LoginForm.test.tsx +42 -42
  397. package/src/components/LoginForm/LoginForm.tsx +12 -8
  398. package/src/components/NavigationMenu/NavigationMenu.tsx +15 -514
  399. package/src/components/NavigationMenu/types.ts +56 -0
  400. package/src/components/NavigationMenu/useNavigationFiltering.ts +390 -0
  401. package/src/components/OrganisationSelector/OrganisationSelector.tsx +3 -0
  402. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +1 -1
  403. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +54 -52
  404. package/src/components/PaceAppLayout/PaceAppLayout.tsx +33 -12
  405. package/src/components/PaceAppLayout/README.md +1 -1
  406. package/src/components/PaceAppLayout/test-setup.tsx +1 -2
  407. package/src/components/PaceLoginPage/PaceLoginPage.tsx +4 -1
  408. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +33 -33
  409. package/src/components/PasswordChange/PasswordChangeForm.tsx +10 -1
  410. package/src/components/Progress/Progress.tsx +1 -1
  411. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -9
  412. package/src/components/PublicLayout/PublicPageLayout.tsx +3 -6
  413. package/src/components/PublicLayout/PublicPageProvider.tsx +4 -0
  414. package/src/components/Select/Select.tsx +95 -438
  415. package/src/components/Select/context.ts +23 -0
  416. package/src/components/Select/hooks/useSelectEvents.ts +87 -0
  417. package/src/components/Select/hooks/useSelectSearch.ts +91 -0
  418. package/src/components/Select/hooks/useSelectState.ts +104 -0
  419. package/src/components/Select/index.ts +9 -1
  420. package/src/components/Select/types.ts +123 -0
  421. package/src/components/Select/utils/text.ts +26 -0
  422. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +5 -6
  423. package/src/components/Switch/Switch.tsx +4 -4
  424. package/src/components/Table/Table.tsx +1 -1
  425. package/src/components/Tabs/Tabs.tsx +1 -1
  426. package/src/components/Textarea/Textarea.tsx +27 -29
  427. package/src/components/Toast/Toast.tsx +5 -1
  428. package/src/components/Tooltip/Tooltip.tsx +3 -3
  429. package/src/components/UserMenu/UserMenu.test.tsx +24 -11
  430. package/src/components/UserMenu/UserMenu.tsx +22 -19
  431. package/src/components/index.ts +2 -2
  432. package/src/hooks/__tests__/hooks.integration.test.tsx +80 -55
  433. package/src/hooks/__tests__/index.unit.test.ts +2 -5
  434. package/src/hooks/__tests__/useStorage.unit.test.ts +36 -36
  435. package/src/hooks/index.ts +1 -2
  436. package/src/hooks/public/usePublicEvent.ts +5 -1
  437. package/src/hooks/public/usePublicEventLogo.ts +5 -1
  438. package/src/hooks/public/usePublicFileDisplay.ts +4 -0
  439. package/src/hooks/public/usePublicRouteParams.ts +5 -1
  440. package/src/hooks/services/useAuth.ts +32 -0
  441. package/src/hooks/services/useCurrentEvent.ts +6 -0
  442. package/src/hooks/services/useCurrentOrganisation.ts +6 -0
  443. package/src/hooks/useDataTableState.ts +8 -18
  444. package/src/hooks/useDebounce.ts +9 -0
  445. package/src/hooks/useEventTheme.ts +6 -0
  446. package/src/hooks/useFileDisplay.ts +4 -0
  447. package/src/hooks/useFileReference.ts +25 -7
  448. package/src/hooks/useFileUrl.ts +11 -1
  449. package/src/hooks/useFocusManagement.ts +16 -2
  450. package/src/hooks/useFocusTrap.ts +7 -4
  451. package/src/hooks/useFormDialog.ts +8 -7
  452. package/src/hooks/useInactivityTracker.ts +4 -1
  453. package/src/hooks/useKeyboardShortcuts.ts +4 -0
  454. package/src/hooks/useOrganisationPermissions.ts +4 -0
  455. package/src/hooks/useOrganisationSecurity.ts +4 -0
  456. package/src/hooks/usePerformanceMonitor.ts +4 -0
  457. package/src/hooks/usePermissionCache.ts +8 -1
  458. package/src/hooks/useQueryCache.ts +12 -1
  459. package/src/hooks/useSessionRestoration.ts +4 -0
  460. package/src/hooks/useStorage.ts +4 -0
  461. package/src/hooks/useToast.ts +3 -3
  462. package/src/index.ts +2 -1
  463. package/src/providers/__tests__/OrganisationProvider.test.tsx +115 -49
  464. package/src/providers/__tests__/ProviderLifecycle.test.tsx +21 -6
  465. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +10 -10
  466. package/src/providers/services/AuthServiceProvider.tsx +18 -0
  467. package/src/providers/services/EventServiceProvider.tsx +18 -0
  468. package/src/providers/services/InactivityServiceProvider.tsx +18 -0
  469. package/src/providers/services/OrganisationServiceProvider.tsx +18 -0
  470. package/src/providers/services/UnifiedAuthProvider.tsx +58 -22
  471. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +33 -7
  472. package/src/rbac/README.md +1 -1
  473. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +26 -26
  474. package/src/rbac/__tests__/scenarios.user-role.test.tsx +4 -5
  475. package/src/rbac/adapters.tsx +14 -5
  476. package/src/rbac/api.ts +100 -67
  477. package/src/rbac/components/EnhancedNavigationMenu.tsx +1 -1
  478. package/src/rbac/components/NavigationGuard.tsx +1 -1
  479. package/src/rbac/components/NavigationProvider.tsx +5 -2
  480. package/src/rbac/components/PagePermissionGuard.tsx +158 -18
  481. package/src/rbac/components/PagePermissionProvider.tsx +1 -1
  482. package/src/rbac/components/PermissionEnforcer.tsx +1 -1
  483. package/src/rbac/components/RoleBasedRouter.tsx +6 -2
  484. package/src/rbac/components/SecureDataProvider.test.tsx +84 -49
  485. package/src/rbac/components/SecureDataProvider.tsx +21 -6
  486. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +24 -14
  487. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +7 -0
  488. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -6
  489. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +15 -4
  490. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +148 -24
  491. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +81 -15
  492. package/src/rbac/engine.ts +38 -14
  493. package/src/rbac/hooks/permissions/index.ts +7 -0
  494. package/src/rbac/hooks/permissions/useAccessLevel.ts +105 -0
  495. package/src/rbac/hooks/permissions/useCachedPermissions.ts +79 -0
  496. package/src/rbac/hooks/permissions/useCan.ts +347 -0
  497. package/src/rbac/hooks/permissions/useHasAllPermissions.ts +90 -0
  498. package/src/rbac/hooks/permissions/useHasAnyPermission.ts +90 -0
  499. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +93 -0
  500. package/src/rbac/hooks/permissions/usePermissions.ts +253 -0
  501. package/src/rbac/hooks/useCan.test.ts +71 -64
  502. package/src/rbac/hooks/usePermissions.ts +14 -995
  503. package/src/rbac/hooks/useResourcePermissions.test.ts +54 -18
  504. package/src/rbac/hooks/useResourcePermissions.ts +14 -4
  505. package/src/rbac/hooks/useSecureSupabase.ts +33 -13
  506. package/src/rbac/permissions.ts +0 -30
  507. package/src/rbac/secureClient.ts +212 -61
  508. package/src/rbac/types.ts +8 -0
  509. package/src/theming/__tests__/parseEventColours.test.ts +6 -9
  510. package/src/theming/parseEventColours.ts +5 -19
  511. package/src/types/vitest-globals.d.ts +51 -26
  512. package/src/utils/__mocks__/supabaseMock.ts +1 -3
  513. package/src/utils/__tests__/formatting.unit.test.ts +4 -4
  514. package/src/utils/__tests__/index.unit.test.ts +2 -2
  515. package/src/utils/audit/audit.ts +0 -3
  516. package/src/utils/core/cn.ts +1 -1
  517. package/src/utils/file-reference/index.ts +53 -1
  518. package/src/utils/formatting/formatting.ts +8 -18
  519. package/src/utils/index.ts +0 -1
  520. package/src/utils/security/secureDataAccess.test.ts +31 -20
  521. package/src/utils/security/secureDataAccess.ts +4 -3
  522. package/dist/chunk-6C4YBBJM.js +0 -628
  523. package/dist/chunk-6C4YBBJM.js.map +0 -1
  524. package/dist/chunk-7D4SUZUM.js 2.map +0 -1
  525. package/dist/chunk-7EQTDTTJ.js 2.map +0 -1
  526. package/dist/chunk-7EQTDTTJ.js.map +0 -1
  527. package/dist/chunk-7FLMSG37.js 2.map +0 -1
  528. package/dist/chunk-7FLMSG37.js.map +0 -1
  529. package/dist/chunk-BC4IJKSL.js.map +0 -1
  530. package/dist/chunk-E3SPN4VZ.js +0 -12917
  531. package/dist/chunk-E3SPN4VZ.js.map +0 -1
  532. package/dist/chunk-E66EQZE6 5.js +0 -37
  533. package/dist/chunk-E66EQZE6.js 2.map +0 -1
  534. package/dist/chunk-HWIIPPNI.js.map +0 -1
  535. package/dist/chunk-I7PSE6JW 5.js +0 -191
  536. package/dist/chunk-I7PSE6JW.js 2.map +0 -1
  537. package/dist/chunk-I7PSE6JW.js.map +0 -1
  538. package/dist/chunk-IIELH4DL.js.map +0 -1
  539. package/dist/chunk-KNC55RTG.js 5.map +0 -1
  540. package/dist/chunk-KNC55RTG.js.map +0 -1
  541. package/dist/chunk-KQCRWDSA.js 5.map +0 -1
  542. package/dist/chunk-LFNCN2SP.js +0 -412
  543. package/dist/chunk-LFNCN2SP.js 2.map +0 -1
  544. package/dist/chunk-LFNCN2SP.js.map +0 -1
  545. package/dist/chunk-LMC26NLJ 2.js +0 -84
  546. package/dist/chunk-NOAYCWCX.js +0 -4993
  547. package/dist/chunk-NOAYCWCX.js.map +0 -1
  548. package/dist/chunk-QWWZ5CAQ.js 3.map +0 -1
  549. package/dist/chunk-QWWZ5CAQ.js.map +0 -1
  550. package/dist/chunk-QXHPKYJV 3.js +0 -113
  551. package/dist/chunk-R77UEZ4E.js +0 -68
  552. package/dist/chunk-R77UEZ4E.js.map +0 -1
  553. package/dist/chunk-SQGMNID3.js.map +0 -1
  554. package/dist/chunk-VBXEHIUJ.js 6.map +0 -1
  555. package/dist/chunk-XNXXZ43G.js.map +0 -1
  556. package/dist/chunk-ZSAAAMVR 6.js +0 -25
  557. package/dist/components.js 5.map +0 -1
  558. package/dist/styles/index 2.js +0 -12
  559. package/dist/styles/index.js 5.map +0 -1
  560. package/dist/theming/runtime 5.js +0 -19
  561. package/dist/theming/runtime.js 5.map +0 -1
  562. package/docs/api/classes/ErrorBoundary.md +0 -144
  563. package/docs/migration/quick-migration-guide.md +0 -356
  564. package/docs/migration/service-architecture.md +0 -281
  565. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +0 -680
  566. package/src/hooks/useSecureDataAccess.test.ts +0 -559
  567. package/src/hooks/useSecureDataAccess.ts +0 -666
  568. /package/dist/{DataTable-5FU7IESH.js.map → DataTable-TPTKCX4D.js.map} +0 -0
  569. /package/dist/{UnifiedAuthProvider-RGJTDE2C.js.map → UnifiedAuthProvider-CH6Z342H.js.map} +0 -0
  570. /package/dist/{api-N774RPUA.js.map → api-MVVQZLJI.js.map} +0 -0
  571. /package/docs/migration/{organisation-context-timing-fix.md → V0.3.44_organisation-context-timing-fix.md} +0 -0
  572. /package/docs/migration/{rbac-migration.md → V0.4.0_rbac-migration.md} +0 -0
  573. /package/docs/migration/{person-scoped-profiles-migration-guide.md → V0.5.190_person-scoped-profiles-migration-guide.md} +0 -0
  574. /package/examples/{rbac → RBAC}/CompleteRBACExample.tsx +0 -0
  575. /package/examples/{rbac → RBAC}/EventBasedApp.tsx +0 -0
  576. /package/examples/{rbac → RBAC}/PermissionExample.tsx +0 -0
  577. /package/examples/{rbac → RBAC}/index.ts +0 -0
@@ -1,559 +0,0 @@
1
- /**
2
- * @file Secure Data Access Hook Tests
3
- * @package @jmruthers/pace-core
4
- * @module Hooks/useSecureDataAccess
5
- * @since 0.4.0
6
- *
7
- * Comprehensive tests for the useSecureDataAccess hook covering all critical functionality.
8
- */
9
-
10
- import { renderHook, waitFor } from '@testing-library/react';
11
- import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
12
- import { useSecureDataAccess } from './useSecureDataAccess';
13
- import { useUnifiedAuth } from '../providers';
14
- import { useOrganisations } from './useOrganisations';
15
- import { setOrganisationContext } from '../utils/context/organisationContext';
16
- import { createMockSupabaseClient, createMockQueryBuilderWithData } from '../__tests__/helpers/supabaseMock';
17
- import { useResolvedScope } from '../rbac/hooks/useResolvedScope';
18
- import { useOrganisationSecurity } from './useOrganisationSecurity';
19
-
20
- // Mock the providers
21
- vi.mock('../providers', () => ({
22
- useUnifiedAuth: vi.fn()
23
- }));
24
-
25
- vi.mock('./useOrganisations', () => ({
26
- useOrganisations: vi.fn()
27
- }));
28
-
29
- // Mock the organisation context utility
30
- vi.mock('../utils/context/organisationContext', () => ({
31
- setOrganisationContext: vi.fn()
32
- }));
33
-
34
- // Mock useResolvedScope
35
- vi.mock('../rbac/hooks/useResolvedScope', () => ({
36
- useResolvedScope: vi.fn()
37
- }));
38
-
39
- // Mock useOrganisationSecurity
40
- vi.mock('./useOrganisationSecurity', () => ({
41
- useOrganisationSecurity: vi.fn()
42
- }));
43
-
44
-
45
- describe('useSecureDataAccess', () => {
46
- const mockUseUnifiedAuth = vi.mocked(useUnifiedAuth);
47
- const mockUseOrganisations = vi.mocked(useOrganisations);
48
- const mockSetOrganisationContext = vi.mocked(setOrganisationContext);
49
- const mockUseResolvedScope = vi.mocked(useResolvedScope);
50
- const mockUseOrganisationSecurity = vi.mocked(useOrganisationSecurity);
51
-
52
- const mockUser = {
53
- id: 'user-123',
54
- email: 'test@example.com'
55
- };
56
-
57
- const mockSession = {
58
- access_token: 'token-123',
59
- refresh_token: 'refresh-123'
60
- };
61
-
62
- // Create proper thenable mock query builder
63
- const mockQueryBuilder = createMockQueryBuilderWithData([{ id: 'record-123' }]);
64
- const mockSupabase = createMockSupabaseClient([{ id: 'record-123' }]);
65
-
66
-
67
- const mockSelectedOrganisation = {
68
- id: 'org-123',
69
- name: 'Test Organisation'
70
- };
71
-
72
- let freshMockQueryBuilder: any;
73
- let freshMockSupabase: any;
74
-
75
- beforeEach(() => {
76
- vi.clearAllMocks();
77
-
78
- // Create a new query builder that we can track
79
- freshMockQueryBuilder = createMockQueryBuilderWithData([{ id: 'record-123' }]);
80
-
81
- // Create Supabase client mock that returns our tracked builder
82
- freshMockSupabase = {
83
- from: vi.fn().mockReturnValue(freshMockQueryBuilder),
84
- rpc: vi.fn().mockResolvedValue({ data: { result: 'success' }, error: null }),
85
- auth: {
86
- getUser: vi.fn().mockResolvedValue({ data: { user: null }, error: null }),
87
- getSession: vi.fn().mockResolvedValue({ data: { session: null }, error: null }),
88
- signIn: vi.fn().mockResolvedValue({ data: { user: null, session: null }, error: null }),
89
- signOut: vi.fn().mockResolvedValue({ error: null }),
90
- onAuthStateChange: vi.fn().mockReturnValue({ data: { subscription: { unsubscribe: vi.fn() } } })
91
- }
92
- };
93
-
94
- mockUseUnifiedAuth.mockReturnValue({
95
- user: mockUser,
96
- session: mockSession,
97
- supabase: freshMockSupabase,
98
- isAuthenticated: true,
99
- signOut: vi.fn(),
100
- // Add other required properties
101
- } as any);
102
-
103
- mockUseOrganisations.mockReturnValue({
104
- selectedOrganisation: mockSelectedOrganisation,
105
- getUserRole: vi.fn().mockReturnValue('member'),
106
- validateOrganisationAccess: vi.fn().mockResolvedValue(true),
107
- ensureOrganisationContext: vi.fn().mockReturnValue(mockSelectedOrganisation),
108
- // Add other required properties
109
- } as any);
110
-
111
- // Mock useResolvedScope to return resolved scope with organisationId
112
- mockUseResolvedScope.mockReturnValue({
113
- resolvedScope: {
114
- organisationId: 'org-123',
115
- eventId: undefined,
116
- appId: undefined,
117
- },
118
- isLoading: false,
119
- error: null,
120
- });
121
-
122
- // Mock useOrganisationSecurity to return not super admin
123
- mockUseOrganisationSecurity.mockReturnValue({
124
- superAdminContext: { isSuperAdmin: false, hasGlobalAccess: false, canManageAllOrganisations: false },
125
- validateOrganisationAccess: vi.fn(),
126
- hasMinimumRole: vi.fn(),
127
- canAccessChildOrganisations: vi.fn(),
128
- checkPermission: vi.fn(),
129
- getPermissions: vi.fn(),
130
- logOrganisationAccess: vi.fn(),
131
- canManageOrganisation: vi.fn(),
132
- } as any);
133
- });
134
-
135
- describe('Hook Initialization', () => {
136
- it('initializes with required dependencies', () => {
137
- const { result } = renderHook(() => useSecureDataAccess());
138
-
139
- expect(result.current).toBeDefined();
140
- expect(result.current.secureQuery).toBeInstanceOf(Function);
141
- expect(result.current.secureInsert).toBeInstanceOf(Function);
142
- expect(result.current.secureUpdate).toBeInstanceOf(Function);
143
- expect(result.current.secureDelete).toBeInstanceOf(Function);
144
- expect(result.current.secureRpc).toBeInstanceOf(Function);
145
- expect(result.current.getCurrentOrganisationId()).toBe('org-123');
146
- });
147
-
148
- it('depends on useUnifiedAuth hook', () => {
149
- renderHook(() => useSecureDataAccess());
150
- expect(mockUseUnifiedAuth).toHaveBeenCalled();
151
- });
152
-
153
- it('depends on useResolvedScope hook', () => {
154
- renderHook(() => useSecureDataAccess());
155
- // useSecureDataAccess now uses useResolvedScope instead of useOrganisations
156
- expect(mockUseResolvedScope).toHaveBeenCalled();
157
- });
158
- });
159
-
160
- describe('Secure Query Operations', () => {
161
- it('executes secure query with organisation filtering', async () => {
162
- const { result } = renderHook(() => useSecureDataAccess());
163
-
164
- const data = await result.current.secureQuery('core_events', '*', { active: true });
165
-
166
- expect(freshMockSupabase.from).toHaveBeenCalledWith('core_events');
167
- expect(freshMockQueryBuilder.select).toHaveBeenCalledWith('*');
168
- expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('organisation_id', 'org-123');
169
- expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('active', true);
170
- });
171
-
172
- it('executes secure query with custom filters', async () => {
173
- const { result } = renderHook(() => useSecureDataAccess());
174
-
175
- const data = await result.current.secureQuery('users', '*', { active: true });
176
-
177
- expect(freshMockSupabase.from).toHaveBeenCalledWith('users');
178
- expect(freshMockQueryBuilder.select).toHaveBeenCalledWith('*');
179
- expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('active', true);
180
- });
181
-
182
- it('executes secure query with ordering', async () => {
183
- const { result } = renderHook(() => useSecureDataAccess());
184
-
185
- const data = await result.current.secureQuery('users', '*', {}, {
186
- orderBy: 'created_at',
187
- ascending: false
188
- });
189
-
190
- expect(freshMockQueryBuilder.select).toHaveBeenCalledWith('*');
191
- });
192
-
193
- it('executes secure query with pagination', async () => {
194
- const paginatedData = Array.from({ length: 10 }, (_, i) => ({ id: `record-${i + 20}` }));
195
-
196
- // Ensure range() returns a thenable that resolves with paginated data
197
- // and that all chain methods (eq, select, etc.) maintain the range function
198
- freshMockQueryBuilder.range = vi.fn().mockImplementation(function(min: number, max: number) {
199
- const rangedBuilder = Object.assign({}, this, {
200
- then: vi.fn().mockImplementation((resolve) => {
201
- resolve({ data: paginatedData, error: null });
202
- }),
203
- catch: vi.fn(),
204
- finally: vi.fn(),
205
- range: freshMockQueryBuilder.range // Maintain range for further chaining if needed
206
- });
207
- return rangedBuilder;
208
- });
209
-
210
- // Ensure eq() returns this which has range()
211
- freshMockQueryBuilder.eq = vi.fn().mockReturnThis();
212
- freshMockQueryBuilder.select = vi.fn().mockReturnThis();
213
- freshMockQueryBuilder.limit = vi.fn().mockReturnThis();
214
-
215
- const { result } = renderHook(() => useSecureDataAccess());
216
-
217
- const data = await result.current.secureQuery('users', '*', {}, {
218
- limit: 10,
219
- offset: 20
220
- });
221
-
222
- expect(freshMockQueryBuilder.select).toHaveBeenCalledWith('*');
223
- expect(freshMockQueryBuilder.range).toHaveBeenCalledWith(20, 29); // offset to (offset + limit - 1)
224
- expect(data).toEqual(paginatedData);
225
- });
226
-
227
- it('handles query errors gracefully', async () => {
228
- // Create a query builder that rejects
229
- const errorBuilder = createMockQueryBuilderWithData([], new Error('Query failed'));
230
- freshMockSupabase.from.mockReturnValue(errorBuilder);
231
-
232
- const { result } = renderHook(() => useSecureDataAccess());
233
-
234
- await expect(result.current.secureQuery('users', '*')).rejects.toThrow('Query failed');
235
- });
236
- });
237
-
238
- describe('Secure Insert Operations', () => {
239
- it('executes secure insert with organisation context', async () => {
240
- const { result } = renderHook(() => useSecureDataAccess());
241
-
242
- const data = await result.current.secureInsert('users', { name: 'Test User' });
243
-
244
- expect(freshMockSupabase.from).toHaveBeenCalledWith('users');
245
- expect(freshMockQueryBuilder.insert).toHaveBeenCalledWith({
246
- name: 'Test User',
247
- organisation_id: 'org-123'
248
- });
249
- });
250
-
251
- it('handles insert errors gracefully', async () => {
252
- // Create a query builder that rejects on single()
253
- const errorBuilder = createMockQueryBuilderWithData(null, new Error('Insert failed'));
254
- freshMockSupabase.from.mockReturnValue(errorBuilder);
255
-
256
- const { result } = renderHook(() => useSecureDataAccess());
257
-
258
- await expect(result.current.secureInsert('users', { name: 'Test User' })).rejects.toThrow('Insert failed');
259
- });
260
-
261
- it('prevents organisation_id override', async () => {
262
- const { result } = renderHook(() => useSecureDataAccess());
263
-
264
- const data = await result.current.secureInsert('users', {
265
- name: 'Test User',
266
- organisation_id: 'malicious-org-id'
267
- });
268
-
269
- expect(freshMockQueryBuilder.insert).toHaveBeenCalledWith({
270
- name: 'Test User',
271
- organisation_id: 'org-123' // Should override malicious value
272
- });
273
- });
274
- });
275
-
276
- describe('Secure Update Operations', () => {
277
- it('executes secure update with organisation filtering', async () => {
278
- const { result } = renderHook(() => useSecureDataAccess());
279
-
280
- const data = await result.current.secureUpdate('core_events', { event_name: 'Updated Event' }, { id: 'event-123' });
281
-
282
- expect(freshMockSupabase.from).toHaveBeenCalledWith('core_events');
283
- expect(freshMockQueryBuilder.update).toHaveBeenCalledWith({ event_name: 'Updated Event' });
284
- expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('id', 'event-123');
285
- expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('organisation_id', 'org-123');
286
- });
287
-
288
- it('handles update errors gracefully', async () => {
289
- // Create a query builder that rejects
290
- const errorBuilder = createMockQueryBuilderWithData([], new Error('Update failed'));
291
- freshMockSupabase.from.mockReturnValue(errorBuilder);
292
-
293
- const { result } = renderHook(() => useSecureDataAccess());
294
-
295
- await expect(result.current.secureUpdate('users', { name: 'Updated User' }, { id: 'user-123' })).rejects.toThrow('Update failed');
296
- });
297
-
298
- it('prevents organisation_id updates', async () => {
299
- const { result } = renderHook(() => useSecureDataAccess());
300
-
301
- const data = await result.current.secureUpdate('users', {
302
- name: 'Updated User',
303
- organisation_id: 'malicious-org-id'
304
- }, { id: 'user-123' });
305
-
306
- expect(freshMockQueryBuilder.update).toHaveBeenCalledWith({
307
- name: 'Updated User'
308
- // organisation_id should be filtered out
309
- });
310
- });
311
- });
312
-
313
- describe('Secure Delete Operations', () => {
314
- it('executes secure delete with organisation filtering', async () => {
315
- const { result } = renderHook(() => useSecureDataAccess());
316
-
317
- await result.current.secureDelete('core_events', { id: 'event-123' });
318
-
319
- expect(freshMockSupabase.from).toHaveBeenCalledWith('core_events');
320
- expect(freshMockQueryBuilder.delete).toHaveBeenCalled();
321
- expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('id', 'event-123');
322
- expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('organisation_id', 'org-123');
323
- });
324
-
325
- it('handles delete errors gracefully', async () => {
326
- // Create a query builder that rejects
327
- const errorBuilder = createMockQueryBuilderWithData([], new Error('Delete failed'));
328
- freshMockSupabase.from.mockReturnValue(errorBuilder);
329
-
330
- const { result } = renderHook(() => useSecureDataAccess());
331
-
332
- await expect(result.current.secureDelete('users', { id: 'user-123' })).rejects.toThrow('Delete failed');
333
- });
334
- });
335
-
336
- describe('Secure RPC Operations', () => {
337
- it('executes secure RPC with organisation context', async () => {
338
- const { result } = renderHook(() => useSecureDataAccess());
339
-
340
- const data = await result.current.secureRpc('get_user_data', { user_id: 'user-123' });
341
-
342
- expect(freshMockSupabase.rpc).toHaveBeenCalledWith('get_user_data', {
343
- user_id: 'user-123',
344
- p_user_id: 'user-123',
345
- organisation_id: 'org-123'
346
- });
347
- });
348
-
349
- it('handles RPC errors gracefully', async () => {
350
- // Mock error response - the RPC should reject with an error
351
- freshMockSupabase.rpc.mockRejectedValue(new Error('RPC failed'));
352
-
353
- const { result } = renderHook(() => useSecureDataAccess());
354
-
355
- await expect(result.current.secureRpc('get_user_data')).rejects.toThrow('RPC failed');
356
- });
357
- });
358
-
359
- describe('Organisation Context Management', () => {
360
- it('sets organisation context before operations', async () => {
361
- const { result } = renderHook(() => useSecureDataAccess());
362
-
363
- await result.current.secureQuery('users', '*');
364
-
365
- expect(mockSetOrganisationContext).toHaveBeenCalledWith(freshMockSupabase, 'org-123');
366
- });
367
-
368
- it('handles missing organisation context', () => {
369
- mockUseUnifiedAuth.mockReturnValue({
370
- user: mockUser,
371
- session: mockSession,
372
- supabase: freshMockSupabase,
373
- isAuthenticated: true,
374
- signOut: vi.fn(),
375
- selectedOrganisation: null,
376
- selectedEvent: null,
377
- } as any);
378
-
379
- // Mock useResolvedScope to return null scope when no context available
380
- mockUseResolvedScope.mockReturnValue({
381
- resolvedScope: null,
382
- isLoading: false,
383
- error: null,
384
- });
385
-
386
- const { result } = renderHook(() => useSecureDataAccess());
387
-
388
- expect(() => result.current.getCurrentOrganisationId()).toThrow('Organisation context is required for data access');
389
- });
390
-
391
- it('validates organisation access before operations', async () => {
392
- // The hook uses useResolvedScope to get organisationId, which is already mocked in beforeEach
393
- // The validation happens in validateContext which checks resolvedScope.organisationId
394
- const { result } = renderHook(() => useSecureDataAccess());
395
-
396
- // Use 'event' table which is in the tablesWithOrganisation list
397
- await result.current.secureQuery('core_events', '*');
398
-
399
- // Verify that the query was executed with organisation filter
400
- expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('organisation_id', 'org-123');
401
- });
402
- });
403
-
404
- describe('Error Handling', () => {
405
- it('handles missing user context', () => {
406
- mockUseUnifiedAuth.mockReturnValue({
407
- user: null,
408
- session: null,
409
- supabase: null,
410
- isAuthenticated: false,
411
- signOut: vi.fn(),
412
- // Add other required properties
413
- } as any);
414
-
415
- const { result } = renderHook(() => useSecureDataAccess());
416
-
417
- expect(() => result.current.getCurrentOrganisationId()).toThrow('No Supabase client available');
418
- });
419
-
420
- it('handles missing supabase client', () => {
421
- mockUseUnifiedAuth.mockReturnValue({
422
- user: mockUser,
423
- session: mockSession,
424
- supabase: null,
425
- isAuthenticated: true,
426
- signOut: vi.fn(),
427
- // Add other required properties
428
- } as any);
429
-
430
- const { result } = renderHook(() => useSecureDataAccess());
431
-
432
- expect(() => result.current.getCurrentOrganisationId()).toThrow('No Supabase client available');
433
- });
434
-
435
- it('handles organisation access validation failures', async () => {
436
- // Mock useResolvedScope to return null scope to simulate missing context
437
- mockUseResolvedScope.mockReturnValue({
438
- resolvedScope: null,
439
- isLoading: false,
440
- error: null,
441
- });
442
-
443
- const { result } = renderHook(() => useSecureDataAccess());
444
-
445
- await expect(result.current.secureQuery('users', '*')).rejects.toThrow('Organisation context is required for data access');
446
- });
447
- });
448
-
449
- describe('Security Features', () => {
450
- it('prevents data leaks between organisations', async () => {
451
- const { result } = renderHook(() => useSecureDataAccess());
452
-
453
- await result.current.secureQuery('core_events', '*');
454
-
455
- // Verify organisation_id filter is always applied
456
- expect(freshMockQueryBuilder.eq).toHaveBeenCalledWith('organisation_id', 'org-123');
457
- });
458
-
459
- it('prevents organisation_id manipulation in inserts', async () => {
460
- const { result } = renderHook(() => useSecureDataAccess());
461
-
462
- await result.current.secureInsert('users', {
463
- name: 'Test User',
464
- organisation_id: 'malicious-org-id'
465
- });
466
-
467
- expect(freshMockQueryBuilder.insert).toHaveBeenCalledWith({
468
- name: 'Test User',
469
- organisation_id: 'org-123' // Should override malicious value
470
- });
471
- });
472
-
473
- it('prevents organisation_id manipulation in updates', async () => {
474
- const { result } = renderHook(() => useSecureDataAccess());
475
-
476
- await result.current.secureUpdate('users', {
477
- name: 'Updated User',
478
- organisation_id: 'malicious-org-id'
479
- }, { id: 'user-123' });
480
-
481
- expect(freshMockQueryBuilder.update).toHaveBeenCalledWith({
482
- name: 'Updated User'
483
- // organisation_id should be filtered out
484
- });
485
- });
486
- });
487
-
488
- describe('Performance', () => {
489
- it('memoizes results to prevent unnecessary re-renders', () => {
490
- const { result, rerender } = renderHook(() => useSecureDataAccess());
491
- const initialSecureQuery = result.current.secureQuery;
492
- const initialGetCurrentOrganisationId = result.current.getCurrentOrganisationId;
493
-
494
- // Re-render with same props
495
- rerender();
496
-
497
- // Should not cause additional renders due to memoization
498
- expect(result.current.secureQuery).toBe(initialSecureQuery);
499
- expect(result.current.getCurrentOrganisationId).toBe(initialGetCurrentOrganisationId);
500
- });
501
-
502
- it('handles organisation changes efficiently', () => {
503
- const { result, rerender } = renderHook(() => useSecureDataAccess());
504
-
505
- expect(result.current.getCurrentOrganisationId()).toBe('org-123');
506
-
507
- // Change organisation
508
- const newOrganisation = { id: 'org-456', name: 'New Organisation' };
509
- mockUseUnifiedAuth.mockReturnValue({
510
- user: mockUser,
511
- session: mockSession,
512
- supabase: freshMockSupabase,
513
- isAuthenticated: true,
514
- signOut: vi.fn(),
515
- selectedOrganisation: newOrganisation,
516
- } as any);
517
-
518
- // Update useResolvedScope mock to return new organisation
519
- mockUseResolvedScope.mockReturnValue({
520
- resolvedScope: {
521
- organisationId: 'org-456',
522
- eventId: undefined,
523
- appId: undefined,
524
- },
525
- isLoading: false,
526
- error: null,
527
- });
528
-
529
- rerender();
530
-
531
- expect(result.current.getCurrentOrganisationId()).toBe('org-456');
532
- });
533
- });
534
-
535
- describe('Integration with Providers', () => {
536
- it('integrates with useUnifiedAuth hook correctly', () => {
537
- renderHook(() => useSecureDataAccess());
538
- expect(mockUseUnifiedAuth).toHaveBeenCalled();
539
- });
540
-
541
- it('integrates with useResolvedScope hook correctly', () => {
542
- renderHook(() => useSecureDataAccess());
543
- // useSecureDataAccess now uses useResolvedScope instead of useOrganisations
544
- expect(mockUseResolvedScope).toHaveBeenCalled();
545
- });
546
-
547
- it('uses organisation context from provider', () => {
548
- const { result } = renderHook(() => useSecureDataAccess());
549
-
550
- expect(result.current.getCurrentOrganisationId()).toBe('org-123');
551
- });
552
-
553
- it('validates organisation access through provider', () => {
554
- // This test is removed as validateOrganisationAccess is not used in useSecureDataAccess
555
- // The hook only calls ensureOrganisationContext during operations
556
- expect(true).toBe(true);
557
- });
558
- });
559
- });