@jmruthers/pace-core 0.6.9 → 0.6.11

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 (1182) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/audit-tool/00-dependencies.cjs +46 -13
  3. package/audit-tool/audits/01-pace-core-compliance.cjs +96 -21
  4. package/audit-tool/audits/02-project-structure.cjs +74 -2
  5. package/audit-tool/audits/03-architecture.cjs +220 -20
  6. package/audit-tool/audits/04-code-quality.cjs +95 -3
  7. package/audit-tool/audits/05-styling.cjs +19 -7
  8. package/audit-tool/audits/06-security-rbac.cjs +214 -25
  9. package/audit-tool/audits/07-api-tech-stack.cjs +31 -15
  10. package/audit-tool/audits/08-testing-documentation.cjs +11 -3
  11. package/audit-tool/audits/09-operations.cjs +19 -7
  12. package/audit-tool/index.cjs +22 -11
  13. package/audit-tool/utils/report-utils.cjs +4 -0
  14. package/cursor-rules/01-pace-core-compliance.mdc +1 -0
  15. package/cursor-rules/02-project-structure.mdc +3 -26
  16. package/cursor-rules/03-architecture.mdc +3 -1
  17. package/cursor-rules/04-code-quality.mdc +1 -0
  18. package/cursor-rules/05-styling.mdc +120 -8
  19. package/cursor-rules/06-security-rbac.mdc +126 -2
  20. package/cursor-rules/07-api-tech-stack.mdc +1 -0
  21. package/cursor-rules/08-testing-documentation.mdc +1 -0
  22. package/cursor-rules/09-operations.mdc +1 -0
  23. package/dist/DataTable-EFYP2QLE.js +16 -0
  24. package/dist/InactivityServiceProvider-BbxwwDz1.d.ts +308 -0
  25. package/dist/UnifiedAuthProvider-Bkt_tzdS.d.ts +183 -0
  26. package/dist/api-BZR2CYXL.js +5 -0
  27. package/dist/api-result-USV1Czr-.d.ts +51 -0
  28. package/dist/assets/app-icons/admin_favicon.svg +462 -0
  29. package/dist/assets/app-icons/base_favicon.svg +85 -0
  30. package/dist/assets/app-icons/cake_favicon.svg +68 -0
  31. package/dist/assets/app-icons/core_favicon.svg +256 -0
  32. package/dist/assets/app-icons/gear_favicon.svg +91 -0
  33. package/dist/assets/app-icons/medi_favicon.svg +92 -0
  34. package/dist/assets/app-icons/mint_favicon.svg +83 -0
  35. package/dist/assets/app-icons/pace_favicon.svg +49 -0
  36. package/dist/assets/app-icons/pump_favicon.svg +68 -0
  37. package/dist/assets/app-icons/seed_favicon.svg +91 -0
  38. package/dist/assets/app-icons/team_favicon.svg +67 -0
  39. package/dist/assets/app-icons/trac_favicon.svg +112 -0
  40. package/dist/assets/app-icons/trip_favicon.svg +102 -0
  41. package/dist/audit-HI2DHUVU.js +4 -0
  42. package/dist/auth-JvdRVaud.d.ts +49 -0
  43. package/dist/chunk-2DL2WSOE.js +327 -0
  44. package/dist/chunk-2OEVOGGR.js +9598 -0
  45. package/dist/chunk-44CNXN4P.js +15 -0
  46. package/dist/chunk-4R3T5ENU.js +2943 -0
  47. package/dist/chunk-7A6IMHH2.js +2321 -0
  48. package/dist/chunk-BTHN5MKC.js +121 -0
  49. package/dist/chunk-CU2BU2MQ.js +2 -0
  50. package/dist/chunk-D6BMFMQZ.js +200 -0
  51. package/dist/chunk-DDMPHZ3D.js +58 -0
  52. package/dist/chunk-ENLXB7GP.js +721 -0
  53. package/dist/chunk-J2KQK6DG.js +2159 -0
  54. package/dist/chunk-KJXRL3XE.js +6434 -0
  55. package/dist/chunk-L5LFKKLJ.js +61 -0
  56. package/dist/chunk-PCSHBLPB.js +811 -0
  57. package/dist/chunk-QRYSEPHB.js +429 -0
  58. package/dist/chunk-RMLY6KB5.js +187 -0
  59. package/dist/chunk-SACF5YSM.js +31 -0
  60. package/dist/chunk-UZNAFKGW.js +125 -0
  61. package/dist/chunk-V7FTM2LU.js +1080 -0
  62. package/dist/chunk-WY6Y7KC3.js +264 -0
  63. package/dist/chunk-XOJME5T7.js +407 -0
  64. package/dist/chunk-XPFVT3GN.js +492 -0
  65. package/dist/chunk-YFTFFJIV.js +529 -0
  66. package/dist/chunk-YYTWKVHO.js +1334 -0
  67. package/dist/components.d.ts +12 -89
  68. package/dist/components.js +23 -55
  69. package/dist/database.generated-qkdoiVrJ.d.ts +9441 -0
  70. package/dist/eslint-rules/index.cjs +3 -0
  71. package/dist/eslint-rules/rules/03-architecture.cjs +74 -0
  72. package/dist/eslint-rules/rules/05-styling.cjs +507 -0
  73. package/dist/eslint-rules/rules/06-security-rbac.cjs +84 -0
  74. package/dist/event-BfCox3N2.d.ts +265 -0
  75. package/dist/file-reference-DU1hcawx.d.ts +164 -0
  76. package/dist/functions-DH45k8ec.d.ts +208 -0
  77. package/dist/hooks.d.ts +28 -14
  78. package/dist/hooks.js +90 -56
  79. package/dist/icons/index.d.ts +1 -0
  80. package/dist/icons/index.js +1 -0
  81. package/dist/index.d.ts +392 -155
  82. package/dist/index.js +337 -347
  83. package/dist/pagination-BW1mqywp.d.ts +201 -0
  84. package/dist/papaparseLoader-WG2UXQ22.js +7 -0
  85. package/dist/providers.d.ts +29 -14
  86. package/dist/providers.js +7 -5
  87. package/dist/rbac/eslint-rules.js +2 -2
  88. package/dist/rbac/index.d.ts +180 -351
  89. package/dist/rbac/index.js +13 -11
  90. package/dist/theming/runtime.d.ts +28 -5
  91. package/dist/theming/runtime.js +2 -2
  92. package/dist/timezone-BTWWXKVY.d.ts +696 -0
  93. package/dist/types-BE2sEHKd.d.ts +55 -0
  94. package/dist/types-CvOPXWWZ.d.ts +111 -0
  95. package/dist/types-Dr8sNhER.d.ts +50 -0
  96. package/dist/types.d.ts +20 -13
  97. package/dist/types.js +1 -0
  98. package/dist/usePublicPageContext-B91dGYW1.d.ts +4367 -0
  99. package/dist/usePublicRouteParams-BgV6VhMi.d.ts +946 -0
  100. package/dist/utils.d.ts +338 -156
  101. package/dist/utils.js +78 -60
  102. package/dist/validation-g5n0hDkh.d.ts +177 -0
  103. package/docs/api/modules.md +1226 -1094
  104. package/docs/api-reference/components.md +5 -5
  105. package/docs/api-reference/rpc-functions.md +12 -3
  106. package/docs/core-concepts/rbac-system.md +8 -0
  107. package/docs/getting-started/cursor-rules.md +17 -20
  108. package/docs/getting-started/dependencies.md +1 -1
  109. package/docs/getting-started/setup.md +235 -0
  110. package/docs/implementation-guides/authentication.md +27 -0
  111. package/docs/implementation-guides/data-tables.md +365 -10
  112. package/docs/migration/ApiResult-migration.md +25 -0
  113. package/docs/rbac/RBAC_CONTRACT.md +0 -12
  114. package/docs/rbac/api-reference.md +33 -31
  115. package/docs/standards/0-standards-overview.md +50 -15
  116. package/docs/standards/1-pace-core-compliance-standards.md +62 -57
  117. package/docs/standards/2-project-structure-standards.md +45 -90
  118. package/docs/standards/3-architecture-standards.md +41 -1
  119. package/docs/standards/4-code-quality-standards.md +26 -6
  120. package/docs/standards/5-styling-standards.md +35 -1
  121. package/docs/standards/6-security-rbac-standards.md +288 -7
  122. package/docs/standards/7-api-tech-stack-standards.md +116 -17
  123. package/docs/standards/8-testing-documentation-standards.md +31 -0
  124. package/docs/standards/9-operations-standards.md +19 -0
  125. package/docs/standards/README.md +20 -201
  126. package/docs/testing/README.md +10 -0
  127. package/docs/testing/test-setup-for-consumers.md +916 -0
  128. package/docs/troubleshooting/common-issues.md +17 -1
  129. package/docs/troubleshooting/organisation-context-setup.md +8 -0
  130. package/docs/troubleshooting/print-event-name-css-variable-analysis.md +217 -0
  131. package/eslint-config-pace-core.cjs +24 -0
  132. package/package.json +14 -20
  133. package/scripts/build-docs.js +180 -0
  134. package/scripts/setup.cjs +536 -0
  135. package/scripts/validate.cjs +480 -0
  136. package/src/__mocks__/lucide-react.ts +0 -2
  137. package/src/__tests__/helpers/component-test-utils.test.tsx +260 -0
  138. package/src/__tests__/helpers/optimized-test-setup.test.ts +224 -0
  139. package/src/__tests__/helpers/supabaseMock.test.ts +273 -0
  140. package/src/__tests__/helpers/test-providers.test.tsx +99 -0
  141. package/src/__tests__/helpers/test-providers.tsx +37 -39
  142. package/src/__tests__/helpers/test-utils.test.tsx +447 -0
  143. package/src/__tests__/helpers/timer-utils.test.ts +371 -0
  144. package/src/assets/app-icons/admin_favicon.svg +462 -0
  145. package/src/assets/app-icons/base_favicon.svg +85 -0
  146. package/src/assets/app-icons/cake_favicon.svg +68 -0
  147. package/src/assets/app-icons/core_favicon.svg +256 -0
  148. package/src/assets/app-icons/gear_favicon.svg +91 -0
  149. package/src/assets/app-icons/index.test.ts +304 -0
  150. package/src/assets/app-icons/index.ts +83 -0
  151. package/src/assets/app-icons/medi_favicon.svg +92 -0
  152. package/src/assets/app-icons/mint_favicon.svg +83 -0
  153. package/src/assets/app-icons/pace_favicon.svg +49 -0
  154. package/src/assets/app-icons/pump_favicon.svg +68 -0
  155. package/src/assets/app-icons/seed_favicon.svg +91 -0
  156. package/src/assets/app-icons/team_favicon.svg +67 -0
  157. package/src/assets/app-icons/trac_favicon.svg +112 -0
  158. package/src/assets/app-icons/trip_favicon.svg +102 -0
  159. package/src/components/AddressField/AddressField.test.tsx +379 -4
  160. package/src/components/AddressField/AddressField.tsx +239 -213
  161. package/src/components/AddressField/types.ts +2 -2
  162. package/src/components/Alert/Alert.test.tsx +35 -25
  163. package/src/components/Alert/Alert.tsx +8 -8
  164. package/src/components/AppSwitcher/AppSwitcher.test.tsx +1250 -0
  165. package/src/components/AppSwitcher/AppSwitcher.tsx +315 -0
  166. package/src/components/Avatar/Avatar.test.tsx +11 -1
  167. package/src/components/Avatar/Avatar.tsx +3 -2
  168. package/src/components/Badge/Badge.test.tsx +11 -1
  169. package/src/components/Button/Button.test.tsx +13 -3
  170. package/src/components/Button/Button.tsx +1 -1
  171. package/src/components/Calendar/Calendar.test.tsx +523 -131
  172. package/src/components/Calendar/Calendar.tsx +107 -488
  173. package/src/components/Card/Card.test.tsx +384 -258
  174. package/src/components/Card/Card.tsx +19 -10
  175. package/src/components/Checkbox/Checkbox.test.tsx +58 -174
  176. package/src/components/ContextSelector/ContextSelector.internals.tsx +204 -0
  177. package/src/components/ContextSelector/ContextSelector.test.tsx +360 -0
  178. package/src/components/ContextSelector/ContextSelector.tsx +66 -280
  179. package/src/components/ContextSelector/ContextSelector.types.ts +35 -0
  180. package/src/components/ContextSelector/useContextSelectorState.tsx +195 -0
  181. package/src/components/DataTable/AUDIT_REPORT.md +59 -44
  182. package/src/components/DataTable/DataTable.comprehensive.test.tsx +759 -0
  183. package/src/components/DataTable/DataTable.default-state.test.tsx +524 -0
  184. package/src/components/DataTable/DataTable.export.test.tsx +705 -0
  185. package/src/components/DataTable/DataTable.grouping-aggregation.test.tsx +658 -0
  186. package/src/components/DataTable/DataTable.hooks.test.tsx +192 -0
  187. package/src/components/DataTable/DataTable.select-label-display.test.tsx +485 -0
  188. package/src/components/DataTable/DataTable.test.tsx +787 -416
  189. package/src/components/DataTable/DataTable.tsx +14 -14
  190. package/src/components/DataTable/DataTableCore.integration.test.tsx +458 -0
  191. package/src/components/DataTable/DataTableCore.test-setup.ts +221 -0
  192. package/src/components/DataTable/DataTableCore.test.tsx +970 -0
  193. package/src/components/DataTable/README.md +155 -0
  194. package/src/components/DataTable/TESTING.md +101 -0
  195. package/src/components/DataTable/a11y.basic.test.tsx +788 -0
  196. package/src/components/DataTable/components/DataTableCore.tsx +126 -894
  197. package/src/components/DataTable/components/GroupingDropdown.test.tsx +621 -0
  198. package/src/components/DataTable/components/GroupingDropdown.tsx +2 -3
  199. package/src/components/DataTable/components/ImportModal.tsx +82 -408
  200. package/src/components/DataTable/components/ImportModalFileSection.tsx +148 -0
  201. package/src/components/DataTable/context/DataTableContext.test.tsx +328 -0
  202. package/src/components/DataTable/context/DataTableContext.tsx +13 -13
  203. package/src/components/DataTable/core/ColumnFactory.test.ts +403 -0
  204. package/src/components/DataTable/core/ColumnFactory.ts +3 -3
  205. package/src/components/DataTable/hooks/useColumnOrderPersistence.test.ts +516 -0
  206. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +12 -9
  207. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.test.ts +256 -0
  208. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +12 -9
  209. package/src/components/DataTable/hooks/useDataTableConfiguration.test.ts +297 -0
  210. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +15 -3
  211. package/src/components/DataTable/hooks/useDataTableDataPipeline.test.ts +270 -0
  212. package/src/components/DataTable/hooks/useDataTableDeletionBatching.test.ts +127 -0
  213. package/src/components/DataTable/hooks/useDataTableDeletionBatching.ts +106 -0
  214. package/src/components/DataTable/hooks/useDataTableEffectiveActions.test.ts +461 -0
  215. package/src/components/DataTable/hooks/useDataTableEffectiveActions.ts +238 -0
  216. package/src/components/DataTable/hooks/useDataTableLayoutHandlers.test.ts +296 -0
  217. package/src/components/DataTable/hooks/useDataTableLayoutHandlers.ts +175 -0
  218. package/src/components/DataTable/hooks/useDataTablePaginationSync.test.ts +203 -0
  219. package/src/components/DataTable/hooks/useDataTablePaginationSync.ts +109 -0
  220. package/src/components/DataTable/hooks/useDataTablePermissions.test.ts +280 -0
  221. package/src/components/DataTable/hooks/useDataTablePermissions.ts +81 -260
  222. package/src/components/DataTable/hooks/useDataTablePipeline.test.tsx +219 -0
  223. package/src/components/DataTable/hooks/useDataTablePipeline.tsx +239 -0
  224. package/src/components/DataTable/hooks/useDataTableRenderGuard.test.tsx +316 -0
  225. package/src/components/DataTable/hooks/useDataTableRenderGuard.tsx +195 -0
  226. package/src/components/DataTable/hooks/useDataTableScope.test.ts +110 -0
  227. package/src/components/DataTable/hooks/useDataTableScope.ts +123 -0
  228. package/src/components/DataTable/hooks/useDataTableState.test.ts +733 -0
  229. package/src/components/DataTable/hooks/useDataTableState.ts +161 -114
  230. package/src/components/DataTable/hooks/useDataTableStateAndPersistence.test.ts +277 -0
  231. package/src/components/DataTable/hooks/useDataTableStateAndPersistence.ts +222 -0
  232. package/src/components/DataTable/hooks/useDataTableSuperAdmin.test.ts +93 -0
  233. package/src/components/DataTable/hooks/useDataTableSuperAdmin.ts +86 -0
  234. package/src/components/DataTable/hooks/useDataTableTableInstance.test.ts +185 -0
  235. package/src/components/DataTable/hooks/useDataTableTableInstance.ts +178 -0
  236. package/src/components/DataTable/hooks/useEffectiveColumnOrder.test.ts +183 -0
  237. package/src/components/DataTable/hooks/useHierarchicalState.test.ts +294 -0
  238. package/src/components/DataTable/hooks/useImportModalFocus.test.ts +184 -0
  239. package/src/components/DataTable/hooks/useImportModalFocus.ts +53 -0
  240. package/src/components/DataTable/hooks/useImportModalState.test.ts +390 -0
  241. package/src/components/DataTable/hooks/useImportModalState.ts +345 -0
  242. package/src/components/DataTable/hooks/useKeyboardNavigation.test.ts +787 -0
  243. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +311 -271
  244. package/src/components/DataTable/hooks/usePermissionTracking.test.ts +381 -0
  245. package/src/components/DataTable/hooks/usePermissionTracking.ts +122 -0
  246. package/src/components/DataTable/hooks/useServerSideDataEffect.test.ts +258 -0
  247. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +27 -4
  248. package/src/components/DataTable/hooks/useTableColumns.test.ts +499 -0
  249. package/src/components/DataTable/hooks/useTableColumns.ts +15 -39
  250. package/src/components/DataTable/hooks/useTableHandlers.test.ts +461 -0
  251. package/src/components/DataTable/hooks/useTableHandlers.ts +13 -22
  252. package/src/components/DataTable/index.ts +28 -5
  253. package/src/components/DataTable/keyboard.test.tsx +734 -0
  254. package/src/components/DataTable/mocks/MockRBACProvider.tsx +66 -0
  255. package/src/components/DataTable/pagination.modes.test.tsx +728 -0
  256. package/src/components/DataTable/ssr.strict-mode.test.tsx +319 -0
  257. package/src/components/DataTable/styles.test.ts +379 -0
  258. package/src/components/DataTable/styles.ts +0 -1
  259. package/src/components/DataTable/test-utils/MockDataTableComponents.tsx +55 -0
  260. package/src/components/DataTable/test-utils/dataFactories.ts +103 -0
  261. package/src/components/DataTable/test-utils/featureConfig.ts +10 -0
  262. package/src/components/DataTable/test-utils/sharedTestUtils.ts +419 -0
  263. package/src/components/DataTable/test-utils.ts +94 -0
  264. package/src/components/DataTable/types/actions.ts +71 -0
  265. package/src/components/DataTable/types/base.ts +39 -0
  266. package/src/components/DataTable/types/columns.ts +125 -0
  267. package/src/components/DataTable/types/export.ts +32 -0
  268. package/src/components/DataTable/types/features.ts +81 -0
  269. package/src/components/DataTable/types/hierarchical.ts +44 -0
  270. package/src/components/DataTable/types/index.ts +43 -0
  271. package/src/components/DataTable/types/pagination.ts +85 -0
  272. package/src/components/DataTable/types/performance.ts +47 -0
  273. package/src/components/DataTable/types/props.ts +62 -0
  274. package/src/components/DataTable/types/rbac.ts +45 -0
  275. package/src/components/DataTable/ui/layout/DataTableCore.test.tsx +1194 -0
  276. package/src/components/DataTable/ui/layout/DataTableCore.tsx +345 -0
  277. package/src/components/DataTable/ui/layout/DataTableErrorBoundary.test.tsx +438 -0
  278. package/src/components/DataTable/ui/layout/DataTableErrorBoundary.tsx +225 -0
  279. package/src/components/DataTable/ui/layout/DataTableLayout.test.tsx +1352 -0
  280. package/src/components/DataTable/ui/layout/DataTableLayout.tsx +661 -0
  281. package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.test.tsx +91 -0
  282. package/src/components/DataTable/ui/modals/BulkDeleteConfirmDialog.tsx +43 -0
  283. package/src/components/DataTable/ui/modals/DataTableModals.test.tsx +749 -0
  284. package/src/components/DataTable/ui/modals/DataTableModals.tsx +341 -0
  285. package/src/components/DataTable/ui/modals/ImportModal.test.tsx +1834 -0
  286. package/src/components/DataTable/ui/modals/ImportModal.tsx +197 -0
  287. package/src/components/DataTable/ui/modals/ImportModalFailedRowsSection.tsx +60 -0
  288. package/src/components/DataTable/ui/modals/ImportModalFileSection.tsx +148 -0
  289. package/src/components/DataTable/ui/modals/ImportModalPreviewSection.tsx +60 -0
  290. package/src/components/DataTable/ui/modals/ImportModalSummarySection.tsx +59 -0
  291. package/src/components/DataTable/ui/modals/importModalPersistence.ts +73 -0
  292. package/src/components/DataTable/ui/shared/AccessDeniedPage.test.tsx +245 -0
  293. package/src/components/DataTable/ui/shared/AccessDeniedPage.tsx +159 -0
  294. package/src/components/DataTable/ui/shared/ActionButtons.test.tsx +921 -0
  295. package/src/components/DataTable/ui/shared/ActionButtons.tsx +195 -0
  296. package/src/components/DataTable/ui/shared/ColumnFilter.test.tsx +497 -0
  297. package/src/components/DataTable/ui/shared/ColumnFilter.tsx +113 -0
  298. package/src/components/DataTable/ui/shared/PaginationControls.test.tsx +451 -0
  299. package/src/components/DataTable/ui/shared/PaginationControls.tsx +291 -0
  300. package/src/components/DataTable/ui/shared/SortIndicator.test.tsx +135 -0
  301. package/src/components/DataTable/ui/shared/SortIndicator.tsx +50 -0
  302. package/src/components/DataTable/ui/table/EditFields.test.tsx +526 -0
  303. package/src/components/DataTable/ui/table/EditFields.tsx +355 -0
  304. package/src/components/DataTable/ui/table/EditableRow.test.tsx +1003 -0
  305. package/src/components/DataTable/ui/table/EditableRow.tsx +444 -0
  306. package/src/components/DataTable/ui/table/EmptyState.test.tsx +360 -0
  307. package/src/components/DataTable/ui/table/EmptyState.tsx +74 -0
  308. package/src/components/DataTable/ui/table/FilterRow.test.tsx +416 -0
  309. package/src/components/DataTable/ui/table/FilterRow.tsx +148 -0
  310. package/src/components/DataTable/ui/table/LoadingState.test.tsx +77 -0
  311. package/src/components/DataTable/ui/table/LoadingState.tsx +17 -0
  312. package/src/components/DataTable/ui/table/RowComponent.test.tsx +1024 -0
  313. package/src/components/DataTable/ui/table/RowComponent.tsx +429 -0
  314. package/src/components/DataTable/ui/table/UnifiedTableBody.test.tsx +1273 -0
  315. package/src/components/DataTable/ui/table/UnifiedTableBody.tsx +440 -0
  316. package/src/components/DataTable/ui/table/cellValueUtils.test.ts +453 -0
  317. package/src/components/DataTable/ui/table/cellValueUtils.ts +40 -0
  318. package/src/components/DataTable/ui/toolbar/BulkOperationsDropdown.test.tsx +551 -0
  319. package/src/components/DataTable/ui/toolbar/BulkOperationsDropdown.tsx +160 -0
  320. package/src/components/DataTable/ui/toolbar/ColumnVisibilityDropdown.test.tsx +751 -0
  321. package/src/components/DataTable/ui/toolbar/ColumnVisibilityDropdown.tsx +114 -0
  322. package/src/components/DataTable/ui/toolbar/DataTableToolbar.test.tsx +629 -0
  323. package/src/components/DataTable/ui/toolbar/DataTableToolbar.tsx +271 -0
  324. package/src/components/DataTable/ui/toolbar/GroupingDropdown.test.tsx +621 -0
  325. package/src/components/DataTable/ui/toolbar/GroupingDropdown.tsx +107 -0
  326. package/src/components/DataTable/utils/a11yUtils.test.ts +548 -0
  327. package/src/components/DataTable/utils/a11yUtils.ts +1 -1
  328. package/src/components/DataTable/utils/aggregationUtils.test.ts +288 -0
  329. package/src/components/DataTable/utils/aggregationUtils.ts +5 -5
  330. package/src/components/DataTable/utils/columnUtils.test.ts +94 -0
  331. package/src/components/DataTable/utils/csvParse.test.ts +74 -0
  332. package/src/components/DataTable/utils/csvParse.ts +65 -0
  333. package/src/components/DataTable/utils/errorHandling.test.ts +209 -0
  334. package/src/components/DataTable/utils/errorHandling.ts +3 -1
  335. package/src/components/DataTable/utils/exportUtils.test.ts +954 -0
  336. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  337. package/src/components/DataTable/utils/flexibleImport.test.ts +573 -0
  338. package/src/components/DataTable/utils/flexibleImport.ts +3 -186
  339. package/src/components/DataTable/utils/hierarchicalSorting.test.ts +235 -0
  340. package/src/components/DataTable/utils/hierarchicalSorting.ts +3 -3
  341. package/src/components/DataTable/utils/hierarchicalUtils.test.ts +586 -0
  342. package/src/components/DataTable/utils/importDateParser.test.ts +162 -0
  343. package/src/components/DataTable/utils/importDateParser.ts +114 -0
  344. package/src/components/DataTable/utils/importValueParser.test.ts +138 -0
  345. package/src/components/DataTable/utils/importValueParser.ts +91 -0
  346. package/src/components/DataTable/utils/paginationUtils.test.ts +593 -0
  347. package/src/components/DataTable/utils/paginationUtils.ts +7 -4
  348. package/src/components/DataTable/utils/performanceUtils.test.ts +470 -0
  349. package/src/components/DataTable/utils/performanceUtils.ts +1 -1
  350. package/src/components/DataTable/utils/rowUtils.test.ts +235 -0
  351. package/src/components/DataTable/utils/selectFieldUtils.test.ts +271 -0
  352. package/src/components/DataTable/utils/selectFieldUtils.ts +97 -67
  353. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +18 -25
  354. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +1 -1
  355. package/src/components/DateTimeField/DateTimeField.test.tsx +3 -16
  356. package/src/components/DateTimeField/DateTimeField.tsx +1 -1
  357. package/src/components/Dialog/Dialog.test-utils.ts +49 -0
  358. package/src/components/Dialog/Dialog.test.tsx +2865 -458
  359. package/src/components/Dialog/Dialog.tsx +183 -986
  360. package/src/components/Dialog/dialogLock.test.ts +238 -0
  361. package/src/components/Dialog/dialogLock.ts +98 -0
  362. package/src/components/Dialog/index.ts +2 -0
  363. package/src/components/Dialog/useDialogDimensions.test.ts +163 -0
  364. package/src/components/Dialog/useDialogDimensions.ts +140 -0
  365. package/src/components/Dialog/useDialogLifecycle.test.ts +358 -0
  366. package/src/components/Dialog/useDialogLifecycle.ts +135 -0
  367. package/src/components/Dialog/useDialogPersistence.test.ts +381 -0
  368. package/src/components/Dialog/useDialogPersistence.ts +357 -0
  369. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +2 -62
  370. package/src/components/ErrorBoundary/ErrorBoundaryContext.context.ts +17 -0
  371. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +2 -45
  372. package/src/components/ErrorBoundary/ErrorBoundaryContext.types.ts +41 -0
  373. package/src/components/ErrorBoundary/index.ts +3 -4
  374. package/src/components/ErrorBoundary/useErrorBoundaryContext.ts +20 -0
  375. package/src/components/FileDisplay/FileDisplay.test.tsx +479 -247
  376. package/src/components/FileDisplay/FileDisplay.tsx +29 -659
  377. package/src/components/FileDisplay/FileDisplayContent.test.tsx +395 -0
  378. package/src/components/FileDisplay/FileDisplayContent.tsx +242 -0
  379. package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.test.tsx +74 -0
  380. package/src/components/FileDisplay/FileDisplayDeleteConfirmDialog.tsx +38 -0
  381. package/src/components/FileDisplay/FileDisplayEmptyView.test.tsx +33 -0
  382. package/src/components/FileDisplay/FileDisplayEmptyView.tsx +33 -0
  383. package/src/components/FileDisplay/FileDisplayErrorView.test.tsx +71 -0
  384. package/src/components/FileDisplay/FileDisplayErrorView.tsx +50 -0
  385. package/src/components/FileDisplay/FileDisplayLoadingFallbackView.test.tsx +22 -0
  386. package/src/components/FileDisplay/FileDisplayLoadingFallbackView.tsx +22 -0
  387. package/src/components/FileDisplay/FileDisplayLoadingView.test.tsx +21 -0
  388. package/src/components/FileDisplay/FileDisplayLoadingView.tsx +23 -0
  389. package/src/components/FileDisplay/FileDisplayMultipleFilesView.test.tsx +101 -0
  390. package/src/components/FileDisplay/FileDisplayMultipleFilesView.tsx +109 -0
  391. package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.test.tsx +58 -0
  392. package/src/components/FileDisplay/FileDisplaySingleDocumentLinkView.tsx +48 -0
  393. package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.test.tsx +111 -0
  394. package/src/components/FileDisplay/FileDisplaySingleFileWithActionsView.tsx +270 -0
  395. package/src/components/FileDisplay/FileDisplaySingleImageView.test.tsx +78 -0
  396. package/src/components/FileDisplay/FileDisplaySingleImageView.tsx +67 -0
  397. package/src/components/FileDisplay/fallbackUtils.test.ts +50 -0
  398. package/src/components/FileDisplay/fallbackUtils.ts +44 -0
  399. package/src/components/FileDisplay/fetchFileDisplayData.ts +24 -0
  400. package/src/components/FileDisplay/fetchFileDisplayData.unit.test.ts +183 -0
  401. package/src/components/FileDisplay/fileDisplayUtils.test.ts +58 -0
  402. package/src/components/FileDisplay/fileDisplayUtils.ts +24 -0
  403. package/src/components/FileDisplay/index.tsx +1 -1
  404. package/src/components/FileDisplay/useFileDisplay.test.ts +538 -0
  405. package/src/components/FileDisplay/useFileDisplay.ts +515 -0
  406. package/src/components/FileDisplay/useFileDisplay.unit.test.ts +1438 -0
  407. package/src/components/FileDisplay/useFileDisplayData.ts +126 -0
  408. package/src/components/FileDisplay/usePublicFileDisplay.test.ts +729 -0
  409. package/src/components/FileDisplay/usePublicFileDisplay.ts +579 -0
  410. package/src/components/FileUpload/FileUpload.test.tsx +69 -27
  411. package/src/components/FileUpload/FileUpload.tsx +112 -527
  412. package/src/components/FileUpload/FileUploadDropZone.tsx +112 -0
  413. package/src/components/FileUpload/FileUploadProgressItem.tsx +86 -0
  414. package/src/components/FileUpload/FileUploadProgressList.tsx +40 -0
  415. package/src/components/FileUpload/index.tsx +1 -1
  416. package/src/components/FileUpload/useFileUploadManager.test.ts +308 -0
  417. package/src/components/FileUpload/useFileUploadManager.ts +454 -0
  418. package/src/components/FileUpload/useResolvedAppId.test.ts +102 -0
  419. package/src/components/FileUpload/useResolvedAppId.ts +77 -0
  420. package/src/components/Footer/Footer.test.tsx +15 -382
  421. package/src/components/Footer/Footer.tsx +8 -125
  422. package/src/components/Form/Form.test.tsx +425 -88
  423. package/src/components/Form/Form.tsx +91 -299
  424. package/src/components/Form/useFormPersistence.ts +257 -0
  425. package/src/components/Header/Header.test.tsx +653 -163
  426. package/src/components/Header/Header.tsx +62 -44
  427. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +35 -76
  428. package/src/components/Input/Input.test.tsx +34 -120
  429. package/src/components/Input/Input.tsx +1 -1
  430. package/src/components/Label/Label.test.tsx +46 -45
  431. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +8 -11
  432. package/src/components/LoginForm/LoginForm.test.tsx +0 -1
  433. package/src/components/NavigationMenu/HierarchicalNavItem.tsx +104 -0
  434. package/src/components/NavigationMenu/NavigationMenu.test.tsx +2422 -102
  435. package/src/components/NavigationMenu/NavigationMenu.tsx +62 -362
  436. package/src/components/NavigationMenu/index.ts +6 -1
  437. package/src/components/NavigationMenu/navigationPermissionHelper.ts +188 -0
  438. package/src/components/NavigationMenu/useNavigationFiltering.test.ts +1949 -0
  439. package/src/components/NavigationMenu/useNavigationFiltering.ts +199 -308
  440. package/src/components/NavigationMenu/useNavigationScope.ts +125 -0
  441. package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +1322 -0
  442. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +50 -49
  443. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +81 -38
  444. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +103 -85
  445. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +774 -44
  446. package/src/components/PaceAppLayout/PaceAppLayout.tsx +282 -764
  447. package/src/components/PaceAppLayout/README.md +0 -9
  448. package/src/components/PaceAppLayout/test-setup.tsx +15 -9
  449. package/src/components/PaceAppLayout/useFilteredNavItems.ts +304 -0
  450. package/src/components/PaceAppLayout/usePaceAppLayoutConfig.ts +142 -0
  451. package/src/components/PaceAppLayout/usePaceAppLayoutGate.tsx +150 -0
  452. package/src/components/PaceAppLayout/usePaceAppLayoutPermissions.ts +162 -0
  453. package/src/components/PaceAppLayout/usePaceAppLayoutScope.ts +79 -0
  454. package/src/components/PaceAppLayout/useRoleBasedRouteAccess.ts +157 -0
  455. package/src/components/PaceAppLayout/useSuperAdminFallback.ts +58 -0
  456. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +782 -20
  457. package/src/components/PaceLoginPage/PaceLoginPage.tsx +33 -125
  458. package/src/components/PaceLoginPage/useLoginAppAccess.ts +153 -0
  459. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +1 -1
  460. package/src/components/Progress/Progress.test.tsx +127 -1
  461. package/src/components/Progress/Progress.tsx +1 -2
  462. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +1196 -4
  463. package/src/components/ProtectedRoute/ProtectedRoute.tsx +29 -217
  464. package/src/components/ProtectedRoute/useProtectedRouteState.ts +128 -0
  465. package/src/components/ProtectedRoute/useVisibilityRedirectGrace.ts +89 -0
  466. package/src/components/PublicLayout/PublicLayout.test.tsx +1640 -38
  467. package/src/components/PublicLayout/PublicPageContext.ts +28 -0
  468. package/src/components/PublicLayout/PublicPageLayout.tsx +134 -75
  469. package/src/components/PublicLayout/PublicPageProvider.tsx +7 -42
  470. package/src/components/PublicLayout/usePublicPageContext.ts +36 -0
  471. package/src/components/Select/Select.test.tsx +45 -8
  472. package/src/components/Select/Select.tsx +57 -40
  473. package/src/components/Select/context.test.tsx +56 -0
  474. package/src/components/Select/text.test.tsx +104 -0
  475. package/src/components/Select/text.ts +26 -0
  476. package/src/components/Select/types.ts +3 -0
  477. package/src/components/Select/useSelectEvents.test.ts +279 -0
  478. package/src/components/Select/useSelectEvents.ts +87 -0
  479. package/src/components/Select/useSelectSearch.test.tsx +295 -0
  480. package/src/components/Select/useSelectSearch.ts +91 -0
  481. package/src/components/Select/useSelectState.test.ts +268 -0
  482. package/src/components/Select/useSelectState.ts +104 -0
  483. package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +28 -112
  484. package/src/components/Switch/Switch.test.tsx +57 -153
  485. package/src/components/Table/Table.test.tsx +395 -317
  486. package/src/components/Tabs/Tabs.test.tsx +270 -0
  487. package/src/components/Tabs/Tabs.tsx +4 -4
  488. package/src/components/Textarea/Textarea.test.tsx +11 -38
  489. package/src/components/Toast/Toast.test.tsx +425 -496
  490. package/src/components/Tooltip/Tooltip.test.tsx +4 -21
  491. package/src/components/UserMenu/UserMenu.test.tsx +1 -21
  492. package/src/components/UserMenu/UserMenu.tsx +0 -1
  493. package/src/components/index.test.ts +346 -0
  494. package/src/components/index.ts +12 -1
  495. package/src/constants/performance.test.ts +91 -0
  496. package/src/hooks/ServiceHooks.test.tsx +725 -0
  497. package/src/hooks/hooks.integration.test.tsx +608 -0
  498. package/src/hooks/index.ts +18 -3
  499. package/src/hooks/index.unit.test.ts +220 -0
  500. package/src/hooks/public/usePublicEvent.test.ts +304 -0
  501. package/src/hooks/public/usePublicEvent.ts +11 -11
  502. package/src/hooks/public/usePublicEventLogo.test.ts +655 -120
  503. package/src/hooks/public/usePublicEventLogo.ts +2 -2
  504. package/src/hooks/public/usePublicRouteParams.test.ts +595 -0
  505. package/src/hooks/public/usePublicRouteParams.ts +2 -2
  506. package/src/hooks/services/useAuth.ts +9 -7
  507. package/src/hooks/services/useAuthService.ts +1 -1
  508. package/src/hooks/services/useEventService.ts +1 -1
  509. package/src/hooks/useAccessibleApps.test.ts +400 -0
  510. package/src/hooks/useAccessibleApps.ts +264 -0
  511. package/src/hooks/useAddressAutocomplete.test.ts +170 -47
  512. package/src/hooks/useAddressAutocomplete.ts +109 -81
  513. package/src/hooks/useApiFetch.unit.test.ts +111 -0
  514. package/src/hooks/useAppConfig.ts +13 -3
  515. package/src/hooks/useAppConfig.unit.test.ts +712 -0
  516. package/src/hooks/useComponentPerformance.unit.test.tsx +314 -0
  517. package/src/hooks/useDataTablePerformance.ts +111 -130
  518. package/src/hooks/useDataTablePerformance.unit.test.ts +720 -0
  519. package/src/hooks/useDataTableState.test.ts +170 -0
  520. package/src/hooks/useDataTableState.ts +5 -5
  521. package/src/hooks/useDebounce.unit.test.ts +157 -0
  522. package/src/hooks/useEventTheme.test.ts +70 -18
  523. package/src/hooks/useEventTheme.ts +50 -22
  524. package/src/hooks/useEvents.ts +49 -2
  525. package/src/hooks/useEvents.unit.test.ts +227 -0
  526. package/src/hooks/useFileReference.test.ts +388 -107
  527. package/src/hooks/useFileReference.ts +184 -179
  528. package/src/hooks/useFileUrl.ts +1 -1
  529. package/src/hooks/useFileUrl.unit.test.ts +686 -0
  530. package/src/hooks/useFileUrlCache.test.ts +319 -0
  531. package/src/hooks/useFileUrlCache.ts +5 -2
  532. package/src/hooks/useFocusManagement.unit.test.ts +604 -0
  533. package/src/hooks/useFocusTrap.unit.test.tsx +613 -0
  534. package/src/hooks/useFormDialog.test.ts +307 -0
  535. package/src/hooks/useFormDialog.ts +2 -2
  536. package/src/hooks/useInactivityTracker.ts +141 -134
  537. package/src/hooks/useInactivityTracker.unit.test.ts +446 -0
  538. package/src/hooks/useIsMobile.unit.test.ts +317 -0
  539. package/src/hooks/useIsPrint.ts +62 -0
  540. package/src/hooks/useIsPrint.unit.test.ts +545 -0
  541. package/src/hooks/useKeyboardShortcuts.unit.test.ts +907 -0
  542. package/src/hooks/useOrganisationPermissions.test.ts +1 -2
  543. package/src/hooks/useOrganisationPermissions.ts +1 -4
  544. package/src/hooks/useOrganisationPermissions.unit.test.tsx +293 -0
  545. package/src/hooks/useOrganisationSecurity.test.ts +4 -33
  546. package/src/hooks/useOrganisationSecurity.ts +192 -203
  547. package/src/hooks/useOrganisationSecurity.unit.test.tsx +959 -0
  548. package/src/hooks/useOrganisations.ts +1 -1
  549. package/src/hooks/useOrganisations.unit.test.ts +369 -0
  550. package/src/hooks/usePerformanceMonitor.ts +1 -1
  551. package/src/hooks/usePerformanceMonitor.unit.test.ts +693 -0
  552. package/src/hooks/usePermissionCache.test.ts +298 -329
  553. package/src/hooks/usePermissionCache.ts +277 -276
  554. package/src/hooks/usePreventTabReload.test.ts +307 -0
  555. package/src/hooks/usePublicEvent.simple.test.ts +794 -0
  556. package/src/hooks/usePublicEvent.test.ts +670 -0
  557. package/src/hooks/usePublicEvent.unit.test.ts +638 -0
  558. package/src/hooks/usePublicFileDisplay.test.ts +948 -0
  559. package/src/hooks/usePublicRouteParams.unit.test.ts +442 -0
  560. package/src/hooks/useQueryCache.test.ts +391 -0
  561. package/src/hooks/useQueryCache.ts +7 -9
  562. package/src/hooks/useRBAC.unit.test.ts +253 -0
  563. package/src/hooks/useSessionDraft.test.ts +556 -0
  564. package/src/hooks/useSessionDraft.ts +14 -11
  565. package/src/hooks/useSessionRestoration.ts +1 -1
  566. package/src/hooks/useSessionRestoration.unit.test.tsx +381 -0
  567. package/src/hooks/useStorage.ts +94 -54
  568. package/src/hooks/useStorage.unit.test.ts +684 -0
  569. package/src/hooks/useToast.test.ts +413 -0
  570. package/src/hooks/useToast.ts +2 -2
  571. package/src/hooks/useToast.unit.test.tsx +481 -0
  572. package/src/hooks/useZodForm.ts +3 -3
  573. package/src/hooks/useZodForm.unit.test.tsx +191 -0
  574. package/src/icons/index.test.ts +133 -0
  575. package/src/icons/index.ts +3 -1
  576. package/src/index.test.ts +528 -0
  577. package/src/index.ts +56 -9
  578. package/src/providers/AuthProvider.test.tsx +218 -0
  579. package/src/providers/EventProvider.test.tsx +487 -0
  580. package/src/providers/InactivityProvider.test-helper.tsx +40 -0
  581. package/src/providers/InactivityProvider.test.tsx +421 -0
  582. package/src/providers/ProviderLifecycle.test.tsx +308 -0
  583. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +7 -12
  584. package/src/providers/UnifiedAuthProvider.test.tsx +503 -0
  585. package/src/providers/index.test.ts +138 -0
  586. package/src/providers/services/AuthServiceContext.ts +27 -0
  587. package/src/providers/services/AuthServiceProvider.integration.test.tsx +229 -0
  588. package/src/providers/services/AuthServiceProvider.test.tsx +638 -0
  589. package/src/providers/services/AuthServiceProvider.tsx +81 -20
  590. package/src/providers/services/EventServiceContext.ts +25 -0
  591. package/src/providers/services/EventServiceProvider.test.tsx +839 -0
  592. package/src/providers/services/EventServiceProvider.tsx +11 -20
  593. package/src/providers/services/InactivityServiceContext.ts +25 -0
  594. package/src/providers/services/InactivityServiceProvider.test.tsx +662 -0
  595. package/src/providers/services/InactivityServiceProvider.tsx +7 -17
  596. package/src/providers/services/OrganisationServiceContext.ts +25 -0
  597. package/src/providers/services/OrganisationServiceProvider.test.tsx +440 -0
  598. package/src/providers/services/OrganisationServiceProvider.tsx +7 -17
  599. package/src/providers/services/UnifiedAuthContext.ts +102 -0
  600. package/src/providers/services/UnifiedAuthProvider.advanced.test.tsx +434 -0
  601. package/src/providers/services/UnifiedAuthProvider.appId.test.tsx +408 -0
  602. package/src/providers/services/UnifiedAuthProvider.integration.test.tsx +304 -0
  603. package/src/providers/services/UnifiedAuthProvider.test.tsx +212 -0
  604. package/src/providers/services/UnifiedAuthProvider.tsx +147 -497
  605. package/src/providers/services/contexts.test.tsx +281 -0
  606. package/src/providers/services/useUnifiedAuth.test.tsx +251 -0
  607. package/src/providers/services/useUnifiedAuth.ts +29 -0
  608. package/src/providers/services/useUnifiedAuthContextValue.ts +279 -0
  609. package/src/providers/useInactivity.test-helper.ts +27 -0
  610. package/src/rbac/README.md +5 -5
  611. package/src/rbac/adapters.comprehensive.test.tsx +429 -0
  612. package/src/rbac/adapters.test.tsx +654 -0
  613. package/src/rbac/adapters.tsx +53 -38
  614. package/src/rbac/api.test.ts +986 -259
  615. package/src/rbac/api.ts +260 -216
  616. package/src/rbac/audit-batched.test.ts +550 -0
  617. package/src/rbac/audit-batched.ts +5 -4
  618. package/src/rbac/audit.test.ts +225 -28
  619. package/src/rbac/audit.ts +26 -18
  620. package/src/rbac/auth-rbac-security.integration.test.tsx +300 -0
  621. package/src/rbac/auth-rbac.e2e.test.tsx +510 -0
  622. package/src/rbac/cache-invalidation.test.ts +715 -0
  623. package/src/rbac/cache-invalidation.ts +18 -15
  624. package/src/rbac/cache.test.ts +123 -63
  625. package/src/rbac/cache.ts +3 -4
  626. package/src/rbac/components/AccessDenied.test.tsx +324 -0
  627. package/src/rbac/components/AccessDenied.tsx +20 -18
  628. package/src/rbac/components/NavigationGuard.test.tsx +1148 -0
  629. package/src/rbac/components/NavigationGuard.tsx +10 -8
  630. package/src/rbac/components/PagePermissionGuard.guard.test.tsx +236 -0
  631. package/src/rbac/components/PagePermissionGuard.performance.test.tsx +252 -0
  632. package/src/rbac/components/PagePermissionGuard.race-condition.test.tsx +243 -0
  633. package/src/rbac/components/PagePermissionGuard.test.tsx +1430 -0
  634. package/src/rbac/components/PagePermissionGuard.tsx +188 -381
  635. package/src/rbac/components/PagePermissionGuard.verification.test.tsx +185 -0
  636. package/src/rbac/config.test.ts +131 -48
  637. package/src/rbac/config.ts +69 -26
  638. package/src/rbac/docs/event-based-apps.md +26 -13
  639. package/src/rbac/engine.comprehensive.test.ts +808 -0
  640. package/src/rbac/engine.test.ts +974 -130
  641. package/src/rbac/engine.ts +53 -13
  642. package/src/rbac/errors.test.ts +99 -87
  643. package/src/rbac/errors.ts +89 -55
  644. package/src/rbac/eslint-rules.js +2 -2
  645. package/src/rbac/hooks/permissions/runPermissionCheck.ts +77 -0
  646. package/src/rbac/hooks/permissions/useAccessLevel.test.ts +622 -0
  647. package/src/rbac/hooks/permissions/useAccessLevel.ts +23 -14
  648. package/src/rbac/hooks/permissions/useCan.test.ts +798 -0
  649. package/src/rbac/hooks/permissions/useCan.ts +173 -253
  650. package/src/rbac/hooks/permissions/useMultiplePermissions.test.ts +843 -0
  651. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +63 -10
  652. package/src/rbac/hooks/permissions/usePermissions.test.ts +543 -0
  653. package/src/rbac/hooks/permissions/usePermissions.ts +50 -78
  654. package/src/rbac/hooks/useCan.test.ts +348 -32
  655. package/src/rbac/hooks/usePageAccessLogging.ts +160 -0
  656. package/src/rbac/hooks/usePageGuardScope.ts +117 -0
  657. package/src/rbac/hooks/usePagePermissionCheck.ts +67 -0
  658. package/src/rbac/hooks/usePermissions.integration.test.ts +427 -0
  659. package/src/rbac/hooks/usePermissions.stability.test.ts +268 -0
  660. package/src/rbac/hooks/usePermissions.test.ts +459 -33
  661. package/src/rbac/hooks/usePermissions.ts +5 -7
  662. package/src/rbac/hooks/useRBAC.test.ts +1784 -21
  663. package/src/rbac/hooks/useRBAC.ts +148 -88
  664. package/src/rbac/hooks/useResolvedScope.test.ts +442 -5
  665. package/src/rbac/hooks/useResolvedScope.ts +4 -1
  666. package/src/rbac/hooks/useResourcePermissions.test.ts +561 -24
  667. package/src/rbac/hooks/useResourcePermissions.ts +76 -140
  668. package/src/rbac/hooks/useResourcePermissionsSuperAdmin.ts +67 -0
  669. package/src/rbac/hooks/useRoleManagement.test.ts +634 -61
  670. package/src/rbac/hooks/useRoleManagement.ts +158 -586
  671. package/src/rbac/hooks/useSecureSupabase.test.ts +1179 -0
  672. package/src/rbac/hooks/useSecureSupabase.ts +21 -14
  673. package/src/rbac/hooks/useSuperAdminCheck.ts +80 -0
  674. package/src/rbac/index.test.ts +107 -0
  675. package/src/rbac/index.ts +32 -32
  676. package/src/rbac/performance.test.ts +451 -0
  677. package/src/rbac/permissions.test.ts +149 -68
  678. package/src/rbac/permissions.ts +0 -3
  679. package/src/rbac/rbac-core.test.tsx +276 -0
  680. package/src/rbac/rbac-engine-core-logic.test.ts +387 -0
  681. package/src/rbac/rbac-engine-simplified.test.ts +252 -0
  682. package/src/rbac/rbac-functions.test.ts +703 -0
  683. package/src/rbac/rbac-integration.test.ts +523 -0
  684. package/src/rbac/rbac-role-isolation.test.ts +456 -0
  685. package/src/rbac/request-deduplication.test.ts +352 -0
  686. package/src/rbac/request-deduplication.ts +5 -4
  687. package/src/rbac/scenarios.user-role.test.tsx +271 -0
  688. package/src/rbac/secureClient.test.ts +499 -115
  689. package/src/rbac/secureClient.ts +54 -28
  690. package/src/rbac/security.test.ts +448 -44
  691. package/src/rbac/security.ts +7 -6
  692. package/src/rbac/types/roleManagement.ts +66 -0
  693. package/src/rbac/types.test.ts +236 -0
  694. package/src/rbac/types.ts +7 -5
  695. package/src/rbac/utils/clientSecurity.test.ts +192 -0
  696. package/src/rbac/utils/clientSecurity.ts +6 -4
  697. package/src/rbac/utils/contextValidator.test.ts +126 -0
  698. package/src/rbac/utils/contextValidator.ts +6 -3
  699. package/src/rbac/utils/deep-equal.test.ts +76 -0
  700. package/src/rbac/utils/eventContext.test.ts +401 -0
  701. package/src/rbac/utils/eventContext.ts +38 -34
  702. package/src/rbac/utils/fetchPermissionMap.ts +13 -0
  703. package/src/rbac/utils/permissionMapHelpers.ts +34 -0
  704. package/src/rbac/utils/roleManagementRpc.ts +303 -0
  705. package/src/services/AuthService.edge-cases.test.ts +746 -0
  706. package/src/services/AuthService.restoreSession.test.ts +59 -0
  707. package/src/services/AuthService.test.ts +1362 -0
  708. package/src/services/AuthService.ts +197 -216
  709. package/src/services/BaseService.edge-cases.test.ts +506 -0
  710. package/src/services/BaseService.test.ts +363 -0
  711. package/src/services/EventService.edge-cases.test.ts +636 -0
  712. package/src/services/EventService.eventColours.test.ts +64 -0
  713. package/src/services/EventService.test.ts +1250 -0
  714. package/src/services/EventService.ts +244 -315
  715. package/src/services/InactivityService.edge-cases.test.ts +492 -0
  716. package/src/services/InactivityService.lifecycle.test.ts +406 -0
  717. package/src/services/InactivityService.test.ts +829 -0
  718. package/src/services/InactivityService.ts +172 -213
  719. package/src/services/OrganisationService.edge-cases.test.ts +633 -0
  720. package/src/services/OrganisationService.pagination.test.ts +409 -0
  721. package/src/services/OrganisationService.test.ts +1579 -0
  722. package/src/services/OrganisationService.ts +186 -257
  723. package/src/services/base/BaseService.test.ts +214 -0
  724. package/src/services/interfaces/IAuthService.test.ts +184 -0
  725. package/src/services/interfaces/IAuthService.ts +10 -9
  726. package/src/services/interfaces/IEventService.test.ts +176 -0
  727. package/src/services/interfaces/IInactivityService.test.ts +183 -0
  728. package/src/services/interfaces/IOrganisationService.test.ts +207 -0
  729. package/src/services/interfaces/IOrganisationService.ts +0 -1
  730. package/src/styles/core.css +244 -12
  731. package/src/theming/parseEventColours.test.ts +321 -0
  732. package/src/theming/parseEventColours.ts +18 -9
  733. package/src/theming/runtime.test.ts +495 -0
  734. package/src/theming/runtime.ts +72 -7
  735. package/src/types/api-result.ts +53 -0
  736. package/src/types/auth.ts +0 -1
  737. package/src/types/core.test.ts +397 -0
  738. package/src/types/database-generated.test.ts +78 -0
  739. package/src/types/database.generated.ts +45 -10
  740. package/src/types/event.ts +39 -19
  741. package/src/types/file-reference.test.ts +351 -0
  742. package/src/types/file-reference.ts +37 -12
  743. package/src/types/guards.test.ts +246 -0
  744. package/src/types/index.test.ts +265 -0
  745. package/src/types/index.ts +3 -0
  746. package/src/types/organisation.roles.test.ts +55 -0
  747. package/src/types/organisation.test.ts +1105 -0
  748. package/src/types/organisation.ts +15 -15
  749. package/src/types/rpc-responses.ts +33 -0
  750. package/src/types/supabase.ts +14 -6
  751. package/src/types/theme.test.ts +830 -0
  752. package/src/types/type-validation.test.ts +526 -0
  753. package/src/types/validation.test.ts +729 -0
  754. package/src/types/vitest-globals.d.ts +1 -1
  755. package/src/utils/app/appConfig.test.ts +235 -0
  756. package/src/utils/app/appIdResolver.test.ts +252 -57
  757. package/src/utils/app/appIdResolver.ts +31 -20
  758. package/src/utils/app/appNameResolver.test.ts +18 -10
  759. package/src/utils/app/appNameResolver.ts +11 -9
  760. package/src/utils/app/appPortMap.test.ts +125 -0
  761. package/src/utils/app/appPortMap.ts +51 -0
  762. package/src/utils/app/buildAppUrl.test.ts +273 -0
  763. package/src/utils/app/buildAppUrl.ts +114 -0
  764. package/src/utils/appConfig.unit.test.ts +55 -0
  765. package/src/utils/audit/audit.test.ts +354 -39
  766. package/src/utils/audit.unit.test.ts +69 -0
  767. package/src/utils/auth-utils.unit.test.ts +69 -0
  768. package/src/utils/bundleAnalysis.unit.test.ts +326 -0
  769. package/src/utils/cn.unit.test.ts +34 -0
  770. package/src/utils/context/organisationContext.test.ts +115 -95
  771. package/src/utils/context/organisationContext.ts +32 -43
  772. package/src/utils/context/sessionTracking.test.ts +354 -0
  773. package/src/utils/core/cn.test.ts +66 -0
  774. package/src/utils/core/debugLogger.test.ts +113 -0
  775. package/src/utils/core/debugLogger.ts +15 -8
  776. package/src/utils/core/logger.test.ts +217 -0
  777. package/src/utils/core/logger.ts +20 -16
  778. package/src/utils/core/mergeRefs.ts +24 -0
  779. package/src/utils/debugLogger.test.ts +417 -0
  780. package/src/utils/device/deviceFingerprint.test.ts +8 -5
  781. package/src/utils/device/deviceFingerprint.ts +3 -3
  782. package/src/utils/deviceFingerprint.unit.test.ts +818 -0
  783. package/src/utils/dynamic/createLazyComponent.tsx +46 -0
  784. package/src/utils/dynamic/dynamicUtils.test.ts +185 -0
  785. package/src/utils/dynamic/dynamicUtils.ts +6 -6
  786. package/src/utils/dynamic/lazyLoad.test.tsx +156 -0
  787. package/src/utils/dynamic/lazyLoad.tsx +8 -36
  788. package/src/utils/dynamic/papaparseLoader.ts +7 -0
  789. package/src/utils/dynamicUtils.unit.test.ts +331 -0
  790. package/src/utils/file-reference/file-reference.test.ts +1238 -0
  791. package/src/utils/file-reference/index.ts +330 -348
  792. package/src/utils/formatDate.unit.test.ts +109 -0
  793. package/src/utils/formatting/formatDate.test.ts +22 -148
  794. package/src/utils/formatting/formatDateTime.test.ts +41 -119
  795. package/src/utils/formatting/formatDateTimeTimezone.test.ts +41 -85
  796. package/src/utils/formatting/formatNumber.test.ts +259 -0
  797. package/src/utils/formatting/formatTime.test.ts +36 -128
  798. package/src/utils/formatting/formatting.ts +1 -1
  799. package/src/utils/formatting.unit.test.ts +99 -0
  800. package/src/utils/google-places/googlePlacesUtils.test.ts +127 -36
  801. package/src/utils/google-places/googlePlacesUtils.ts +67 -86
  802. package/src/utils/google-places/loadGoogleMapsScript.test.ts +68 -8
  803. package/src/utils/google-places/loadGoogleMapsScript.ts +140 -118
  804. package/src/utils/index.ts +52 -11
  805. package/src/utils/index.unit.test.ts +251 -0
  806. package/src/utils/lazyLoad.unit.test.tsx +319 -0
  807. package/src/utils/location/location.test.ts +19 -116
  808. package/src/utils/logger.unit.test.ts +398 -0
  809. package/src/utils/organisationContext.unit.test.ts +180 -0
  810. package/src/utils/performance/bundleAnalysis.test.ts +148 -0
  811. package/src/utils/performance/bundleAnalysis.ts +16 -22
  812. package/src/utils/performance/performanceBenchmark.test.ts +251 -0
  813. package/src/utils/performance/performanceBenchmark.ts +12 -4
  814. package/src/utils/performance/performanceBudgets.test.ts +241 -0
  815. package/src/utils/performance/performanceBudgets.ts +9 -6
  816. package/src/utils/performanceBenchmark.test.ts +174 -0
  817. package/src/utils/performanceBudgets.unit.test.ts +288 -0
  818. package/src/utils/permissionTypes.unit.test.ts +250 -0
  819. package/src/utils/permissionUtils.unit.test.ts +362 -0
  820. package/src/utils/permissions/permissionTypes.test.ts +149 -0
  821. package/src/utils/permissions/permissionUtils.test.ts +20 -42
  822. package/src/utils/persistence/keyDerivation.test.ts +306 -0
  823. package/src/utils/persistence/sensitiveFieldDetection.test.ts +271 -0
  824. package/src/utils/persistence/sensitiveFieldDetection.ts +2 -2
  825. package/src/utils/request-deduplication.test.ts +349 -0
  826. package/src/utils/request-deduplication.ts +6 -4
  827. package/src/utils/sanitization.unit.test.ts +346 -0
  828. package/src/utils/schemaUtils.unit.test.ts +441 -0
  829. package/src/utils/secureDataAccess.unit.test.ts +334 -0
  830. package/src/utils/secureErrors.unit.test.ts +390 -0
  831. package/src/utils/secureStorage.unit.test.ts +289 -0
  832. package/src/utils/security/auth-utils.ts +38 -27
  833. package/src/utils/security/secureDataAccess.test.ts +22 -191
  834. package/src/utils/security/secureDataAccess.ts +241 -281
  835. package/src/utils/security/secureErrors.test.ts +163 -0
  836. package/src/utils/security/secureStorage.test.ts +156 -0
  837. package/src/utils/security/secureStorage.ts +1 -1
  838. package/src/utils/security/security.test.ts +212 -0
  839. package/src/utils/security/security.ts +15 -18
  840. package/src/utils/security/securityMonitor.test.ts +90 -0
  841. package/src/utils/security/securityMonitor.ts +1 -1
  842. package/src/utils/security.unit.test.ts +155 -0
  843. package/src/utils/securityMonitor.unit.test.ts +276 -0
  844. package/src/utils/sessionTracking.unit.test.ts +218 -0
  845. package/src/utils/storage/config.unit.test.ts +239 -0
  846. package/src/utils/storage/helpers.test.ts +769 -456
  847. package/src/utils/storage/helpers.ts +174 -253
  848. package/src/utils/storage/index.unit.test.ts +68 -0
  849. package/src/utils/storage/storageUtils.ts +32 -0
  850. package/src/utils/storage/types.ts +9 -2
  851. package/src/utils/supabase/createBaseClient.test.ts +201 -0
  852. package/src/utils/supabase/createBaseClient.ts +2 -1
  853. package/src/utils/timezone/timezone.test.ts +26 -44
  854. package/src/utils/timezone.test.ts +345 -0
  855. package/src/utils/validation/common.test.ts +115 -0
  856. package/src/utils/validation/csrf.test.ts +198 -0
  857. package/src/utils/validation/csrf.ts +42 -41
  858. package/src/utils/validation/htmlSanitization.ts +27 -31
  859. package/src/utils/validation/htmlSanitization.unit.test.ts +618 -0
  860. package/src/utils/validation/passwordSchema.test.ts +164 -0
  861. package/src/utils/validation/schema.test.ts +127 -0
  862. package/src/utils/validation/schema.ts +6 -3
  863. package/src/utils/validation/sqlInjectionProtection.test.ts +165 -0
  864. package/src/utils/validation/sqlInjectionProtection.ts +2 -2
  865. package/src/utils/validation/user.test.ts +173 -0
  866. package/src/utils/validation/validation.test.ts +197 -0
  867. package/src/utils/validation/validationUtils.test.ts +294 -0
  868. package/src/utils/validation.unit.test.ts +307 -0
  869. package/src/utils/validationUtils.unit.test.ts +558 -0
  870. package/src/vite-env.d.ts +6 -0
  871. package/dist/AuthService-DmfO5rGS.d.ts +0 -524
  872. package/dist/DataTable-DRUIgtUH.d.ts +0 -166
  873. package/dist/DataTable-SOAFXIWY.js +0 -15
  874. package/dist/PublicPageProvider-CIGSujI2.d.ts +0 -4147
  875. package/dist/UnifiedAuthProvider-7SNDOWYD.js +0 -7
  876. package/dist/UnifiedAuthProvider-CKvHP1MK.d.ts +0 -139
  877. package/dist/api-7P7DI652.js +0 -4
  878. package/dist/audit-MYQXYZFU.js +0 -3
  879. package/dist/auth-BZOJqrdd.d.ts +0 -49
  880. package/dist/chunk-4DDCYDQ3.js +0 -544
  881. package/dist/chunk-5HNSDQWH.js +0 -5046
  882. package/dist/chunk-5W2A3DRC.js +0 -164
  883. package/dist/chunk-6GLLNA6U.js +0 -31
  884. package/dist/chunk-7ILTDCL2.js +0 -80
  885. package/dist/chunk-A3W6LW53.js +0 -70
  886. package/dist/chunk-AHU7G2R5.js +0 -423
  887. package/dist/chunk-C7ZQ5O4C.js +0 -481
  888. package/dist/chunk-EF2UGZWY.js +0 -611
  889. package/dist/chunk-FEJLJNWA.js +0 -181
  890. package/dist/chunk-FYHN4DD5.js +0 -415
  891. package/dist/chunk-GS5672WG.js +0 -2003
  892. package/dist/chunk-HF6O3O37.js +0 -187
  893. package/dist/chunk-J2U36LHD.js +0 -8517
  894. package/dist/chunk-LX6U42O3.js +0 -2177
  895. package/dist/chunk-MPBLMWVR.js +0 -2161
  896. package/dist/chunk-OJ4SKRSV.js +0 -105
  897. package/dist/chunk-S6ZQKDY6.js +0 -62
  898. package/dist/chunk-S7DKJPLT.js +0 -699
  899. package/dist/chunk-T5CVK4R3.js +0 -2816
  900. package/dist/chunk-TTRFSOKR.js +0 -121
  901. package/dist/chunk-Z2FNRKF3.js +0 -994
  902. package/dist/database.generated-DT8JTZiP.d.ts +0 -9406
  903. package/dist/event-CW5YB_2p.d.ts +0 -239
  904. package/dist/file-reference-BavO2eQj.d.ts +0 -148
  905. package/dist/functions-lBy5L2ry.d.ts +0 -208
  906. package/dist/timezone-0AyangqX.d.ts +0 -697
  907. package/dist/types-BeoeWV5I.d.ts +0 -110
  908. package/dist/types-DXstZpNI.d.ts +0 -614
  909. package/dist/types-t9H8qKRw.d.ts +0 -55
  910. package/dist/usePublicRouteParams-DQLrDqDb.d.ts +0 -876
  911. package/dist/useToast-AyaT-x7p.d.ts +0 -68
  912. package/dist/validation-643vUDZW.d.ts +0 -177
  913. package/scripts/build-docs-incremental.js +0 -179
  914. package/scripts/eslint-audit.cjs +0 -123
  915. package/scripts/generate-docs.js +0 -157
  916. package/scripts/install-cursor-rules.cjs +0 -255
  917. package/scripts/install-eslint-config.cjs +0 -349
  918. package/scripts/setup-build-cache.js +0 -73
  919. package/scripts/validate-pre-publish.js +0 -145
  920. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +0 -260
  921. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +0 -224
  922. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +0 -273
  923. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +0 -99
  924. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -448
  925. package/src/__tests__/helpers/__tests__/timer-utils.test.ts +0 -371
  926. package/src/__tests__/hooks/usePermissions.test.ts +0 -268
  927. package/src/__tests__/integration/UserProfile.test.tsx +0 -124
  928. package/src/__tests__/public-recipe-view.test.ts +0 -228
  929. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +0 -220
  930. package/src/__tests__/rls-policies.test.ts +0 -471
  931. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +0 -759
  932. package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +0 -524
  933. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +0 -705
  934. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +0 -658
  935. package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +0 -192
  936. package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +0 -483
  937. package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -876
  938. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +0 -220
  939. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +0 -1474
  940. package/src/components/DataTable/__tests__/README.md +0 -145
  941. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +0 -788
  942. package/src/components/DataTable/__tests__/keyboard.test.tsx +0 -756
  943. package/src/components/DataTable/__tests__/mocks/MockRBACProvider.tsx +0 -66
  944. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +0 -730
  945. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -325
  946. package/src/components/DataTable/__tests__/styles.test.ts +0 -382
  947. package/src/components/DataTable/__tests__/test-utils/dataFactories.ts +0 -103
  948. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +0 -380
  949. package/src/components/DataTable/__tests__/test-utils.ts +0 -94
  950. package/src/components/DataTable/components/AccessDeniedPage.tsx +0 -159
  951. package/src/components/DataTable/components/ActionButtons.tsx +0 -190
  952. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +0 -160
  953. package/src/components/DataTable/components/ColumnFilter.tsx +0 -118
  954. package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +0 -114
  955. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +0 -225
  956. package/src/components/DataTable/components/DataTableLayout.tsx +0 -573
  957. package/src/components/DataTable/components/DataTableModals.tsx +0 -245
  958. package/src/components/DataTable/components/DataTableToolbar.tsx +0 -271
  959. package/src/components/DataTable/components/EditFields.tsx +0 -327
  960. package/src/components/DataTable/components/EditableRow.tsx +0 -462
  961. package/src/components/DataTable/components/EmptyState.tsx +0 -79
  962. package/src/components/DataTable/components/FilterRow.tsx +0 -141
  963. package/src/components/DataTable/components/LoadingState.tsx +0 -17
  964. package/src/components/DataTable/components/PaginationControls.tsx +0 -289
  965. package/src/components/DataTable/components/RowComponent.tsx +0 -403
  966. package/src/components/DataTable/components/SortIndicator.tsx +0 -50
  967. package/src/components/DataTable/components/UnifiedTableBody.tsx +0 -355
  968. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +0 -657
  969. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +0 -913
  970. package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +0 -572
  971. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +0 -612
  972. package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +0 -708
  973. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +0 -479
  974. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +0 -475
  975. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +0 -157
  976. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +0 -1061
  977. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +0 -437
  978. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +0 -474
  979. package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +0 -617
  980. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +0 -1093
  981. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +0 -139
  982. package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +0 -519
  983. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +0 -1004
  984. package/src/components/DataTable/components/cellValueUtils.ts +0 -40
  985. package/src/components/DataTable/components/hooks/useImportModalFocus.ts +0 -53
  986. package/src/components/DataTable/components/hooks/usePermissionTracking.ts +0 -122
  987. package/src/components/DataTable/components/index.ts +0 -16
  988. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +0 -342
  989. package/src/components/DataTable/core/ActionManager.ts +0 -235
  990. package/src/components/DataTable/core/ColumnManager.ts +0 -205
  991. package/src/components/DataTable/core/DataManager.ts +0 -188
  992. package/src/components/DataTable/core/LocalDataAdapter.ts +0 -274
  993. package/src/components/DataTable/core/PluginRegistry.ts +0 -229
  994. package/src/components/DataTable/core/StateManager.ts +0 -312
  995. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +0 -123
  996. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +0 -305
  997. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +0 -84
  998. package/src/components/DataTable/core/__tests__/DataManager.test.ts +0 -115
  999. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +0 -100
  1000. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +0 -120
  1001. package/src/components/DataTable/core/__tests__/StateManager.test.ts +0 -104
  1002. package/src/components/DataTable/core/index.ts +0 -1
  1003. package/src/components/DataTable/core/interfaces.ts +0 -338
  1004. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +0 -521
  1005. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +0 -167
  1006. package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +0 -124
  1007. package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +0 -117
  1008. package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +0 -102
  1009. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +0 -596
  1010. package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +0 -53
  1011. package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +0 -214
  1012. package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +0 -448
  1013. package/src/components/DataTable/hooks/index.ts +0 -13
  1014. package/src/components/DataTable/types.ts +0 -761
  1015. package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +0 -612
  1016. package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +0 -94
  1017. package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +0 -266
  1018. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +0 -954
  1019. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +0 -573
  1020. package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +0 -247
  1021. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +0 -570
  1022. package/src/components/DataTable/utils/__tests__/performanceUtils.test.ts +0 -470
  1023. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +0 -251
  1024. package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +0 -207
  1025. package/src/components/DataTable/utils/index.ts +0 -10
  1026. package/src/components/PublicLayout/index.ts +0 -32
  1027. package/src/components/Select/hooks/useSelectEvents.ts +0 -87
  1028. package/src/components/Select/hooks/useSelectSearch.ts +0 -91
  1029. package/src/components/Select/hooks/useSelectState.ts +0 -104
  1030. package/src/components/Select/utils/text.ts +0 -26
  1031. package/src/hooks/__tests__/ServiceHooks.test.tsx +0 -615
  1032. package/src/hooks/__tests__/hooks.integration.test.tsx +0 -607
  1033. package/src/hooks/__tests__/index.unit.test.ts +0 -220
  1034. package/src/hooks/__tests__/useApiFetch.unit.test.ts +0 -111
  1035. package/src/hooks/__tests__/useAppConfig.unit.test.ts +0 -347
  1036. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +0 -144
  1037. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +0 -776
  1038. package/src/hooks/__tests__/useDataTableState.test.ts +0 -76
  1039. package/src/hooks/__tests__/useDebounce.unit.test.ts +0 -82
  1040. package/src/hooks/__tests__/useEvents.unit.test.ts +0 -252
  1041. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +0 -1112
  1042. package/src/hooks/__tests__/useFileUrl.unit.test.ts +0 -916
  1043. package/src/hooks/__tests__/useFileUrlCache.test.ts +0 -129
  1044. package/src/hooks/__tests__/useFocusManagement.unit.test.ts +0 -230
  1045. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +0 -828
  1046. package/src/hooks/__tests__/useFormDialog.test.ts +0 -478
  1047. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +0 -446
  1048. package/src/hooks/__tests__/useIsMobile.unit.test.ts +0 -317
  1049. package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +0 -910
  1050. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -294
  1051. package/src/hooks/__tests__/useOrganisationSecurity.unit.test.tsx +0 -961
  1052. package/src/hooks/__tests__/useOrganisations.unit.test.ts +0 -369
  1053. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +0 -694
  1054. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
  1055. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
  1056. package/src/hooks/__tests__/usePreventTabReload.test.ts +0 -88
  1057. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +0 -785
  1058. package/src/hooks/__tests__/usePublicEvent.test.ts +0 -678
  1059. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +0 -630
  1060. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +0 -951
  1061. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +0 -443
  1062. package/src/hooks/__tests__/useQueryCache.test.ts +0 -144
  1063. package/src/hooks/__tests__/useRBAC.unit.test.ts +0 -236
  1064. package/src/hooks/__tests__/useSessionDraft.test.ts +0 -163
  1065. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +0 -390
  1066. package/src/hooks/__tests__/useStorage.unit.test.ts +0 -751
  1067. package/src/hooks/__tests__/useToast.unit.test.tsx +0 -481
  1068. package/src/hooks/__tests__/useZodForm.unit.test.tsx +0 -37
  1069. package/src/hooks/public/index.ts +0 -36
  1070. package/src/hooks/public/usePublicFileDisplay.ts +0 -504
  1071. package/src/hooks/useFileDisplay.ts +0 -715
  1072. package/src/providers/OrganisationProvider.tsx +0 -92
  1073. package/src/providers/__tests__/AuthProvider.test.tsx +0 -287
  1074. package/src/providers/__tests__/EventProvider.test.tsx +0 -551
  1075. package/src/providers/__tests__/InactivityProvider.test-helper.tsx +0 -65
  1076. package/src/providers/__tests__/InactivityProvider.test.tsx +0 -572
  1077. package/src/providers/__tests__/OrganisationProvider.test.tsx +0 -617
  1078. package/src/providers/__tests__/ProviderLifecycle.test.tsx +0 -424
  1079. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +0 -596
  1080. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +0 -263
  1081. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +0 -294
  1082. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +0 -434
  1083. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +0 -313
  1084. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +0 -486
  1085. package/src/rbac/__tests__/cache-invalidation.test.ts +0 -399
  1086. package/src/rbac/__tests__/engine.comprehensive.test.ts +0 -813
  1087. package/src/rbac/__tests__/isSuperAdmin.real.test.ts +0 -82
  1088. package/src/rbac/__tests__/rbac-core.test.tsx +0 -276
  1089. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -392
  1090. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +0 -258
  1091. package/src/rbac/__tests__/rbac-functions.test.ts +0 -647
  1092. package/src/rbac/__tests__/rbac-integration.test.ts +0 -524
  1093. package/src/rbac/__tests__/rbac-role-isolation.test.ts +0 -456
  1094. package/src/rbac/__tests__/scenarios.user-role.test.tsx +0 -282
  1095. package/src/rbac/audit-enhanced.ts +0 -384
  1096. package/src/rbac/compliance/database-validator.ts +0 -165
  1097. package/src/rbac/compliance/index.ts +0 -48
  1098. package/src/rbac/compliance/pattern-detector.ts +0 -553
  1099. package/src/rbac/compliance/quick-fix-suggestions.ts +0 -209
  1100. package/src/rbac/compliance/runtime-compliance.ts +0 -99
  1101. package/src/rbac/compliance/setup-validator.ts +0 -131
  1102. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +0 -975
  1103. package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +0 -248
  1104. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +0 -242
  1105. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +0 -1107
  1106. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +0 -184
  1107. package/src/rbac/components/index.ts +0 -26
  1108. package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -432
  1109. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +0 -579
  1110. package/src/rbac/hooks/index.ts +0 -34
  1111. package/src/rbac/hooks/permissions/index.ts +0 -4
  1112. package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
  1113. package/src/rbac/utils/__tests__/contextValidator.test.ts +0 -128
  1114. package/src/rbac/utils/__tests__/deep-equal.test.ts +0 -53
  1115. package/src/rbac/utils/__tests__/eventContext.test.ts +0 -433
  1116. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -490
  1117. package/src/services/__tests__/AuthService.restoreSession.test.ts +0 -39
  1118. package/src/services/__tests__/AuthService.test.ts +0 -1332
  1119. package/src/services/__tests__/BaseService.test.ts +0 -314
  1120. package/src/services/__tests__/EventService.eventColours.test.ts +0 -76
  1121. package/src/services/__tests__/EventService.test.ts +0 -1025
  1122. package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -411
  1123. package/src/services/__tests__/InactivityService.test.ts +0 -654
  1124. package/src/services/__tests__/OrganisationService.pagination.test.ts +0 -409
  1125. package/src/services/__tests__/OrganisationService.test.ts +0 -1176
  1126. package/src/theming/__tests__/parseEventColours.test.ts +0 -321
  1127. package/src/theming/__tests__/runtime.test.ts +0 -569
  1128. package/src/types/__tests__/file-reference.test.ts +0 -447
  1129. package/src/types/__tests__/guards.test.ts +0 -246
  1130. package/src/types/__tests__/organisation.roles.test.ts +0 -55
  1131. package/src/types/__tests__/organisation.test.ts +0 -1133
  1132. package/src/types/__tests__/theme.test.ts +0 -830
  1133. package/src/types/__tests__/type-validation.test.ts +0 -526
  1134. package/src/types/__tests__/validation.test.ts +0 -731
  1135. package/src/utils/__tests__/appConfig.unit.test.ts +0 -55
  1136. package/src/utils/__tests__/audit.unit.test.ts +0 -69
  1137. package/src/utils/__tests__/auth-utils.unit.test.ts +0 -70
  1138. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +0 -339
  1139. package/src/utils/__tests__/cn.unit.test.ts +0 -34
  1140. package/src/utils/__tests__/debugLogger.test.ts +0 -417
  1141. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +0 -818
  1142. package/src/utils/__tests__/dynamicUtils.unit.test.ts +0 -318
  1143. package/src/utils/__tests__/formatDate.unit.test.ts +0 -109
  1144. package/src/utils/__tests__/formatting.unit.test.ts +0 -99
  1145. package/src/utils/__tests__/index.unit.test.ts +0 -251
  1146. package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -321
  1147. package/src/utils/__tests__/logger.unit.test.ts +0 -398
  1148. package/src/utils/__tests__/organisationContext.unit.test.ts +0 -191
  1149. package/src/utils/__tests__/performanceBenchmark.test.ts +0 -175
  1150. package/src/utils/__tests__/performanceBudgets.unit.test.ts +0 -253
  1151. package/src/utils/__tests__/permissionTypes.unit.test.ts +0 -250
  1152. package/src/utils/__tests__/permissionUtils.unit.test.ts +0 -362
  1153. package/src/utils/__tests__/sanitization.unit.test.ts +0 -346
  1154. package/src/utils/__tests__/schemaUtils.unit.test.ts +0 -441
  1155. package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -335
  1156. package/src/utils/__tests__/secureErrors.unit.test.ts +0 -390
  1157. package/src/utils/__tests__/secureStorage.unit.test.ts +0 -289
  1158. package/src/utils/__tests__/security.unit.test.ts +0 -149
  1159. package/src/utils/__tests__/securityMonitor.unit.test.ts +0 -276
  1160. package/src/utils/__tests__/sessionTracking.unit.test.ts +0 -218
  1161. package/src/utils/__tests__/timezone.test.ts +0 -345
  1162. package/src/utils/__tests__/validation.unit.test.ts +0 -308
  1163. package/src/utils/__tests__/validationUtils.unit.test.ts +0 -555
  1164. package/src/utils/app/appNameResolver.simple.test.ts +0 -212
  1165. package/src/utils/file-reference/__tests__/file-reference.test.ts +0 -875
  1166. package/src/utils/google-places/index.ts +0 -26
  1167. package/src/utils/location/index.ts +0 -16
  1168. package/src/utils/persistence/__tests__/keyDerivation.test.ts +0 -135
  1169. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +0 -123
  1170. package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -332
  1171. package/src/utils/storage/__tests__/index.unit.test.ts +0 -16
  1172. package/src/utils/storage/index.ts +0 -67
  1173. package/src/utils/timezone/index.ts +0 -17
  1174. package/src/utils/validation/__tests__/csrf.test.ts +0 -105
  1175. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +0 -598
  1176. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +0 -92
  1177. package/src/utils/validation/__tests__/validationUtils.test.ts +0 -72
  1178. package/src/utils/validation/index.ts +0 -73
  1179. /package/src/components/DataTable/{components/__tests__ → ui}/COVERAGE_NOTE.md +0 -0
  1180. /package/src/components/DataTable/utils/{__tests__/COVERAGE_NOTE.md → COVERAGE_NOTE.md} +0 -0
  1181. /package/src/providers/{__tests__/README.md → README.md} +0 -0
  1182. /package/src/types/{__tests__/README.md → README.md} +0 -0
@@ -1,2816 +0,0 @@
1
- import { isRBACInitialized, setupRBAC } from './chunk-LX6U42O3.js';
2
- import { assertOrganisationId, assertUserId } from './chunk-4SXLQIZO.js';
3
- import { secureStorage } from './chunk-HF6O3O37.js';
4
- import { createLogger, logger } from './chunk-TTRFSOKR.js';
5
- import { createContext, useRef, useEffect, useState, useMemo, useContext, useReducer, useCallback } from 'react';
6
- import { AuthError } from '@supabase/supabase-js';
7
- import { jsx } from 'react/jsx-runtime';
8
-
9
- // src/services/base/BaseService.ts
10
- var BaseService = class {
11
- constructor() {
12
- this.subscribers = [];
13
- this.isInitialized = false;
14
- }
15
- /**
16
- * Subscribe to state changes
17
- * @param callback Function to call when state changes
18
- * @returns Unsubscribe function
19
- */
20
- subscribe(callback) {
21
- this.subscribers.push(callback);
22
- return () => {
23
- const index = this.subscribers.indexOf(callback);
24
- if (index > -1) {
25
- this.subscribers.splice(index, 1);
26
- }
27
- };
28
- }
29
- /**
30
- * Notify all subscribers of state changes
31
- * This triggers React re-renders
32
- */
33
- notify() {
34
- this.subscribers.forEach((callback) => {
35
- try {
36
- callback();
37
- } catch (error) {
38
- logger.error("BaseService", "Error in subscriber callback:", error);
39
- }
40
- });
41
- }
42
- /**
43
- * Initialize the service
44
- * Override in subclasses to implement initialization logic
45
- */
46
- async initialize() {
47
- if (this.isInitialized) {
48
- return;
49
- }
50
- await this.doInitialize();
51
- this.isInitialized = true;
52
- }
53
- /**
54
- * Cleanup the service
55
- * Override in subclasses to implement cleanup logic
56
- */
57
- cleanup() {
58
- this.subscribers = [];
59
- this.doCleanup();
60
- this.isInitialized = false;
61
- }
62
- /**
63
- * Check if service is initialized
64
- */
65
- getInitialized() {
66
- return this.isInitialized;
67
- }
68
- /**
69
- * Reset initialization state (allows re-initialization)
70
- * Use when dependencies change and service needs to re-initialize
71
- */
72
- resetInitialization() {
73
- this.isInitialized = false;
74
- }
75
- };
76
-
77
- // src/services/AuthService.ts
78
- var _AuthService = class _AuthService extends BaseService {
79
- // Track previous auth state to detect transitions
80
- constructor(supabaseClient, appName) {
81
- super();
82
- this.user = null;
83
- this.session = null;
84
- this.authLoading = false;
85
- this.authError = null;
86
- this.supabaseClient = null;
87
- this.authStateSubscription = null;
88
- this.sessionRestorationState = {
89
- isRestoring: false,
90
- restorationComplete: false,
91
- restorationError: null
92
- };
93
- this.restorationTimeoutId = null;
94
- // Increased timeout to handle hard refresh scenarios where localStorage access
95
- // and session restoration may take longer, especially with organisation/event context
96
- this.restorationTimeoutMs = 1e4;
97
- // 10 seconds (increased from 5)
98
- this.restorationStartTime = null;
99
- this.appName = void 0;
100
- this.errorHandler = null;
101
- this.unhandledRejectionHandler = null;
102
- this.wasAuthenticatedRef = false;
103
- this.instanceId = ++_AuthService.instanceCount;
104
- this.supabaseClient = supabaseClient;
105
- this.appName = appName;
106
- }
107
- getInstanceId() {
108
- return this.instanceId;
109
- }
110
- // Auth state getters
111
- getUser() {
112
- return this.user;
113
- }
114
- getSession() {
115
- return this.session;
116
- }
117
- isAuthenticated() {
118
- return !!(this.user && this.session);
119
- }
120
- isLoading() {
121
- return this.authLoading;
122
- }
123
- getError() {
124
- return this.authError;
125
- }
126
- getSupabaseClient() {
127
- return this.supabaseClient;
128
- }
129
- getSessionRestorationState() {
130
- return { ...this.sessionRestorationState };
131
- }
132
- // Auth methods
133
- async signIn(email, password) {
134
- if (!this.supabaseClient) {
135
- const error = new AuthError("Supabase client not available");
136
- this.authError = error;
137
- this.notify();
138
- return { user: null, session: null, error };
139
- }
140
- try {
141
- const { data, error } = await this.supabaseClient.auth.signInWithPassword({
142
- email,
143
- password: password || ""
144
- });
145
- if (error) {
146
- this.authError = error;
147
- this.user = null;
148
- this.session = null;
149
- } else {
150
- this.authError = null;
151
- this.user = data.user;
152
- this.session = data.session;
153
- if (!this.wasAuthenticatedRef && data.user) {
154
- this.clearPersistenceOnLogin(null, true);
155
- this.wasAuthenticatedRef = true;
156
- }
157
- }
158
- this.notify();
159
- return { user: data.user, session: data.session, error };
160
- } catch (error) {
161
- const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
162
- this.authError = authError;
163
- this.user = null;
164
- this.session = null;
165
- this.notify();
166
- return { user: null, session: null, error: authError };
167
- }
168
- }
169
- async signUp(email, password) {
170
- if (!this.supabaseClient) {
171
- const error = new AuthError("Supabase client not available");
172
- this.authError = error;
173
- this.notify();
174
- return { user: null, session: null, error };
175
- }
176
- try {
177
- const { data, error } = await this.supabaseClient.auth.signUp({
178
- email,
179
- password
180
- });
181
- if (error) {
182
- this.authError = error;
183
- this.user = null;
184
- this.session = null;
185
- } else {
186
- this.authError = null;
187
- this.user = data.user;
188
- this.session = data.session;
189
- if (!this.wasAuthenticatedRef && data.user) {
190
- this.clearPersistenceOnLogin(null, true);
191
- this.wasAuthenticatedRef = true;
192
- }
193
- }
194
- this.notify();
195
- return { user: data.user, session: data.session, error };
196
- } catch (error) {
197
- const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
198
- this.authError = authError;
199
- this.user = null;
200
- this.session = null;
201
- this.notify();
202
- return { user: null, session: null, error: authError };
203
- }
204
- }
205
- async signOut() {
206
- if (!this.supabaseClient) {
207
- const error = new AuthError("Supabase client not available");
208
- this.authError = error;
209
- this.notify();
210
- return { user: null, session: null, error };
211
- }
212
- try {
213
- const { error } = await this.supabaseClient.auth.signOut();
214
- try {
215
- sessionStorage.clear();
216
- } catch (storageError) {
217
- logger.warn("AuthService", "Failed to clear sessionStorage", { error: storageError });
218
- }
219
- if (error) {
220
- this.authError = error;
221
- } else {
222
- this.authError = null;
223
- this.user = null;
224
- this.session = null;
225
- }
226
- this.notify();
227
- return { user: null, session: null, error };
228
- } catch (error) {
229
- try {
230
- sessionStorage.clear();
231
- } catch (storageError) {
232
- logger.warn("AuthService", "Failed to clear sessionStorage", { error: storageError });
233
- }
234
- const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
235
- this.authError = authError;
236
- this.user = null;
237
- this.session = null;
238
- this.notify();
239
- return { user: null, session: null, error: authError };
240
- }
241
- }
242
- async resetPassword(email) {
243
- if (!this.supabaseClient) {
244
- const error = new AuthError("Supabase client not available");
245
- this.authError = error;
246
- this.notify();
247
- return { user: null, session: null, error };
248
- }
249
- try {
250
- const { error } = await this.supabaseClient.auth.resetPasswordForEmail(email);
251
- if (error) {
252
- this.authError = error;
253
- } else {
254
- this.authError = null;
255
- }
256
- this.notify();
257
- return { user: null, session: null, error };
258
- } catch (error) {
259
- const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
260
- this.authError = authError;
261
- this.notify();
262
- return { user: null, session: null, error: authError };
263
- }
264
- }
265
- async updatePassword(password) {
266
- if (!this.supabaseClient) {
267
- const error = new AuthError("Supabase client not available");
268
- this.authError = error;
269
- this.notify();
270
- return { user: null, session: null, error };
271
- }
272
- try {
273
- const { error } = await this.supabaseClient.auth.updateUser({
274
- password
275
- });
276
- if (error) {
277
- this.authError = error;
278
- } else {
279
- this.authError = null;
280
- }
281
- this.notify();
282
- return { user: null, session: null, error };
283
- } catch (error) {
284
- const authError = error;
285
- this.authError = authError;
286
- this.notify();
287
- return { user: null, session: null, error: authError };
288
- }
289
- }
290
- async refreshSession() {
291
- if (!this.supabaseClient) {
292
- const error = new AuthError("Supabase client not available");
293
- this.authError = error;
294
- this.notify();
295
- return { user: null, session: null, error };
296
- }
297
- try {
298
- const { data, error } = await this.supabaseClient.auth.refreshSession();
299
- if (error) {
300
- this.authError = error;
301
- this.user = null;
302
- this.session = null;
303
- } else {
304
- this.authError = null;
305
- if (data?.user && data?.session) {
306
- this.user = data.user;
307
- this.session = data.session;
308
- } else {
309
- this.user = null;
310
- this.session = null;
311
- }
312
- }
313
- this.notify();
314
- return {
315
- user: data?.user && data?.session ? data.user : null,
316
- session: data?.session ?? null,
317
- error
318
- };
319
- } catch (error) {
320
- const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
321
- this.authError = authError;
322
- this.user = null;
323
- this.session = null;
324
- this.notify();
325
- return { user: null, session: null, error: authError };
326
- }
327
- }
328
- // Lifecycle methods
329
- async initialize() {
330
- await super.initialize();
331
- this.authLoading = true;
332
- this.notify();
333
- await this.setupAuthStateListener();
334
- await this.restoreSession();
335
- }
336
- cleanup() {
337
- if (this.authStateSubscription) {
338
- this.authStateSubscription.unsubscribe();
339
- this.authStateSubscription = null;
340
- }
341
- this.clearRestorationTimeout();
342
- this.restorationStartTime = null;
343
- this.sessionRestorationState = {
344
- isRestoring: false,
345
- restorationComplete: false,
346
- restorationError: null
347
- };
348
- this.authLoading = false;
349
- super.cleanup();
350
- }
351
- async doInitialize() {
352
- this.setupErrorHandlers();
353
- }
354
- doCleanup() {
355
- this.removeErrorHandlers();
356
- }
357
- startSessionRestoration() {
358
- this.clearRestorationTimeout();
359
- this.sessionRestorationState = {
360
- isRestoring: true,
361
- restorationComplete: false,
362
- restorationError: null
363
- };
364
- this.authLoading = true;
365
- this.restorationStartTime = Date.now();
366
- this.notify();
367
- this.restorationTimeoutId = setTimeout(() => {
368
- logger.warn("AuthService", "Session restoration timed out after", this.restorationTimeoutMs, "ms");
369
- const timeoutError = new Error(`Session restoration timed out after ${this.restorationTimeoutMs}ms`);
370
- timeoutError.name = "SessionRestorationTimeoutError";
371
- this.finishSessionRestoration(timeoutError);
372
- }, this.restorationTimeoutMs);
373
- }
374
- finishSessionRestoration(error) {
375
- if (!this.sessionRestorationState.isRestoring && !error) {
376
- return;
377
- }
378
- this.clearRestorationTimeout();
379
- const completedAt = Date.now();
380
- this.restorationStartTime ? completedAt - this.restorationStartTime : null;
381
- this.restorationStartTime = null;
382
- const restorationComplete = !error;
383
- this.sessionRestorationState = {
384
- isRestoring: false,
385
- restorationComplete,
386
- restorationError: error ?? null
387
- };
388
- this.authLoading = false;
389
- if (error) {
390
- logger.warn("AuthService", "Session restoration finished with error:", error);
391
- }
392
- this.notify();
393
- }
394
- clearRestorationTimeout() {
395
- if (this.restorationTimeoutId) {
396
- clearTimeout(this.restorationTimeoutId);
397
- this.restorationTimeoutId = null;
398
- }
399
- }
400
- /**
401
- * Clear pace-core persistence entries from sessionStorage
402
- * This includes dialog, form, and datatable persistence
403
- *
404
- * @param userId - Optional user ID to clear only that user's persistence.
405
- * If not provided, clears all pace-core persistence (for user changes).
406
- * @param clearUnscoped - If true, also clears old unscoped keys (without :user: prefix)
407
- */
408
- clearPersistenceOnLogin(userId, clearUnscoped = true) {
409
- if (typeof window === "undefined" || !window.sessionStorage) {
410
- return;
411
- }
412
- try {
413
- const keysToRemove = [];
414
- for (let i = 0; i < sessionStorage.length; i++) {
415
- const key = sessionStorage.key(i);
416
- if (key && (key.startsWith("pace-core:draft:") || key.startsWith("pace-core:dialog:"))) {
417
- if (userId && !key.includes(`:user:${userId}`)) {
418
- if (clearUnscoped && !key.includes(":user:")) {
419
- keysToRemove.push(key);
420
- }
421
- continue;
422
- }
423
- keysToRemove.push(key);
424
- }
425
- }
426
- keysToRemove.forEach((key) => {
427
- try {
428
- sessionStorage.removeItem(key);
429
- } catch (error) {
430
- logger.warn("AuthService", `Failed to remove persistence key: ${key}`, error);
431
- }
432
- });
433
- } catch (error) {
434
- logger.warn("AuthService", `Failed to clear persistence [ID:${this.instanceId}]:`, error);
435
- }
436
- }
437
- async setupAuthStateListener() {
438
- if (!this.supabaseClient) {
439
- this.authLoading = false;
440
- this.notify();
441
- return;
442
- }
443
- try {
444
- const subscription = this.supabaseClient.auth.onAuthStateChange(
445
- (event, session) => {
446
- try {
447
- const wasAuthenticated = this.wasAuthenticatedRef;
448
- const isNowAuthenticated = !!session?.user;
449
- const previousUserId = this.user?.id || null;
450
- const newUserId = session?.user?.id || null;
451
- const userChanged = previousUserId !== null && newUserId !== null && previousUserId !== newUserId;
452
- if (event === "SIGNED_OUT") {
453
- this.session = null;
454
- this.user = null;
455
- this.authError = null;
456
- this.wasAuthenticatedRef = false;
457
- if (session?.user) {
458
- this.trackSession("logout", session).catch((err) => {
459
- logger.warn("AuthService", `Failed to track logout session [ID:${this.instanceId}]:`, err);
460
- });
461
- }
462
- } else if (event === "SIGNED_IN" || event === "TOKEN_REFRESHED") {
463
- this.session = session;
464
- this.user = session?.user ?? null;
465
- if (session?.user) {
466
- this.authError = null;
467
- }
468
- if (!wasAuthenticated && isNowAuthenticated && event === "SIGNED_IN") {
469
- this.clearPersistenceOnLogin(null, true);
470
- } else if (userChanged && previousUserId) {
471
- this.clearPersistenceOnLogin(previousUserId, true);
472
- }
473
- this.wasAuthenticatedRef = isNowAuthenticated;
474
- if (event === "SIGNED_IN" && session?.user) {
475
- this.trackSession("login", session).catch((err) => {
476
- logger.warn("AuthService", `Failed to track login session [ID:${this.instanceId}]:`, err);
477
- });
478
- }
479
- } else if (event === "INITIAL_SESSION") {
480
- if (session) {
481
- const previousUserId2 = this.user?.id || null;
482
- const newUserId2 = session.user?.id || null;
483
- const userChanged2 = previousUserId2 !== null && newUserId2 !== null && previousUserId2 !== newUserId2;
484
- this.session = session;
485
- this.user = session.user ?? null;
486
- this.authError = null;
487
- if (userChanged2 && previousUserId2) {
488
- this.clearPersistenceOnLogin(previousUserId2, true);
489
- } else if (!wasAuthenticated && !!session.user) {
490
- this.clearPersistenceOnLogin(null, true);
491
- }
492
- this.wasAuthenticatedRef = !!session.user;
493
- const hasTimeoutError = this.sessionRestorationState.restorationError?.name === "SessionRestorationTimeoutError";
494
- if (this.sessionRestorationState.isRestoring || this.sessionRestorationState.restorationError || hasTimeoutError && session) {
495
- this.finishSessionRestoration();
496
- }
497
- } else {
498
- this.wasAuthenticatedRef = false;
499
- if (this.sessionRestorationState.isRestoring) {
500
- this.finishSessionRestoration();
501
- }
502
- }
503
- this.authLoading = false;
504
- this.notify();
505
- return;
506
- }
507
- this.authLoading = false;
508
- this.notify();
509
- } catch (error) {
510
- logger.warn("AuthService", `Error in auth state change handler [ID:${this.instanceId}]:`, error);
511
- this.authLoading = false;
512
- this.notify();
513
- }
514
- }
515
- );
516
- this.authStateSubscription = subscription.data.subscription;
517
- } catch (error) {
518
- logger.error("AuthService", "Failed to setup auth state listener:", error);
519
- throw error;
520
- }
521
- }
522
- async restoreSession() {
523
- if (!this.supabaseClient) {
524
- const error = new Error("Supabase client not available during session restoration");
525
- logger.error("AuthService", "Unable to restore session:", error);
526
- this.finishSessionRestoration(error);
527
- return;
528
- }
529
- this.startSessionRestoration();
530
- try {
531
- let currentSession = null;
532
- let sessionError = null;
533
- try {
534
- const { data, error } = await this.supabaseClient.auth.getSession();
535
- currentSession = data?.session ?? null;
536
- sessionError = error ?? null;
537
- } catch (error) {
538
- currentSession = null;
539
- sessionError = null;
540
- }
541
- if (sessionError) {
542
- this.authError = sessionError;
543
- try {
544
- const { data, error } = await this.supabaseClient.auth.getUser();
545
- const currentUser = data?.user ?? null;
546
- const userError = error ?? null;
547
- if (currentUser) {
548
- this.user = currentUser;
549
- this.session = null;
550
- }
551
- if (userError && !this.authError) {
552
- this.authError = userError;
553
- }
554
- } catch (getUserError) {
555
- }
556
- }
557
- if (currentSession) {
558
- this.session = currentSession;
559
- this.user = currentSession.user;
560
- this.authError = null;
561
- } else if (!sessionError) {
562
- this.session = null;
563
- this.user = null;
564
- this.authError = null;
565
- }
566
- setTimeout(() => {
567
- if (this.sessionRestorationState.isRestoring && !this.sessionRestorationState.restorationComplete) {
568
- logger.debug("AuthService", "INITIAL_SESSION event did not fire, finishing restoration");
569
- this.finishSessionRestoration();
570
- }
571
- }, 100);
572
- } catch (error) {
573
- const restorationError = error instanceof Error ? error : new Error("Unknown error during auth initialization");
574
- logger.error("AuthService", "Error during auth initialization:", restorationError);
575
- if (restorationError instanceof AuthError) {
576
- this.authError = restorationError;
577
- }
578
- this.finishSessionRestoration(restorationError);
579
- }
580
- }
581
- /**
582
- * Automatically track user session using rbac_session_track
583
- * This method is called automatically on SIGNED_IN and SIGNED_OUT events.
584
- * It's non-blocking and failures are logged as warnings.
585
- */
586
- async trackSession(sessionType, session) {
587
- if (!this.supabaseClient || !session?.user) {
588
- return;
589
- }
590
- try {
591
- let appId = void 0;
592
- if (this.appName) {
593
- const { data, error: error2 } = await this.supabaseClient.from("rbac_apps").select("id").eq("name", this.appName).eq("is_active", true).single();
594
- if (!error2 && data) {
595
- appId = data.id;
596
- }
597
- }
598
- const ipAddress = void 0;
599
- const userAgent = typeof navigator !== "undefined" ? navigator.userAgent : void 0;
600
- const deviceFingerprint = void 0;
601
- const { error } = await this.supabaseClient.rpc("rbac_session_track", {
602
- p_user_id: session.user.id,
603
- p_session_type: sessionType,
604
- p_event_id: null,
605
- // Event ID should come from context, not auth service
606
- p_app_id: appId,
607
- p_ip_address: ipAddress,
608
- p_user_agent: userAgent,
609
- p_device_fingerprint: deviceFingerprint
610
- });
611
- if (error) {
612
- logger.warn("AuthService", `Failed to track ${sessionType} session:`, error);
613
- }
614
- } catch (error) {
615
- logger.warn("AuthService", `Error tracking ${sessionType} session:`, error);
616
- }
617
- }
618
- setupErrorHandlers() {
619
- if (typeof window === "undefined") return;
620
- this.errorHandler = (event) => {
621
- if (event.error?.message?.includes("AuthSessionMissingError") || event.error?.message?.includes("Auth session missing")) {
622
- logger.warn("AuthService", "Suppressing AuthSessionMissingError during logout");
623
- event.preventDefault();
624
- return false;
625
- }
626
- };
627
- this.unhandledRejectionHandler = (event) => {
628
- if (event.reason?.message?.includes("AuthSessionMissingError") || event.reason?.message?.includes("Auth session missing")) {
629
- logger.warn("AuthService", "Suppressing unhandled AuthSessionMissingError");
630
- event.preventDefault();
631
- return false;
632
- }
633
- };
634
- window.addEventListener("error", this.errorHandler);
635
- window.addEventListener("unhandledrejection", this.unhandledRejectionHandler);
636
- }
637
- removeErrorHandlers() {
638
- if (typeof window === "undefined") return;
639
- if (this.errorHandler) {
640
- window.removeEventListener("error", this.errorHandler);
641
- this.errorHandler = null;
642
- }
643
- if (this.unhandledRejectionHandler) {
644
- window.removeEventListener("unhandledrejection", this.unhandledRejectionHandler);
645
- this.unhandledRejectionHandler = null;
646
- }
647
- }
648
- };
649
- _AuthService.instanceCount = 0;
650
- var AuthService = _AuthService;
651
- var AuthServiceContext = createContext(null);
652
- function AuthServiceProvider({ children, supabaseClient, appName }) {
653
- const authServiceRef = useRef(null);
654
- if (!authServiceRef.current) {
655
- authServiceRef.current = new AuthService(supabaseClient, appName);
656
- }
657
- const authService = authServiceRef.current;
658
- useEffect(() => {
659
- }, [authService, supabaseClient, appName]);
660
- const [sessionRestoration, setSessionRestoration] = useState(
661
- () => authService.getSessionRestorationState()
662
- );
663
- useEffect(() => {
664
- const unsubscribe = authService.subscribe(() => {
665
- const restorationState = authService.getSessionRestorationState();
666
- setSessionRestoration(restorationState);
667
- });
668
- return () => {
669
- unsubscribe();
670
- };
671
- }, [authService]);
672
- useEffect(() => {
673
- authService.initialize().catch((error) => {
674
- logger.error("AuthServiceProvider", "Failed to initialize auth service:", error);
675
- });
676
- return () => {
677
- authService.cleanup();
678
- };
679
- }, [authService]);
680
- const contextValue = useMemo(() => ({
681
- authService,
682
- sessionRestoration
683
- }), [authService, sessionRestoration]);
684
- return /* @__PURE__ */ jsx(AuthServiceContext.Provider, { value: contextValue, children });
685
- }
686
-
687
- // src/services/OrganisationService.ts
688
- var _OrganisationService = class _OrganisationService extends BaseService {
689
- constructor(supabaseClient, user, session) {
690
- super();
691
- this._selectedOrganisation = null;
692
- this._organisations = [];
693
- this._userMemberships = [];
694
- this._roleMapState = /* @__PURE__ */ new Map();
695
- this._isLoading = false;
696
- this._error = null;
697
- this._isSuperAdmin = false;
698
- // Cache super admin status
699
- this._isContextReady = false;
700
- this.retryCount = 0;
701
- // Dependencies
702
- this.supabaseClient = null;
703
- this.user = null;
704
- this.session = null;
705
- // Internal state management
706
- this.isLoadingRef = false;
707
- this.lastLoadTimeRef = 0;
708
- this.hasFailedRef = false;
709
- this.abortControllerRef = null;
710
- this.instanceId = ++_OrganisationService.instanceCount;
711
- this.supabaseClient = supabaseClient;
712
- this.user = user;
713
- this.session = session;
714
- }
715
- getInstanceId() {
716
- return this.instanceId;
717
- }
718
- // Interface implementation
719
- getSelectedOrganisation() {
720
- return this._selectedOrganisation;
721
- }
722
- getOrganisations() {
723
- return this._organisations;
724
- }
725
- getUserMemberships() {
726
- return this._userMemberships;
727
- }
728
- isLoading() {
729
- return this._isLoading;
730
- }
731
- getError() {
732
- return this._error;
733
- }
734
- hasValidOrganisationContext() {
735
- return !!(this._selectedOrganisation && !this._isLoading && !this._error && this._isContextReady);
736
- }
737
- isContextReady() {
738
- return this._isContextReady;
739
- }
740
- // Additional methods for testing
741
- setSelectedOrganisation(organisation) {
742
- if (organisation && this._organisations.length > 0) {
743
- if (!this._isSuperAdmin) {
744
- const isValidOrg = this._organisations.some((org) => org.id === organisation.id);
745
- if (!isValidOrg) {
746
- logger.warn("OrganisationService", "Attempted to set invalid organisation - not in user's accessible organisations", {
747
- organisationId: organisation.id,
748
- organisationName: organisation.name,
749
- accessibleOrgIds: this._organisations.map((o) => o.id)
750
- });
751
- return;
752
- }
753
- }
754
- }
755
- this._selectedOrganisation = organisation;
756
- if (organisation) {
757
- localStorage.setItem("pace-core-selected-organisation", JSON.stringify(organisation));
758
- this.setDatabaseOrganisationContext(organisation);
759
- } else {
760
- localStorage.removeItem("pace-core-selected-organisation");
761
- this._isContextReady = false;
762
- }
763
- this.notify();
764
- }
765
- // For testing: expose dependencies
766
- getDependencies() {
767
- return {
768
- user: this.user,
769
- session: this.session,
770
- supabaseClient: this.supabaseClient
771
- };
772
- }
773
- // For testing: manually set state
774
- setTestState(organisations, memberships, roleMap, selectedOrg = null) {
775
- this._organisations = organisations;
776
- this._userMemberships = memberships;
777
- this._roleMapState = roleMap;
778
- if (selectedOrg) {
779
- this._selectedOrganisation = selectedOrg;
780
- } else if (organisations.length > 0) {
781
- this._selectedOrganisation = organisations[0];
782
- }
783
- this._isLoading = false;
784
- this._error = null;
785
- this.notify();
786
- }
787
- // Update dependencies
788
- updateDependencies(user, session) {
789
- const previousUserId = this.user?.id || null;
790
- const newUserId = user?.id || null;
791
- const userChanged = previousUserId !== newUserId;
792
- const needsRetry = this._error !== null && !this.isLoadingRef;
793
- const isEmpty = newUserId !== null && this._organisations.length === 0 && !this.isLoadingRef;
794
- if (userChanged || needsRetry || isEmpty) {
795
- if (userChanged) ; else if (needsRetry) {
796
- logger.debug("OrganisationService", `Previous error detected [ID:${this.instanceId}], retrying initialization`);
797
- } else if (isEmpty) {
798
- logger.debug("OrganisationService", `No organisations found [ID:${this.instanceId}], retrying initialization`);
799
- }
800
- this._isSuperAdmin = false;
801
- this.resetInitialization();
802
- if (userChanged) {
803
- this._organisations = [];
804
- this._userMemberships = [];
805
- this._roleMapState = /* @__PURE__ */ new Map();
806
- this._selectedOrganisation = null;
807
- this._isContextReady = false;
808
- }
809
- this.lastLoadTimeRef = 0;
810
- }
811
- this.user = user;
812
- this.session = session;
813
- this.notify();
814
- }
815
- // Organisation methods
816
- async switchOrganisation(orgId) {
817
- if (!this.validateOrganisationAccess(orgId)) {
818
- throw new Error(`User does not have access to organisation ${orgId}`);
819
- }
820
- const targetOrg = this._organisations.find((org) => org.id === orgId);
821
- if (!targetOrg) {
822
- throw new Error(`Organisation ${orgId} not found in user's organisations`);
823
- }
824
- this._selectedOrganisation = targetOrg;
825
- localStorage.setItem("pace-core-selected-organisation", JSON.stringify(targetOrg));
826
- await this.setDatabaseOrganisationContext(targetOrg);
827
- this.notify();
828
- }
829
- getUserRole(orgId) {
830
- const targetOrgId = orgId || this._selectedOrganisation?.id;
831
- if (!targetOrgId) return "no_access";
832
- return this._roleMapState.get(targetOrgId) || "no_access";
833
- }
834
- validateOrganisationAccess(orgId) {
835
- return this._userMemberships.some(
836
- (m) => m.organisation_id === orgId && m.status === "active" && m.revoked_at === null
837
- );
838
- }
839
- async refreshOrganisations() {
840
- if (!this.user || !this.session || !this.supabaseClient) return;
841
- this._isLoading = true;
842
- this.notify();
843
- await this.loadUserOrganisations();
844
- }
845
- ensureOrganisationContext() {
846
- if (!this._selectedOrganisation) {
847
- throw new Error("Organisation context is required but not available");
848
- }
849
- return this._selectedOrganisation;
850
- }
851
- isOrganisationSecure() {
852
- return !!(this._selectedOrganisation && this.user);
853
- }
854
- getPrimaryOrganisation() {
855
- const rolePriority = ["org_admin", "leader", "member"];
856
- for (const role of rolePriority) {
857
- const membership = this._userMemberships.find((m) => m.role === role);
858
- if (membership) {
859
- return this._organisations.find((org) => org.id === membership.organisation_id) || null;
860
- }
861
- }
862
- return null;
863
- }
864
- buildOrganisationHierarchy(orgs) {
865
- const orgMap = /* @__PURE__ */ new Map();
866
- orgs.forEach((org) => orgMap.set(org.id, org));
867
- const roots = [];
868
- orgs.forEach((org) => {
869
- if (!org.parent_id) {
870
- roots.push({
871
- organisation: org,
872
- children: [],
873
- depth: 0
874
- });
875
- }
876
- });
877
- return roots;
878
- }
879
- // Lifecycle methods
880
- async initialize() {
881
- if (!this.user) {
882
- return;
883
- }
884
- await super.initialize();
885
- if (!this.isLoadingRef) {
886
- await this.loadUserOrganisations();
887
- }
888
- }
889
- cleanup() {
890
- this.isLoadingRef = false;
891
- this.hasFailedRef = false;
892
- this.lastLoadTimeRef = 0;
893
- if (this.abortControllerRef) {
894
- this.abortControllerRef = null;
895
- }
896
- this._selectedOrganisation = null;
897
- this._organisations = [];
898
- this._userMemberships = [];
899
- this._roleMapState = /* @__PURE__ */ new Map();
900
- this._isLoading = false;
901
- this._error = null;
902
- this._isContextReady = false;
903
- super.cleanup();
904
- }
905
- async doInitialize() {
906
- }
907
- doCleanup() {
908
- }
909
- async setDatabaseOrganisationContext(organisation) {
910
- this._isContextReady = true;
911
- this.notify();
912
- }
913
- async loadUserOrganisations() {
914
- if (!this.user || !this.session || !this.supabaseClient) {
915
- this._selectedOrganisation = null;
916
- this._organisations = [];
917
- this._userMemberships = [];
918
- this._isLoading = false;
919
- this._error = null;
920
- this.notify();
921
- return;
922
- }
923
- if (this.isLoadingRef) {
924
- this._isLoading = true;
925
- this.notify();
926
- return;
927
- }
928
- const now = Date.now();
929
- if (this._organisations.length > 0 && now - this.lastLoadTimeRef < 2e3) {
930
- if (this._organisations.length > 0 || this._selectedOrganisation) {
931
- this._isLoading = false;
932
- } else {
933
- this._isLoading = true;
934
- }
935
- this.notify();
936
- return;
937
- }
938
- if (this.abortControllerRef) {
939
- this.abortControllerRef.abort();
940
- }
941
- this.abortControllerRef = new AbortController();
942
- const abortSignal = this.abortControllerRef.signal;
943
- this.lastLoadTimeRef = now;
944
- this.isLoadingRef = true;
945
- this._isLoading = true;
946
- this._error = null;
947
- this.notify();
948
- try {
949
- let memberships, membershipError, organisations = [];
950
- try {
951
- if (abortSignal.aborted) {
952
- throw new Error("Request aborted");
953
- }
954
- const { data: rolesData, error: rolesError } = await this.supabaseClient.from("rbac_organisation_roles").select(`
955
- id,
956
- user_id,
957
- organisation_id,
958
- role,
959
- status,
960
- granted_at,
961
- granted_by,
962
- revoked_at,
963
- revoked_by,
964
- notes,
965
- created_at,
966
- updated_at,
967
- core_organisations!inner(
968
- id,
969
- name,
970
- display_name,
971
- subscription_tier,
972
- settings,
973
- is_active,
974
- parent_id,
975
- created_at,
976
- updated_at
977
- )
978
- `).eq("user_id", this.user.id).eq("status", "active").is("revoked_at", null);
979
- if (rolesError) {
980
- logger.error("OrganisationService", "Error loading organisation roles:", rolesError);
981
- throw rolesError;
982
- }
983
- memberships = rolesData?.map((m) => ({
984
- ...m,
985
- user_id: assertUserId(m.user_id),
986
- organisation_id: assertOrganisationId(m.organisation_id)
987
- })) || [];
988
- const organisationsMap = /* @__PURE__ */ new Map();
989
- rolesData?.forEach((role) => {
990
- const orgData = role.core_organisations;
991
- if (orgData && role.organisation_id && !organisationsMap.has(role.organisation_id)) {
992
- organisationsMap.set(role.organisation_id, {
993
- id: orgData.id,
994
- name: orgData.name,
995
- display_name: orgData.display_name,
996
- subscription_tier: orgData.subscription_tier,
997
- settings: orgData.settings,
998
- is_active: orgData.is_active,
999
- parent_id: orgData.parent_id,
1000
- created_at: orgData.created_at,
1001
- updated_at: orgData.updated_at
1002
- });
1003
- }
1004
- });
1005
- organisations = Array.from(organisationsMap.values());
1006
- } catch (queryError) {
1007
- if (queryError instanceof Error) {
1008
- membershipError = queryError;
1009
- } else if (queryError && typeof queryError === "object" && "message" in queryError) {
1010
- membershipError = new Error(String(queryError.message));
1011
- } else {
1012
- membershipError = new Error(String(queryError));
1013
- }
1014
- logger.error("OrganisationService", "Error loading organisation roles:", membershipError);
1015
- throw membershipError;
1016
- }
1017
- let userIsSuperAdmin = false;
1018
- if (this.user?.id) {
1019
- try {
1020
- const { isSuperAdmin: checkSuperAdmin, isRBACInitialized: isRBACInitialized2, setupRBAC: setupRBAC2 } = await import('./api-7P7DI652.js');
1021
- if (!isRBACInitialized2() && this.supabaseClient) {
1022
- setupRBAC2(this.supabaseClient);
1023
- }
1024
- if (isRBACInitialized2()) {
1025
- userIsSuperAdmin = await checkSuperAdmin(this.user.id);
1026
- } else {
1027
- userIsSuperAdmin = false;
1028
- }
1029
- this._isSuperAdmin = userIsSuperAdmin;
1030
- } catch (error) {
1031
- logger.warn("OrganisationService", "Failed to check super admin status", { error });
1032
- this._isSuperAdmin = false;
1033
- }
1034
- } else {
1035
- this._isSuperAdmin = false;
1036
- }
1037
- if (!memberships || memberships.length === 0) {
1038
- if (userIsSuperAdmin) {
1039
- this._organisations = [];
1040
- this._userMemberships = [];
1041
- this._isLoading = false;
1042
- this._error = null;
1043
- this._isContextReady = true;
1044
- this.notify();
1045
- return;
1046
- }
1047
- throw new Error("User has no active organisation memberships");
1048
- }
1049
- if (!organisations || organisations.length === 0) {
1050
- if (userIsSuperAdmin) {
1051
- this._organisations = [];
1052
- this._userMemberships = [];
1053
- this._isLoading = false;
1054
- this._error = null;
1055
- this._isContextReady = true;
1056
- this.notify();
1057
- return;
1058
- }
1059
- throw new Error("No organisations found in role data");
1060
- }
1061
- const roleMap = /* @__PURE__ */ new Map();
1062
- memberships?.forEach((membership) => {
1063
- roleMap.set(membership.organisation_id, membership.role);
1064
- });
1065
- const orgs = organisations;
1066
- const activeOrgs = orgs.filter((org) => org.is_active);
1067
- if (activeOrgs.length === 0) {
1068
- if (userIsSuperAdmin) {
1069
- this._organisations = [];
1070
- this._userMemberships = [];
1071
- this._isLoading = false;
1072
- this._error = null;
1073
- this._isContextReady = true;
1074
- this.notify();
1075
- return;
1076
- }
1077
- throw new Error("User has no access to active organisations");
1078
- }
1079
- const sortedOrgs = [...activeOrgs].sort((a, b) => {
1080
- const nameA = (a.display_name || a.name || "").toLowerCase();
1081
- const nameB = (b.display_name || b.name || "").toLowerCase();
1082
- return nameA.localeCompare(nameB);
1083
- });
1084
- this._organisations = sortedOrgs;
1085
- this._userMemberships = memberships;
1086
- this._roleMapState = roleMap;
1087
- let initialOrg = null;
1088
- let selectionMethod = "first";
1089
- try {
1090
- const persistedOrgString = localStorage.getItem("pace-core-selected-organisation");
1091
- if (persistedOrgString) {
1092
- const persistedOrg = JSON.parse(persistedOrgString);
1093
- if (persistedOrg.id && typeof persistedOrg.id === "string" && persistedOrg.id.trim() !== "") {
1094
- const validPersistedOrg = activeOrgs.find((org) => org.id === persistedOrg.id);
1095
- if (validPersistedOrg) {
1096
- initialOrg = validPersistedOrg;
1097
- selectionMethod = "persisted";
1098
- } else {
1099
- localStorage.removeItem("pace-core-selected-organisation");
1100
- }
1101
- } else {
1102
- localStorage.removeItem("pace-core-selected-organisation");
1103
- }
1104
- }
1105
- } catch (storageError) {
1106
- localStorage.removeItem("pace-core-selected-organisation");
1107
- }
1108
- if (!initialOrg) {
1109
- const adminMembership = memberships.find((m) => m.role === "org_admin");
1110
- if (adminMembership) {
1111
- const foundOrg = organisations.find((org) => org.id === adminMembership.organisation_id);
1112
- if (foundOrg) {
1113
- initialOrg = foundOrg;
1114
- selectionMethod = "admin";
1115
- }
1116
- }
1117
- }
1118
- if (!initialOrg) {
1119
- initialOrg = activeOrgs[0];
1120
- selectionMethod = "first";
1121
- }
1122
- if (!initialOrg) {
1123
- throw new Error("No valid organisation found for user");
1124
- }
1125
- const currentSelectedOrg = this._selectedOrganisation;
1126
- if (currentSelectedOrg && !activeOrgs.some((org) => org.id === currentSelectedOrg.id)) {
1127
- logger.warn("OrganisationService", "Current selected organisation is no longer valid, resetting", {
1128
- invalidOrgId: currentSelectedOrg.id,
1129
- validOrgIds: activeOrgs.map((o) => o.id)
1130
- });
1131
- this._selectedOrganisation = null;
1132
- }
1133
- this._selectedOrganisation = initialOrg;
1134
- localStorage.setItem("pace-core-selected-organisation", JSON.stringify(initialOrg));
1135
- await this.setDatabaseOrganisationContext(initialOrg);
1136
- this.retryCount = 0;
1137
- this.hasFailedRef = false;
1138
- } catch (err) {
1139
- const error = err;
1140
- if (error.message !== "User has no access to active organisations") {
1141
- logger.error("OrganisationService", "Failed to load organisations:", err);
1142
- }
1143
- this._error = error;
1144
- this.retryCount = this.retryCount + 1;
1145
- this.hasFailedRef = true;
1146
- this.clearAllCachedData();
1147
- this._isContextReady = true;
1148
- } finally {
1149
- this.isLoadingRef = false;
1150
- this._isLoading = false;
1151
- this.abortControllerRef = null;
1152
- this.notify();
1153
- }
1154
- }
1155
- clearAllCachedData() {
1156
- localStorage.removeItem("pace-core-selected-organisation");
1157
- localStorage.removeItem("pace-core-organisation-context");
1158
- this._selectedOrganisation = null;
1159
- this._organisations = [];
1160
- this._userMemberships = [];
1161
- this._roleMapState = /* @__PURE__ */ new Map();
1162
- this.retryCount = 0;
1163
- this._isContextReady = false;
1164
- }
1165
- };
1166
- _OrganisationService.instanceCount = 0;
1167
- var OrganisationService = _OrganisationService;
1168
- var OrganisationServiceContext = createContext(null);
1169
- function OrganisationServiceProvider({
1170
- children,
1171
- supabaseClient,
1172
- user,
1173
- session
1174
- }) {
1175
- const organisationServiceRef = useRef(null);
1176
- if (!organisationServiceRef.current) {
1177
- organisationServiceRef.current = new OrganisationService(supabaseClient, user, session);
1178
- }
1179
- const organisationService = organisationServiceRef.current;
1180
- useEffect(() => {
1181
- organisationService.updateDependencies(user, session);
1182
- let isMounted = true;
1183
- organisationService.initialize().catch((error) => {
1184
- if (isMounted) {
1185
- const errorMessage = error instanceof Error ? error.message : String(error);
1186
- if (errorMessage === "User has no access to active organisations") {
1187
- logger.warn("OrganisationServiceProvider", "User has no active organisations (this is expected for users without organisation access):", error);
1188
- } else {
1189
- logger.error("OrganisationServiceProvider", "Failed to initialize organisation service:", error);
1190
- }
1191
- }
1192
- });
1193
- return () => {
1194
- isMounted = false;
1195
- };
1196
- }, [organisationService, user, session]);
1197
- useEffect(() => {
1198
- return () => {
1199
- organisationService.cleanup();
1200
- };
1201
- }, [organisationService]);
1202
- const contextValue = useMemo(() => ({
1203
- organisationService
1204
- }), [organisationService]);
1205
- return /* @__PURE__ */ jsx(OrganisationServiceContext.Provider, { value: contextValue, children });
1206
- }
1207
-
1208
- // src/services/EventService.ts
1209
- var _EventService = class _EventService extends BaseService {
1210
- constructor(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId) {
1211
- super();
1212
- this.events = [];
1213
- this.selectedEvent = null;
1214
- this._isLoading = false;
1215
- // Start as false to avoid blocking UI
1216
- this.error = null;
1217
- // Dependencies
1218
- this.supabaseClient = null;
1219
- this.user = null;
1220
- this.session = null;
1221
- this.appName = "";
1222
- this.selectedOrganisation = null;
1223
- this.setSelectedEventId = null;
1224
- this.isSuperAdmin = false;
1225
- // Track super admin status for conditional validation
1226
- // App config removed - scope is now page-level only (rbac_app_pages.scope_type)
1227
- // Internal state management
1228
- this.isInitializedRef = false;
1229
- this.isFetchingRef = false;
1230
- this.hasAutoSelectedRef = false;
1231
- this.userClearedEventRef = false;
1232
- this.instanceId = ++_EventService.instanceCount;
1233
- this.supabaseClient = supabaseClient;
1234
- this.user = user;
1235
- this.session = session;
1236
- this.appName = appName;
1237
- this.selectedOrganisation = selectedOrganisation;
1238
- this.setSelectedEventId = setSelectedEventId;
1239
- }
1240
- getInstanceId() {
1241
- return this.instanceId;
1242
- }
1243
- // Helper method to get user-scoped storage key
1244
- getStorageKey(userId) {
1245
- if (!userId) {
1246
- return "pace-core-selected-event-no-user";
1247
- }
1248
- return `pace-core-selected-event-${userId}`;
1249
- }
1250
- // Update dependencies
1251
- async updateDependencies(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId) {
1252
- const previousOrgId = this.selectedOrganisation?.id;
1253
- const newOrgId = selectedOrganisation?.id;
1254
- const previousUserId = this.user?.id || null;
1255
- const newUserId = user?.id || null;
1256
- this.appName;
1257
- if (previousUserId !== newUserId) {
1258
- if (previousUserId !== null) {
1259
- await this.clearEventSelectionForUser(previousUserId);
1260
- }
1261
- if (newUserId === null) {
1262
- this.selectedEvent = null;
1263
- this.setSelectedEventId?.(null);
1264
- }
1265
- this.resetInitialization();
1266
- this.isInitializedRef = false;
1267
- this.isFetchingRef = false;
1268
- this.userClearedEventRef = false;
1269
- this.hasAutoSelectedRef = false;
1270
- }
1271
- this.supabaseClient = supabaseClient;
1272
- this.user = user;
1273
- this.session = session;
1274
- this.appName = appName;
1275
- this.selectedOrganisation = selectedOrganisation;
1276
- this.setSelectedEventId = setSelectedEventId;
1277
- if (user?.id) {
1278
- try {
1279
- const { isRBACInitialized: isRBACInitialized2, isSuperAdmin: checkSuperAdmin, setupRBAC: setupRBAC2 } = await import('./api-7P7DI652.js');
1280
- if (!isRBACInitialized2() && this.supabaseClient) {
1281
- setupRBAC2(this.supabaseClient);
1282
- }
1283
- if (isRBACInitialized2()) {
1284
- this.isSuperAdmin = await checkSuperAdmin(user.id);
1285
- } else {
1286
- logger.warn("EventService", "RBAC not initialized in updateDependencies, keeping existing super admin status", {
1287
- userId: user.id,
1288
- existingIsSuperAdmin: this.isSuperAdmin,
1289
- note: "RBAC should be initialized by UnifiedAuthProvider. This may indicate EventService is being used outside the provider."
1290
- });
1291
- }
1292
- } catch (error) {
1293
- logger.warn("EventService", "Failed to check super admin status in updateDependencies", {
1294
- error,
1295
- userId: user.id,
1296
- existingIsSuperAdmin: this.isSuperAdmin
1297
- });
1298
- }
1299
- } else {
1300
- this.isSuperAdmin = false;
1301
- }
1302
- if (previousOrgId !== newOrgId) {
1303
- this.resetInitialization();
1304
- this.isInitializedRef = false;
1305
- this.isFetchingRef = false;
1306
- const shouldClearEvents = !this.isSuperAdmin;
1307
- const isFirstOrgSet = (previousOrgId === null || previousOrgId === void 0) && newOrgId !== null && newOrgId !== void 0;
1308
- if (isFirstOrgSet) {
1309
- const hadAutoSelectedEvent = this.hasAutoSelectedRef && !!this.selectedEvent;
1310
- this.userClearedEventRef = false;
1311
- if (!hadAutoSelectedEvent) {
1312
- this.hasAutoSelectedRef = false;
1313
- }
1314
- logger.debug("EventService", "Organisation first set - preserving event and resetting auto-selection flags", {
1315
- organisationId: newOrgId,
1316
- hasSelectedEvent: !!this.selectedEvent,
1317
- selectedEventId: this.selectedEvent?.event_id,
1318
- hadAutoSelectedEvent,
1319
- preservingEvent: hadAutoSelectedEvent,
1320
- previousOrgId,
1321
- newOrgId
1322
- });
1323
- } else if (previousOrgId !== null && previousOrgId !== void 0 && newOrgId !== null && newOrgId !== void 0 && previousOrgId !== newOrgId) {
1324
- if (shouldClearEvents) {
1325
- this.events = [];
1326
- this.setSelectedEvent(null);
1327
- }
1328
- } else if (previousOrgId !== null && previousOrgId !== void 0 && newOrgId === null) {
1329
- if (shouldClearEvents) {
1330
- this.events = [];
1331
- this.setSelectedEvent(null);
1332
- }
1333
- }
1334
- }
1335
- this.notify();
1336
- }
1337
- // Event state getters
1338
- getEvents() {
1339
- return this.events;
1340
- }
1341
- getSelectedEvent() {
1342
- return this.selectedEvent;
1343
- }
1344
- isLoading() {
1345
- return this._isLoading;
1346
- }
1347
- getError() {
1348
- return this.error;
1349
- }
1350
- // Event methods
1351
- setSelectedEvent(event) {
1352
- if (event) {
1353
- this.selectedEvent = event;
1354
- this.setSelectedEventId?.(event.event_id);
1355
- this.persistEventSelection(event.event_id).catch((error) => {
1356
- logger.warn("EventService", "Failed to persist event selection:", error);
1357
- });
1358
- this.userClearedEventRef = false;
1359
- } else {
1360
- this.selectedEvent?.event_id;
1361
- this.selectedEvent = null;
1362
- this.setSelectedEventId?.(null);
1363
- this.clearEventSelection().catch((error) => {
1364
- logger.warn("EventService", "Failed to clear event selection:", error);
1365
- });
1366
- this.hasAutoSelectedRef = false;
1367
- this.userClearedEventRef = true;
1368
- }
1369
- this.notify();
1370
- }
1371
- async refreshEvents() {
1372
- this.isInitializedRef = false;
1373
- this.isFetchingRef = false;
1374
- await this.fetchEvents();
1375
- }
1376
- async loadPersistedEvent(events) {
1377
- try {
1378
- const userId = this.user?.id || null;
1379
- if (!userId) {
1380
- return false;
1381
- }
1382
- const storageKey = this.getStorageKey(userId);
1383
- const persistedEventId = await secureStorage.getItem(storageKey);
1384
- if (persistedEventId && events.length > 0) {
1385
- const persistedEvent = events.find((event) => event.event_id === persistedEventId);
1386
- if (persistedEvent) {
1387
- this.setSelectedEvent(persistedEvent);
1388
- return true;
1389
- } else {
1390
- await secureStorage.removeItem(storageKey);
1391
- }
1392
- }
1393
- } catch (error) {
1394
- logger.warn("EventService", "Failed to load persisted event:", error);
1395
- }
1396
- return false;
1397
- }
1398
- /**
1399
- * Restore persisted event after login screen has rendered
1400
- * This should be called explicitly from login page component
1401
- *
1402
- * @returns Promise<boolean> - true if event was successfully restored, false otherwise
1403
- */
1404
- async restorePersistedEvent() {
1405
- if (this.events.length === 0) {
1406
- return false;
1407
- }
1408
- return await this.loadPersistedEvent(this.events);
1409
- }
1410
- async persistEventSelection(eventId) {
1411
- try {
1412
- const userId = this.user?.id || null;
1413
- const storageKey = this.getStorageKey(userId);
1414
- await secureStorage.setItem(storageKey, eventId, { encrypt: true });
1415
- } catch (error) {
1416
- logger.warn("EventService", "Failed to persist event selection:", error);
1417
- }
1418
- }
1419
- async clearEventSelection() {
1420
- try {
1421
- const userId = this.user?.id || null;
1422
- const storageKey = this.getStorageKey(userId);
1423
- await secureStorage.removeItem(storageKey);
1424
- this.selectedEvent = null;
1425
- this.setSelectedEventId?.(null);
1426
- } catch (error) {
1427
- logger.warn("EventService", "Failed to clear event selection:", error);
1428
- }
1429
- }
1430
- /**
1431
- * Clear event selection for a specific user (used when user logs out or changes)
1432
- */
1433
- async clearEventSelectionForUser(userId) {
1434
- try {
1435
- if (!userId) return;
1436
- const storageKey = this.getStorageKey(userId);
1437
- await secureStorage.removeItem(storageKey);
1438
- } catch (error) {
1439
- logger.warn("EventService", "Failed to clear event selection for user:", error);
1440
- }
1441
- }
1442
- autoSelectNextEvent(events) {
1443
- const nextEvent = this.getNextEventByDate(events);
1444
- if (nextEvent) {
1445
- this.setSelectedEvent(nextEvent);
1446
- }
1447
- }
1448
- // Lifecycle methods
1449
- async initialize() {
1450
- await super.initialize();
1451
- }
1452
- cleanup() {
1453
- super.cleanup();
1454
- }
1455
- async doInitialize() {
1456
- if (this.isInitializedRef) {
1457
- return;
1458
- }
1459
- if (this.isFetchingRef) {
1460
- return;
1461
- }
1462
- try {
1463
- sessionStorage.removeItem("pace-core-selected-event");
1464
- localStorage.removeItem("pace-core-selected-event");
1465
- localStorage.removeItem("_sec_pace-core-selected-event");
1466
- } catch (error) {
1467
- logger.warn("EventService", "Failed to clean up old storage keys:", error);
1468
- }
1469
- if (!this.user) {
1470
- return;
1471
- }
1472
- await this.fetchEvents(false);
1473
- this.isInitializedRef = true;
1474
- }
1475
- doCleanup() {
1476
- }
1477
- async fetchEvents(skipLoadPersisted = false) {
1478
- if (!this.user || !this.session || !this.supabaseClient || !this.appName) {
1479
- this.notify();
1480
- return;
1481
- }
1482
- this._isLoading = true;
1483
- this.notify();
1484
- if (this.isFetchingRef) {
1485
- return;
1486
- }
1487
- this.isFetchingRef = true;
1488
- let isMounted = true;
1489
- try {
1490
- let organisationIdForRpc = null;
1491
- let userIsSuperAdmin = this.isSuperAdmin;
1492
- try {
1493
- const { isRBACInitialized: isRBACInitialized2, isSuperAdmin: checkSuperAdmin, setupRBAC: setupRBAC2 } = await import('./api-7P7DI652.js');
1494
- if (!isRBACInitialized2() && this.supabaseClient) {
1495
- setupRBAC2(this.supabaseClient);
1496
- }
1497
- if (isRBACInitialized2()) {
1498
- userIsSuperAdmin = await checkSuperAdmin(this.user.id);
1499
- this.isSuperAdmin = userIsSuperAdmin;
1500
- } else {
1501
- if (this.isSuperAdmin) {
1502
- userIsSuperAdmin = true;
1503
- logger.warn("EventService", "RBAC not initialized, using cached super admin status", {
1504
- userId: this.user.id,
1505
- cachedIsSuperAdmin: this.isSuperAdmin,
1506
- note: "RBAC should be initialized by UnifiedAuthProvider. This may indicate EventService is being used outside the provider."
1507
- });
1508
- } else {
1509
- logger.warn("EventService", "RBAC not initialized, using cached non-super-admin status", {
1510
- userId: this.user.id,
1511
- cachedIsSuperAdmin: this.isSuperAdmin,
1512
- note: "RBAC should be initialized by UnifiedAuthProvider. This may indicate EventService is being used outside the provider."
1513
- });
1514
- }
1515
- }
1516
- if (userIsSuperAdmin) {
1517
- organisationIdForRpc = null;
1518
- } else {
1519
- if (this.selectedEvent) {
1520
- organisationIdForRpc = this.selectedEvent.organisation_id;
1521
- } else if (this.selectedOrganisation) {
1522
- organisationIdForRpc = this.selectedOrganisation.id;
1523
- } else {
1524
- organisationIdForRpc = null;
1525
- }
1526
- }
1527
- } catch (superAdminCheckError) {
1528
- if (this.isSuperAdmin) {
1529
- userIsSuperAdmin = true;
1530
- organisationIdForRpc = null;
1531
- logger.warn("EventService", "Super admin check failed, using cached super admin status", {
1532
- error: superAdminCheckError,
1533
- cachedIsSuperAdmin: this.isSuperAdmin
1534
- });
1535
- } else {
1536
- logger.warn("EventService", "Failed to check super admin status, using organisation-scoped query", {
1537
- error: superAdminCheckError,
1538
- cachedIsSuperAdmin: this.isSuperAdmin
1539
- });
1540
- if (this.selectedEvent) {
1541
- organisationIdForRpc = this.selectedEvent.organisation_id;
1542
- } else if (this.selectedOrganisation) {
1543
- organisationIdForRpc = this.selectedOrganisation.id;
1544
- } else {
1545
- organisationIdForRpc = null;
1546
- }
1547
- }
1548
- }
1549
- let { data, error: rpcError } = await this.supabaseClient.rpc("data_user_events_get", {
1550
- p_user_id: this.user.id,
1551
- p_organisation_id: organisationIdForRpc,
1552
- p_app_name: this.appName
1553
- });
1554
- if (rpcError) {
1555
- logger.error("EventService", "RPC error fetching events:", rpcError);
1556
- throw new Error(rpcError.message || "Failed to fetch events");
1557
- }
1558
- if (isMounted) {
1559
- const eventsData = data || [];
1560
- const transformedEvents = eventsData.map((event) => ({
1561
- id: event.event_id,
1562
- event_id: event.event_id,
1563
- event_name: event.event_name,
1564
- event_code: event.event_code,
1565
- event_date: event.event_date,
1566
- event_venue: event.event_venue,
1567
- event_participants: event.event_participants,
1568
- event_colours: event.event_colours,
1569
- event_logo: "",
1570
- // No logo field in event table
1571
- organisation_id: assertOrganisationId(event.organisation_id),
1572
- is_visible: event.is_visible,
1573
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
1574
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
1575
- }));
1576
- const sortedEvents = [...transformedEvents].sort((a, b) => {
1577
- if (a.event_date && b.event_date) {
1578
- return new Date(b.event_date).getTime() - new Date(a.event_date).getTime();
1579
- }
1580
- if (a.event_date && !b.event_date) return -1;
1581
- if (!a.event_date && b.event_date) return 1;
1582
- return 0;
1583
- });
1584
- this.events = sortedEvents;
1585
- this.error = null;
1586
- if (this.selectedEvent) {
1587
- const selectedEventId = this.selectedEvent.event_id;
1588
- const eventStillExists = transformedEvents.some(
1589
- (e) => e.event_id === selectedEventId
1590
- );
1591
- if (!eventStillExists) {
1592
- const previousUserClearedRef = this.userClearedEventRef;
1593
- this.selectedEvent = null;
1594
- this.setSelectedEventId?.(null);
1595
- this.userClearedEventRef = previousUserClearedRef;
1596
- }
1597
- }
1598
- this.hasAutoSelectedRef = false;
1599
- if (!skipLoadPersisted) {
1600
- const persistedEventLoaded = await this.loadPersistedEvent(transformedEvents);
1601
- if (!persistedEventLoaded && !this.userClearedEventRef) {
1602
- const nextEvent = this.getNextEventByDate(transformedEvents);
1603
- if (nextEvent) {
1604
- this.hasAutoSelectedRef = true;
1605
- this.setSelectedEvent(nextEvent);
1606
- }
1607
- } else if (persistedEventLoaded) {
1608
- } else if (this.userClearedEventRef) {
1609
- }
1610
- } else {
1611
- if (!this.userClearedEventRef) {
1612
- const nextEvent = this.getNextEventByDate(transformedEvents);
1613
- if (nextEvent) {
1614
- this.hasAutoSelectedRef = true;
1615
- this.setSelectedEvent(nextEvent);
1616
- }
1617
- } else {
1618
- }
1619
- }
1620
- }
1621
- } catch (err) {
1622
- logger.error("EventService", "Error fetching events:", err);
1623
- const _error = err instanceof Error ? err : new Error("Unknown error occurred");
1624
- {
1625
- this.error = _error;
1626
- this.events = [];
1627
- }
1628
- } finally {
1629
- {
1630
- this._isLoading = false;
1631
- }
1632
- this.isFetchingRef = false;
1633
- this.notify();
1634
- }
1635
- }
1636
- getNextEventByDate(events) {
1637
- const eventsToUse = events || this.events;
1638
- if (!eventsToUse || eventsToUse.length === 0) {
1639
- return null;
1640
- }
1641
- const now = /* @__PURE__ */ new Date();
1642
- const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
1643
- const futureEvents = eventsToUse.filter((event) => {
1644
- if (!event.event_date) return false;
1645
- const eventDate = new Date(event.event_date);
1646
- const startOfEventDate = new Date(eventDate.getFullYear(), eventDate.getMonth(), eventDate.getDate()).getTime();
1647
- return startOfEventDate >= startOfToday;
1648
- });
1649
- if (futureEvents.length > 0) {
1650
- const sortedFutureEvents = futureEvents.sort((a, b) => {
1651
- const dateA = new Date(a.event_date);
1652
- const dateB = new Date(b.event_date);
1653
- return dateA.getTime() - dateB.getTime();
1654
- });
1655
- return sortedFutureEvents[0];
1656
- }
1657
- const pastEvents = eventsToUse.filter((event) => {
1658
- if (!event.event_date) return false;
1659
- const eventDate = new Date(event.event_date);
1660
- const startOfEventDate = new Date(eventDate.getFullYear(), eventDate.getMonth(), eventDate.getDate()).getTime();
1661
- return startOfEventDate < startOfToday;
1662
- });
1663
- if (pastEvents.length > 0) {
1664
- const sortedPastEvents = pastEvents.sort((a, b) => {
1665
- const dateA = new Date(a.event_date);
1666
- const dateB = new Date(b.event_date);
1667
- return dateB.getTime() - dateA.getTime();
1668
- });
1669
- return sortedPastEvents[0];
1670
- }
1671
- return null;
1672
- }
1673
- };
1674
- _EventService.instanceCount = 0;
1675
- var EventService = _EventService;
1676
- var EventServiceContext = createContext(null);
1677
- function EventServiceProvider({
1678
- children,
1679
- supabaseClient,
1680
- user,
1681
- session,
1682
- appName,
1683
- selectedOrganisation,
1684
- setSelectedEventId
1685
- }) {
1686
- const eventServiceRef = useRef(null);
1687
- const initializingRef = useRef(false);
1688
- if (!eventServiceRef.current) {
1689
- eventServiceRef.current = new EventService(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);
1690
- }
1691
- const eventService = eventServiceRef.current;
1692
- useEffect(() => {
1693
- let isMounted = true;
1694
- if (initializingRef.current) {
1695
- return;
1696
- }
1697
- const updateAndInitialize = async () => {
1698
- initializingRef.current = true;
1699
- try {
1700
- await eventService.updateDependencies(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);
1701
- if (!isMounted) return;
1702
- if (user && session && supabaseClient && appName) {
1703
- await eventService.initialize().catch((error) => {
1704
- if (isMounted) {
1705
- logger.error("EventServiceProvider", "Failed to initialize event service:", error);
1706
- }
1707
- });
1708
- } else {
1709
- }
1710
- } finally {
1711
- initializingRef.current = false;
1712
- }
1713
- };
1714
- updateAndInitialize();
1715
- return () => {
1716
- isMounted = false;
1717
- initializingRef.current = false;
1718
- };
1719
- }, [supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId]);
1720
- useEffect(() => {
1721
- return () => {
1722
- eventService.cleanup();
1723
- };
1724
- }, [eventService]);
1725
- const contextValue = useMemo(() => ({
1726
- eventService
1727
- }), [eventService]);
1728
- return /* @__PURE__ */ jsx(EventServiceContext.Provider, { value: contextValue, children });
1729
- }
1730
-
1731
- // src/services/InactivityService.ts
1732
- var InactivityService = class extends BaseService {
1733
- constructor(supabaseClient, user, session, idleTimeoutMs = 30 * 60 * 1e3, warnBeforeMs = 60 * 1e3, onIdleLogout) {
1734
- super();
1735
- this._showInactivityWarning = false;
1736
- this._inactivityTimeRemaining = 0;
1737
- this._isIdle = false;
1738
- this._timeRemaining = 0;
1739
- this._showWarning = false;
1740
- this._isTracking = false;
1741
- // Dependencies
1742
- this.supabaseClient = null;
1743
- this.user = null;
1744
- this.session = null;
1745
- this.idleTimeoutMs = 30 * 60 * 1e3;
1746
- // 30 minutes
1747
- this.warnBeforeMs = 60 * 1e3;
1748
- // 60 seconds
1749
- this.onIdleLogout = null;
1750
- // Internal state management
1751
- this.inactivityTracker = null;
1752
- this.isInactivityEnabled = true;
1753
- this.cleanupHandlers = null;
1754
- this.supabaseClient = supabaseClient;
1755
- this.user = user;
1756
- this.session = session;
1757
- this.idleTimeoutMs = idleTimeoutMs;
1758
- this.warnBeforeMs = warnBeforeMs;
1759
- this.onIdleLogout = onIdleLogout;
1760
- this._timeRemaining = idleTimeoutMs;
1761
- }
1762
- // Interface implementation
1763
- isIdle() {
1764
- return this._isIdle;
1765
- }
1766
- getTimeRemaining() {
1767
- return this._timeRemaining;
1768
- }
1769
- isWarningShown() {
1770
- return this._showWarning;
1771
- }
1772
- isTracking() {
1773
- return this._isTracking;
1774
- }
1775
- getShowInactivityWarning() {
1776
- return this._showInactivityWarning;
1777
- }
1778
- getInactivityTimeRemaining() {
1779
- return this._inactivityTimeRemaining;
1780
- }
1781
- // Additional getter methods that tests expect
1782
- getIsIdle() {
1783
- return this._isIdle;
1784
- }
1785
- getIsTracking() {
1786
- return this._isTracking;
1787
- }
1788
- getShowWarning() {
1789
- return this._showWarning;
1790
- }
1791
- // Additional methods for testing
1792
- setShowInactivityWarning(value) {
1793
- this._showInactivityWarning = value;
1794
- this.notify();
1795
- }
1796
- setInactivityTimeRemaining(value) {
1797
- this._inactivityTimeRemaining = value;
1798
- this.notify();
1799
- }
1800
- setIsIdle(value) {
1801
- this._isIdle = value;
1802
- this.notify();
1803
- }
1804
- setTimeRemaining(value) {
1805
- this._timeRemaining = value;
1806
- this.notify();
1807
- }
1808
- setShowWarning(value) {
1809
- this._showWarning = value;
1810
- this.notify();
1811
- }
1812
- setIsTracking(value) {
1813
- this._isTracking = value;
1814
- this.notify();
1815
- }
1816
- triggerWarning(timeRemaining) {
1817
- this._showInactivityWarning = true;
1818
- this._inactivityTimeRemaining = Math.ceil(timeRemaining / 1e3);
1819
- this._showWarning = true;
1820
- this.notify();
1821
- }
1822
- triggerIdle() {
1823
- this._isIdle = true;
1824
- this.handleIdleLogout();
1825
- this.notify();
1826
- }
1827
- // Update dependencies
1828
- updateDependencies(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout) {
1829
- this.supabaseClient = supabaseClient;
1830
- this.user = user;
1831
- this.session = session;
1832
- if (idleTimeoutMs !== void 0) this.idleTimeoutMs = idleTimeoutMs;
1833
- if (warnBeforeMs !== void 0) this.warnBeforeMs = warnBeforeMs;
1834
- if (onIdleLogout !== void 0) this.onIdleLogout = onIdleLogout;
1835
- this.notify();
1836
- }
1837
- // Inactivity methods
1838
- resetActivity() {
1839
- if (this.inactivityTracker) {
1840
- this.inactivityTracker.resetActivity();
1841
- }
1842
- const prevIsIdle = this._isIdle;
1843
- const prevShowWarning = this._showWarning;
1844
- const prevShowInactivityWarning = this._showInactivityWarning;
1845
- const prevInactivityTimeRemaining = this._inactivityTimeRemaining;
1846
- const prevTimeRemaining = this._timeRemaining;
1847
- this._isIdle = false;
1848
- this._showWarning = false;
1849
- this._showInactivityWarning = false;
1850
- this._inactivityTimeRemaining = 0;
1851
- this._timeRemaining = this.idleTimeoutMs;
1852
- if (prevIsIdle !== this._isIdle || prevShowWarning !== this._showWarning || prevShowInactivityWarning !== this._showInactivityWarning || prevInactivityTimeRemaining !== this._inactivityTimeRemaining || prevTimeRemaining !== this._timeRemaining) {
1853
- this.notify();
1854
- }
1855
- }
1856
- startTracking() {
1857
- if (this.inactivityTracker) {
1858
- this.inactivityTracker.startTracking();
1859
- }
1860
- this._isTracking = true;
1861
- this.notify();
1862
- }
1863
- stopTracking() {
1864
- if (this.inactivityTracker) {
1865
- this.inactivityTracker.stopTracking();
1866
- }
1867
- this._isTracking = false;
1868
- this.notify();
1869
- }
1870
- async handleIdleLogout() {
1871
- this._showInactivityWarning = false;
1872
- this._inactivityTimeRemaining = 0;
1873
- this.stopTracking();
1874
- try {
1875
- if (this.supabaseClient) {
1876
- await this.supabaseClient.auth.signOut();
1877
- }
1878
- } catch (error) {
1879
- logger.error("InactivityService", "Error during idle logout:", error);
1880
- }
1881
- try {
1882
- sessionStorage.clear();
1883
- } catch (storageError) {
1884
- logger.warn("InactivityService", "Failed to clear sessionStorage", { error: storageError });
1885
- }
1886
- this.onIdleLogout?.("inactivity");
1887
- this.notify();
1888
- }
1889
- handleStaySignedIn() {
1890
- this._showInactivityWarning = false;
1891
- this._inactivityTimeRemaining = 0;
1892
- this.resetActivity();
1893
- this.notify();
1894
- }
1895
- async handleSignOutNow() {
1896
- this._showInactivityWarning = false;
1897
- this._inactivityTimeRemaining = 0;
1898
- this.stopTracking();
1899
- try {
1900
- if (this.supabaseClient) {
1901
- await this.supabaseClient.auth.signOut();
1902
- }
1903
- } catch (error) {
1904
- logger.error("InactivityService", "Error during manual sign out:", error);
1905
- }
1906
- try {
1907
- sessionStorage.clear();
1908
- } catch (storageError) {
1909
- logger.warn("InactivityService", "Failed to clear sessionStorage", { error: storageError });
1910
- }
1911
- this.onIdleLogout?.("inactivity");
1912
- this.notify();
1913
- }
1914
- // Lifecycle methods
1915
- async initialize() {
1916
- await super.initialize();
1917
- await this.setupInactivityTracker();
1918
- }
1919
- cleanup() {
1920
- if (this.cleanupHandlers) {
1921
- this.cleanupHandlers();
1922
- this.cleanupHandlers = null;
1923
- }
1924
- if (this.inactivityTracker) {
1925
- this.inactivityTracker = null;
1926
- }
1927
- this._isTracking = false;
1928
- this._isIdle = false;
1929
- this._showWarning = false;
1930
- this._showInactivityWarning = false;
1931
- this._timeRemaining = 0;
1932
- this._inactivityTimeRemaining = 0;
1933
- super.cleanup();
1934
- }
1935
- async doInitialize() {
1936
- if (typeof window !== "undefined") {
1937
- const isProduction = import.meta.env.MODE === "production";
1938
- if (isProduction) {
1939
- logger.warn("InactivityService", "Inactivity feature enabled in production");
1940
- }
1941
- }
1942
- }
1943
- doCleanup() {
1944
- }
1945
- async setupInactivityTracker() {
1946
- if (typeof window === "undefined") return;
1947
- this.isInactivityEnabled = !!(this.user && this.session);
1948
- if (!this.isInactivityEnabled) {
1949
- return;
1950
- }
1951
- this.setupEventHandlers();
1952
- }
1953
- setupEventHandlers() {
1954
- if (typeof window === "undefined") return;
1955
- let warningTimer = null;
1956
- let logoutTimer = null;
1957
- let countdownInterval = null;
1958
- let lastActivity = Date.now();
1959
- let prevIsIdle = false;
1960
- let prevShowWarning = false;
1961
- let prevShowInactivityWarning = false;
1962
- let prevInactivityTimeRemaining = 0;
1963
- let prevTimeRemaining = this.idleTimeoutMs;
1964
- const getTimeUntilWarning = () => {
1965
- const timeSinceActivity = Date.now() - lastActivity;
1966
- return Math.max(0, this.idleTimeoutMs - this.warnBeforeMs - timeSinceActivity);
1967
- };
1968
- const getTimeUntilLogout = () => {
1969
- const timeSinceActivity = Date.now() - lastActivity;
1970
- return Math.max(0, this.idleTimeoutMs - timeSinceActivity);
1971
- };
1972
- const updateState = (forceNotify = false) => {
1973
- const now = Date.now();
1974
- const timeSinceActivity = now - lastActivity;
1975
- const timeUntilIdle = this.idleTimeoutMs - timeSinceActivity;
1976
- const newIsIdle = timeSinceActivity >= this.idleTimeoutMs;
1977
- const newShowWarning = timeSinceActivity >= this.idleTimeoutMs - this.warnBeforeMs && !newIsIdle;
1978
- const newShowInactivityWarning = newShowWarning;
1979
- const newInactivityTimeRemaining = newShowWarning ? Math.ceil(timeUntilIdle / 1e3) : 0;
1980
- const newTimeRemaining = Math.max(0, timeUntilIdle);
1981
- const stateChanged = prevIsIdle !== newIsIdle || prevShowWarning !== newShowWarning || prevShowInactivityWarning !== newShowInactivityWarning || newShowWarning && prevInactivityTimeRemaining !== newInactivityTimeRemaining || prevTimeRemaining !== newTimeRemaining;
1982
- if (stateChanged || forceNotify) {
1983
- this._isIdle = newIsIdle;
1984
- this._showWarning = newShowWarning;
1985
- this._showInactivityWarning = newShowInactivityWarning;
1986
- this._inactivityTimeRemaining = newInactivityTimeRemaining;
1987
- this._timeRemaining = newTimeRemaining;
1988
- prevIsIdle = newIsIdle;
1989
- prevShowWarning = newShowWarning;
1990
- prevShowInactivityWarning = newShowInactivityWarning;
1991
- prevInactivityTimeRemaining = newInactivityTimeRemaining;
1992
- prevTimeRemaining = newTimeRemaining;
1993
- if (stateChanged) {
1994
- this.notify();
1995
- }
1996
- if (newIsIdle) {
1997
- this.handleIdleLogout();
1998
- }
1999
- }
2000
- };
2001
- const scheduleNextCheck = () => {
2002
- if (warningTimer) {
2003
- clearTimeout(warningTimer);
2004
- warningTimer = null;
2005
- }
2006
- if (logoutTimer) {
2007
- clearTimeout(logoutTimer);
2008
- logoutTimer = null;
2009
- }
2010
- if (countdownInterval) {
2011
- clearInterval(countdownInterval);
2012
- countdownInterval = null;
2013
- }
2014
- const timeUntilWarning = getTimeUntilWarning();
2015
- const timeUntilLogout = getTimeUntilLogout();
2016
- const timeSinceActivity = Date.now() - lastActivity;
2017
- if (timeSinceActivity >= this.idleTimeoutMs) {
2018
- return;
2019
- }
2020
- if (timeSinceActivity >= this.idleTimeoutMs - this.warnBeforeMs) {
2021
- updateState();
2022
- countdownInterval = setInterval(() => {
2023
- updateState();
2024
- if (Date.now() - lastActivity >= this.idleTimeoutMs) {
2025
- if (countdownInterval) {
2026
- clearInterval(countdownInterval);
2027
- countdownInterval = null;
2028
- }
2029
- this.handleIdleLogout();
2030
- }
2031
- }, 1e3);
2032
- logoutTimer = setTimeout(() => {
2033
- if (countdownInterval) {
2034
- clearInterval(countdownInterval);
2035
- countdownInterval = null;
2036
- }
2037
- this.handleIdleLogout();
2038
- }, timeUntilLogout);
2039
- } else {
2040
- const timeUntilWarningMs = timeUntilWarning;
2041
- const adaptiveInterval = timeUntilWarningMs > 5 * 60 * 1e3 ? 60 * 1e3 : timeUntilWarningMs > 60 * 1e3 ? 10 * 1e3 : 1e3;
2042
- warningTimer = setTimeout(() => {
2043
- updateState();
2044
- scheduleNextCheck();
2045
- }, Math.min(adaptiveInterval, timeUntilWarningMs));
2046
- }
2047
- };
2048
- const resetTimers = () => {
2049
- lastActivity = Date.now();
2050
- if (warningTimer) {
2051
- clearTimeout(warningTimer);
2052
- warningTimer = null;
2053
- }
2054
- if (logoutTimer) {
2055
- clearTimeout(logoutTimer);
2056
- logoutTimer = null;
2057
- }
2058
- if (countdownInterval) {
2059
- clearInterval(countdownInterval);
2060
- countdownInterval = null;
2061
- }
2062
- const hadWarning = this._showWarning || this._showInactivityWarning;
2063
- this._showInactivityWarning = false;
2064
- this._inactivityTimeRemaining = 0;
2065
- this._isIdle = false;
2066
- this._showWarning = false;
2067
- this._timeRemaining = this.idleTimeoutMs;
2068
- prevIsIdle = false;
2069
- prevShowWarning = false;
2070
- prevShowInactivityWarning = false;
2071
- prevInactivityTimeRemaining = 0;
2072
- prevTimeRemaining = this.idleTimeoutMs;
2073
- if (hadWarning) {
2074
- this.notify();
2075
- }
2076
- scheduleNextCheck();
2077
- };
2078
- const activityEvents = ["mousedown", "mousemove", "keypress", "scroll", "touchstart", "click"];
2079
- let activityThrottleTimer = null;
2080
- const handleActivity = () => {
2081
- if (activityThrottleTimer) {
2082
- return;
2083
- }
2084
- activityThrottleTimer = setTimeout(() => {
2085
- activityThrottleTimer = null;
2086
- resetTimers();
2087
- }, 1e3);
2088
- };
2089
- activityEvents.forEach((event) => {
2090
- document.addEventListener(event, handleActivity, true);
2091
- });
2092
- updateState(true);
2093
- scheduleNextCheck();
2094
- this.cleanupHandlers = () => {
2095
- if (warningTimer) {
2096
- clearTimeout(warningTimer);
2097
- warningTimer = null;
2098
- }
2099
- if (logoutTimer) {
2100
- clearTimeout(logoutTimer);
2101
- logoutTimer = null;
2102
- }
2103
- if (countdownInterval) {
2104
- clearInterval(countdownInterval);
2105
- countdownInterval = null;
2106
- }
2107
- if (activityThrottleTimer) {
2108
- clearTimeout(activityThrottleTimer);
2109
- activityThrottleTimer = null;
2110
- }
2111
- activityEvents.forEach((event) => {
2112
- document.removeEventListener(event, handleActivity, true);
2113
- });
2114
- this._isTracking = false;
2115
- this._isIdle = false;
2116
- this._showWarning = false;
2117
- this._timeRemaining = 0;
2118
- this._showInactivityWarning = false;
2119
- this._inactivityTimeRemaining = 0;
2120
- };
2121
- this._isTracking = true;
2122
- }
2123
- };
2124
- var InactivityServiceContext = createContext(null);
2125
- function InactivityServiceProvider({
2126
- children,
2127
- supabaseClient,
2128
- user,
2129
- session,
2130
- idleTimeoutMs,
2131
- // REQUIRED: No default - must be explicitly provided
2132
- warnBeforeMs,
2133
- // REQUIRED: No default - must be explicitly provided
2134
- onIdleLogout
2135
- }) {
2136
- const inactivityServiceRef = useRef(null);
2137
- if (!inactivityServiceRef.current) {
2138
- inactivityServiceRef.current = new InactivityService(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout);
2139
- }
2140
- const inactivityService = inactivityServiceRef.current;
2141
- useEffect(() => {
2142
- inactivityService.updateDependencies(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout);
2143
- let isMounted = true;
2144
- inactivityService.initialize().catch((error) => {
2145
- if (isMounted) {
2146
- logger.error("InactivityServiceProvider", "Failed to initialize inactivity service:", error);
2147
- }
2148
- });
2149
- return () => {
2150
- isMounted = false;
2151
- };
2152
- }, [inactivityService, supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout]);
2153
- useEffect(() => {
2154
- return () => {
2155
- inactivityService.cleanup();
2156
- };
2157
- }, [inactivityService]);
2158
- const contextValue = useMemo(() => ({
2159
- inactivityService
2160
- }), [inactivityService]);
2161
- return /* @__PURE__ */ jsx(InactivityServiceContext.Provider, { value: contextValue, children });
2162
- }
2163
- function useAuthService() {
2164
- const context = useContext(AuthServiceContext);
2165
- if (!context) {
2166
- throw new Error("useAuthService must be used within AuthServiceProvider");
2167
- }
2168
- const [, forceUpdate] = useReducer((x) => x + 1, 0);
2169
- const timeoutRef = useRef(null);
2170
- useEffect(() => {
2171
- const debouncedUpdate = () => {
2172
- if (timeoutRef.current) {
2173
- clearTimeout(timeoutRef.current);
2174
- }
2175
- timeoutRef.current = setTimeout(() => {
2176
- forceUpdate();
2177
- timeoutRef.current = null;
2178
- }, 50);
2179
- };
2180
- const unsubscribe = context.authService.subscribe(debouncedUpdate);
2181
- return () => {
2182
- unsubscribe();
2183
- if (timeoutRef.current) {
2184
- clearTimeout(timeoutRef.current);
2185
- }
2186
- };
2187
- }, [context.authService]);
2188
- return context.authService;
2189
- }
2190
- function useOrganisationService() {
2191
- const context = useContext(OrganisationServiceContext);
2192
- if (!context) {
2193
- throw new Error("useOrganisationService must be used within OrganisationServiceProvider");
2194
- }
2195
- const [, forceUpdate] = useReducer((x) => x + 1, 0);
2196
- const timeoutRef = useRef(null);
2197
- useEffect(() => {
2198
- const debouncedUpdate = () => {
2199
- if (timeoutRef.current) {
2200
- clearTimeout(timeoutRef.current);
2201
- }
2202
- timeoutRef.current = setTimeout(() => {
2203
- forceUpdate();
2204
- timeoutRef.current = null;
2205
- }, 50);
2206
- };
2207
- const unsubscribe = context.organisationService.subscribe(debouncedUpdate);
2208
- return () => {
2209
- unsubscribe();
2210
- if (timeoutRef.current) {
2211
- clearTimeout(timeoutRef.current);
2212
- }
2213
- };
2214
- }, [context.organisationService]);
2215
- return context.organisationService;
2216
- }
2217
-
2218
- // src/hooks/useOrganisations.ts
2219
- function useOrganisations() {
2220
- const organisationService = useOrganisationService();
2221
- const selectedOrg = organisationService.getSelectedOrganisation();
2222
- return {
2223
- selectedOrganisation: selectedOrg,
2224
- organisations: organisationService.getOrganisations(),
2225
- userMemberships: organisationService.getUserMemberships(),
2226
- isLoading: organisationService.isLoading(),
2227
- error: organisationService.getError(),
2228
- hasValidOrganisationContext: organisationService.hasValidOrganisationContext(),
2229
- isContextReady: organisationService.isContextReady(),
2230
- setSelectedOrganisation: (org) => organisationService.setSelectedOrganisation(org),
2231
- switchOrganisation: (orgId) => organisationService.switchOrganisation(orgId),
2232
- getUserRole: (orgId) => organisationService.getUserRole(orgId),
2233
- validateOrganisationAccess: (orgId) => organisationService.validateOrganisationAccess(orgId),
2234
- refreshOrganisations: () => organisationService.refreshOrganisations(),
2235
- ensureOrganisationContext: () => organisationService.ensureOrganisationContext(),
2236
- isOrganisationSecure: () => organisationService.isOrganisationSecure(),
2237
- getPrimaryOrganisation: () => organisationService.getPrimaryOrganisation()
2238
- };
2239
- }
2240
- function useEventService() {
2241
- const context = useContext(EventServiceContext);
2242
- if (!context) {
2243
- throw new Error("useEventService must be used within EventServiceProvider");
2244
- }
2245
- const [, forceUpdate] = useReducer((x) => x + 1, 0);
2246
- const timeoutRef = useRef(null);
2247
- useEffect(() => {
2248
- const debouncedUpdate = () => {
2249
- if (timeoutRef.current) {
2250
- clearTimeout(timeoutRef.current);
2251
- }
2252
- timeoutRef.current = setTimeout(() => {
2253
- forceUpdate();
2254
- timeoutRef.current = null;
2255
- }, 50);
2256
- };
2257
- const unsubscribe = context.eventService.subscribe(debouncedUpdate);
2258
- return () => {
2259
- unsubscribe();
2260
- if (timeoutRef.current) {
2261
- clearTimeout(timeoutRef.current);
2262
- }
2263
- };
2264
- }, [context.eventService]);
2265
- return context.eventService;
2266
- }
2267
- function useInactivityService() {
2268
- const context = useContext(InactivityServiceContext);
2269
- if (!context) {
2270
- throw new Error("useInactivityService must be used within InactivityServiceProvider");
2271
- }
2272
- const [, forceUpdate] = useReducer((x) => x + 1, 0);
2273
- const timeoutRef = useRef(null);
2274
- useEffect(() => {
2275
- const debouncedUpdate = () => {
2276
- if (timeoutRef.current) {
2277
- clearTimeout(timeoutRef.current);
2278
- }
2279
- timeoutRef.current = setTimeout(() => {
2280
- forceUpdate();
2281
- timeoutRef.current = null;
2282
- }, 50);
2283
- };
2284
- const unsubscribe = context.inactivityService.subscribe(debouncedUpdate);
2285
- return () => {
2286
- unsubscribe();
2287
- if (timeoutRef.current) {
2288
- clearTimeout(timeoutRef.current);
2289
- }
2290
- };
2291
- }, [context.inactivityService]);
2292
- return context.inactivityService;
2293
- }
2294
- var log = createLogger("useSessionRestoration");
2295
- var SESSION_RESTORATION_TIMEOUT_MS = 1e4;
2296
- function useSessionRestoration() {
2297
- const context = useContext(AuthServiceContext);
2298
- if (!context) {
2299
- throw new Error("useSessionRestoration must be used within AuthServiceProvider");
2300
- }
2301
- const { sessionRestoration } = context;
2302
- const [hasTimedOut, setHasTimedOut] = useState(false);
2303
- useEffect(() => {
2304
- let timeoutHandle = null;
2305
- if (sessionRestoration.isRestoring && !sessionRestoration.restorationComplete && !sessionRestoration.restorationError) {
2306
- setHasTimedOut(false);
2307
- timeoutHandle = setTimeout(() => {
2308
- log.warn("Session restoration timed out");
2309
- setHasTimedOut(true);
2310
- }, SESSION_RESTORATION_TIMEOUT_MS);
2311
- } else {
2312
- setHasTimedOut(false);
2313
- }
2314
- return () => {
2315
- if (timeoutHandle) {
2316
- clearTimeout(timeoutHandle);
2317
- }
2318
- };
2319
- }, [
2320
- sessionRestoration.isRestoring,
2321
- sessionRestoration.restorationComplete,
2322
- sessionRestoration.restorationError
2323
- ]);
2324
- return useMemo(() => ({
2325
- ...sessionRestoration,
2326
- hasTimedOut,
2327
- timeoutMs: SESSION_RESTORATION_TIMEOUT_MS
2328
- }), [sessionRestoration, hasTimedOut]);
2329
- }
2330
- var UnifiedAuthContext = createContext(void 0);
2331
- var useUnifiedAuth = () => {
2332
- const context = useContext(UnifiedAuthContext);
2333
- if (!context) {
2334
- logger.error("useUnifiedAuth", "useUnifiedAuth must be used within a UnifiedAuthProvider");
2335
- throw new Error("useUnifiedAuth must be used within a UnifiedAuthProvider");
2336
- }
2337
- return context;
2338
- };
2339
- function UnifiedAuthContextProvider({
2340
- children,
2341
- appName,
2342
- supabaseClient: supabaseClientProp,
2343
- ...props
2344
- }) {
2345
- const authService = useAuthService();
2346
- const organisationService = useOrganisationService();
2347
- const inactivityService = useInactivityService();
2348
- const sessionRestorationState = useSessionRestoration();
2349
- const {
2350
- hasTimedOut: sessionRestorationTimedOut,
2351
- timeoutMs: sessionRestorationTimeoutMs,
2352
- isRestoring,
2353
- restorationComplete,
2354
- restorationError
2355
- } = sessionRestorationState;
2356
- const sessionRestoration = useMemo(() => ({
2357
- isRestoring,
2358
- restorationComplete,
2359
- restorationError
2360
- }), [isRestoring, restorationComplete, restorationError]);
2361
- const eventService = useEventService();
2362
- const currentUser = authService.getUser();
2363
- const currentSession = authService.getSession();
2364
- const isAuth = !!(currentUser && currentSession);
2365
- const supabase = useMemo(() => supabaseClientProp, [supabaseClientProp]);
2366
- const [appId, setAppId] = useState(void 0);
2367
- const isResolvingAppIdRef = useRef(false);
2368
- const resolvedAppIdRef = useRef(void 0);
2369
- const resolvedUserIdRef = useRef(void 0);
2370
- useEffect(() => {
2371
- if (!isAuth) {
2372
- resolvedAppIdRef.current = void 0;
2373
- resolvedUserIdRef.current = void 0;
2374
- setAppId(void 0);
2375
- return;
2376
- }
2377
- if (currentUser?.id && resolvedUserIdRef.current && resolvedUserIdRef.current !== currentUser.id) {
2378
- resolvedAppIdRef.current = void 0;
2379
- resolvedUserIdRef.current = void 0;
2380
- setAppId(void 0);
2381
- }
2382
- const currentUserId = currentUser?.id;
2383
- if (isAuth && currentUserId && supabase && appName && resolvedUserIdRef.current !== currentUserId && // Haven't resolved for this user yet
2384
- !isResolvingAppIdRef.current) {
2385
- isResolvingAppIdRef.current = true;
2386
- resolvedUserIdRef.current = currentUserId;
2387
- const userId = currentUserId;
2388
- const appNameValue = appName;
2389
- import('./api-7P7DI652.js').then(async ({ resolveAppContext, setupRBAC: setupRBAC2 }) => {
2390
- try {
2391
- setupRBAC2(supabase);
2392
- const result = await resolveAppContext({
2393
- userId,
2394
- appName: appNameValue
2395
- });
2396
- if (result?.appId) {
2397
- resolvedAppIdRef.current = result.appId;
2398
- setAppId(result.appId);
2399
- } else {
2400
- resolvedUserIdRef.current = void 0;
2401
- }
2402
- } catch (error) {
2403
- logger.error("UnifiedAuthProvider", "Failed to resolve appId on login", {
2404
- error: error instanceof Error ? error.message : String(error),
2405
- appName: appNameValue,
2406
- userId
2407
- });
2408
- resolvedUserIdRef.current = void 0;
2409
- } finally {
2410
- isResolvingAppIdRef.current = false;
2411
- }
2412
- }).catch((importError) => {
2413
- logger.error("UnifiedAuthProvider", "Failed to import RBAC API", importError);
2414
- isResolvingAppIdRef.current = false;
2415
- resolvedUserIdRef.current = void 0;
2416
- });
2417
- }
2418
- }, [isAuth, currentUser?.id, supabase, appName]);
2419
- const [, forceUpdate] = useReducer((x) => x + 1, 0);
2420
- const forceUpdateTimeoutRef = useRef(null);
2421
- const debouncedForceUpdate = useCallback(() => {
2422
- if (forceUpdateTimeoutRef.current) {
2423
- clearTimeout(forceUpdateTimeoutRef.current);
2424
- }
2425
- forceUpdateTimeoutRef.current = setTimeout(() => {
2426
- forceUpdate();
2427
- forceUpdateTimeoutRef.current = null;
2428
- }, 100);
2429
- }, [forceUpdate]);
2430
- const authServiceRef = useRef(authService);
2431
- const organisationServiceRef = useRef(organisationService);
2432
- const eventServiceRef = useRef(eventService);
2433
- const inactivityServiceRef = useRef(inactivityService);
2434
- useEffect(() => {
2435
- authServiceRef.current = authService;
2436
- organisationServiceRef.current = organisationService;
2437
- eventServiceRef.current = eventService;
2438
- inactivityServiceRef.current = inactivityService;
2439
- }, [authService, organisationService, eventService, inactivityService]);
2440
- useEffect(() => {
2441
- const unsubscribeAuth = authServiceRef.current.subscribe(debouncedForceUpdate);
2442
- const unsubscribeOrg = organisationServiceRef.current.subscribe(debouncedForceUpdate);
2443
- const unsubscribeEvent = eventServiceRef.current.subscribe(debouncedForceUpdate);
2444
- const unsubscribeInactivity = inactivityServiceRef.current.subscribe(debouncedForceUpdate);
2445
- return () => {
2446
- unsubscribeAuth();
2447
- unsubscribeOrg();
2448
- unsubscribeEvent();
2449
- unsubscribeInactivity();
2450
- if (forceUpdateTimeoutRef.current) {
2451
- clearTimeout(forceUpdateTimeoutRef.current);
2452
- }
2453
- };
2454
- }, [debouncedForceUpdate]);
2455
- const authLoading = authService.isLoading();
2456
- const orgLoading = organisationService.isLoading();
2457
- const eventLoading = eventService.isLoading();
2458
- const restorationLoading = sessionRestoration.isRestoring && !sessionRestorationTimedOut && !sessionRestoration.restorationError;
2459
- const shouldIncludeOrgLoading = appName !== "ADMIN" && appName !== "PORTAL";
2460
- const totalLoading = restorationLoading || authLoading || (shouldIncludeOrgLoading ? orgLoading : false) || eventLoading;
2461
- const authError = authService.getError();
2462
- const rawSelectedOrganisation = organisationService.getSelectedOrganisation();
2463
- const organisationError = organisationService.getError();
2464
- const selectedOrganisation = rawSelectedOrganisation;
2465
- const hasValidOrganisationContext = organisationService.hasValidOrganisationContext();
2466
- const isContextReady = organisationService.isContextReady();
2467
- const rawEvents = eventService.getEvents();
2468
- const rawOrganisations = organisationService.getOrganisations();
2469
- const rawUserMemberships = organisationService.getUserMemberships();
2470
- const events = useMemo(() => {
2471
- return rawEvents;
2472
- }, [
2473
- // Create dependency string from event IDs - only changes when events actually change
2474
- rawEvents.map((e) => e.event_id || e.id).join(",")
2475
- ]);
2476
- const organisations = useMemo(() => {
2477
- return rawOrganisations;
2478
- }, [
2479
- // Create dependency string from organisation IDs - only changes when orgs actually change
2480
- rawOrganisations.map((o) => o.id).join(",")
2481
- ]);
2482
- const userMemberships = useMemo(() => {
2483
- return rawUserMemberships;
2484
- }, [
2485
- // Create dependency string from membership IDs - only changes when memberships actually change
2486
- rawUserMemberships.map((m) => `${m.organisation_id}-${m.user_id}`).join(",")
2487
- ]);
2488
- const selectedEvent = eventService.getSelectedEvent();
2489
- const eventError = eventService.getError();
2490
- const showInactivityWarning = inactivityService.getShowInactivityWarning();
2491
- const inactivityTimeRemaining = inactivityService.getInactivityTimeRemaining();
2492
- const isIdle = inactivityService.isIdle();
2493
- const timeRemaining = inactivityService.getTimeRemaining();
2494
- const showWarning = inactivityService.isWarningShown();
2495
- const isTracking = inactivityService.isTracking();
2496
- const inactivityState = useMemo(() => ({
2497
- showInactivityWarning,
2498
- inactivityTimeRemaining,
2499
- isIdle,
2500
- timeRemaining,
2501
- showWarning,
2502
- isTracking
2503
- }), [
2504
- showInactivityWarning,
2505
- inactivityTimeRemaining,
2506
- isIdle,
2507
- timeRemaining,
2508
- showWarning,
2509
- isTracking
2510
- ]);
2511
- const hasErrors = !!(authError || organisationError || eventError || sessionRestoration.restorationError);
2512
- const signIn = (email, password) => authService.signIn(email, password);
2513
- const signUp = (email, password) => authService.signUp(email, password);
2514
- const signOut = () => authService.signOut();
2515
- const resetPassword = (email) => authService.resetPassword(email);
2516
- const updatePassword = (password) => authService.updatePassword(password);
2517
- const refreshSession = () => authService.refreshSession();
2518
- const switchOrganisation = (orgId) => organisationService.switchOrganisation(orgId);
2519
- const getUserRole = (orgId) => organisationService.getUserRole(orgId);
2520
- const validateOrganisationAccess = (orgId) => organisationService.validateOrganisationAccess(orgId);
2521
- const refreshOrganisations = () => organisationService.refreshOrganisations();
2522
- const ensureOrganisationContext = () => organisationService.ensureOrganisationContext();
2523
- const isOrganisationSecure = () => organisationService.isOrganisationSecure();
2524
- const getPrimaryOrganisation = () => organisationService.getPrimaryOrganisation();
2525
- const setSelectedEvent = (event) => eventService.setSelectedEvent(event);
2526
- const refreshEvents = () => eventService.refreshEvents();
2527
- const resetActivity = () => inactivityService.resetActivity();
2528
- const startTracking = () => inactivityService.startTracking();
2529
- const stopTracking = () => inactivityService.stopTracking();
2530
- const handleIdleLogout = () => inactivityService.handleIdleLogout();
2531
- const handleStaySignedIn = () => inactivityService.handleStaySignedIn();
2532
- const handleSignOutNow = () => inactivityService.handleSignOutNow();
2533
- const prevStateRef = useRef(null);
2534
- const isDev = import.meta.env.DEV || import.meta.env.MODE === "development";
2535
- if (isDev) {
2536
- const currentState = {
2537
- isAuthenticated: isAuth,
2538
- userEmail: currentUser?.email,
2539
- totalLoading
2540
- };
2541
- const prevState = prevStateRef.current;
2542
- if (!prevState || prevState.isAuthenticated !== currentState.isAuthenticated || prevState.userEmail !== currentState.userEmail || prevState.totalLoading !== currentState.totalLoading) {
2543
- prevStateRef.current = currentState;
2544
- }
2545
- }
2546
- const contextValue = useMemo(() => {
2547
- return {
2548
- // Auth state
2549
- user: currentUser,
2550
- session: currentSession,
2551
- isAuthenticated: isAuth,
2552
- authLoading,
2553
- authError,
2554
- supabase,
2555
- // Auth methods
2556
- signIn,
2557
- signUp,
2558
- signOut,
2559
- resetPassword,
2560
- updatePassword,
2561
- refreshSession,
2562
- // Organisation state
2563
- selectedOrganisation,
2564
- selectedOrganisationId: selectedOrganisation?.id || null,
2565
- organisations,
2566
- userMemberships,
2567
- organisationLoading: orgLoading,
2568
- organisationError,
2569
- hasValidOrganisationContext,
2570
- isContextReady,
2571
- // Organisation methods
2572
- switchOrganisation,
2573
- getUserRole,
2574
- validateOrganisationAccess,
2575
- refreshOrganisations,
2576
- ensureOrganisationContext,
2577
- isOrganisationSecure,
2578
- getPrimaryOrganisation,
2579
- // Event state
2580
- events,
2581
- selectedEvent,
2582
- selectedEventId: selectedEvent?.event_id || null,
2583
- eventLoading,
2584
- eventError,
2585
- // Event methods
2586
- setSelectedEvent,
2587
- refreshEvents,
2588
- // Inactivity state
2589
- showInactivityWarning: inactivityState.showInactivityWarning,
2590
- inactivityTimeRemaining: inactivityState.inactivityTimeRemaining,
2591
- isIdle: inactivityState.isIdle,
2592
- timeRemaining: inactivityState.timeRemaining,
2593
- showWarning: inactivityState.showWarning,
2594
- isTracking: inactivityState.isTracking,
2595
- // Inactivity methods
2596
- resetActivity,
2597
- startTracking,
2598
- stopTracking,
2599
- handleIdleLogout,
2600
- handleStaySignedIn,
2601
- handleSignOutNow,
2602
- // Additional unified properties
2603
- appName,
2604
- appId,
2605
- // Resolved immediately on login
2606
- isLoading: totalLoading,
2607
- hasErrors,
2608
- sessionRestoration,
2609
- sessionRestorationTimedOut,
2610
- sessionRestorationTimeoutMs
2611
- };
2612
- }, [
2613
- // All primitive values extracted from services
2614
- // Note: Arrays/objects from services are stable references (same reference unless data changes)
2615
- currentUser,
2616
- currentSession,
2617
- isAuth,
2618
- authLoading,
2619
- authError,
2620
- supabase,
2621
- selectedOrganisation,
2622
- organisations,
2623
- userMemberships,
2624
- orgLoading,
2625
- organisationError,
2626
- hasValidOrganisationContext,
2627
- isContextReady,
2628
- events,
2629
- selectedEvent,
2630
- eventLoading,
2631
- eventError,
2632
- inactivityState,
2633
- // Use memoized object instead of individual values
2634
- totalLoading,
2635
- hasErrors,
2636
- appName,
2637
- appId,
2638
- sessionRestoration,
2639
- sessionRestorationTimedOut,
2640
- sessionRestorationTimeoutMs,
2641
- // Stable function references from useCallback (services are stable, so callbacks are too)
2642
- signIn,
2643
- signUp,
2644
- signOut,
2645
- resetPassword,
2646
- updatePassword,
2647
- refreshSession,
2648
- switchOrganisation,
2649
- getUserRole,
2650
- validateOrganisationAccess,
2651
- refreshOrganisations,
2652
- ensureOrganisationContext,
2653
- isOrganisationSecure,
2654
- getPrimaryOrganisation,
2655
- setSelectedEvent,
2656
- refreshEvents,
2657
- resetActivity,
2658
- startTracking,
2659
- stopTracking,
2660
- handleIdleLogout,
2661
- handleStaySignedIn,
2662
- handleSignOutNow
2663
- ]);
2664
- return /* @__PURE__ */ jsx(UnifiedAuthContext.Provider, { value: contextValue, children });
2665
- }
2666
- function EventServiceProviderWrapper({
2667
- children,
2668
- supabaseClient,
2669
- user,
2670
- session,
2671
- appName
2672
- }) {
2673
- const { selectedOrganisation } = useOrganisations();
2674
- const setSelectedEventId = useCallback(() => {
2675
- }, []);
2676
- useEffect(() => {
2677
- }, [user?.id, session?.access_token, selectedOrganisation?.id]);
2678
- return /* @__PURE__ */ jsx(
2679
- EventServiceProvider,
2680
- {
2681
- supabaseClient,
2682
- user,
2683
- session,
2684
- appName,
2685
- selectedOrganisation,
2686
- setSelectedEventId,
2687
- children
2688
- }
2689
- );
2690
- }
2691
- function ServiceAwareProviders({
2692
- children,
2693
- supabaseClient,
2694
- appName,
2695
- persistState,
2696
- enablePersistence,
2697
- requireOrganisationContext,
2698
- idleTimeoutMs,
2699
- warnBeforeMs,
2700
- onIdleLogout,
2701
- renderInactivityWarning,
2702
- dangerouslyDisableInactivity
2703
- }) {
2704
- const authService = useAuthService();
2705
- const [userState, setUserState] = useState(() => authService.getUser());
2706
- const [sessionState, setSessionState] = useState(() => authService.getSession());
2707
- useEffect(() => {
2708
- const unsubscribe = authService.subscribe(() => {
2709
- const newUser = authService.getUser();
2710
- const newSession = authService.getSession();
2711
- setUserState(newUser);
2712
- setSessionState(newSession);
2713
- });
2714
- return unsubscribe;
2715
- }, [authService]);
2716
- const user = userState;
2717
- const session = sessionState;
2718
- return /* @__PURE__ */ jsx(
2719
- OrganisationServiceProvider,
2720
- {
2721
- supabaseClient,
2722
- user,
2723
- session,
2724
- children: /* @__PURE__ */ jsx(
2725
- EventServiceProviderWrapper,
2726
- {
2727
- supabaseClient,
2728
- user,
2729
- session,
2730
- appName,
2731
- children: /* @__PURE__ */ jsx(
2732
- InactivityServiceProvider,
2733
- {
2734
- supabaseClient,
2735
- user,
2736
- session,
2737
- idleTimeoutMs,
2738
- warnBeforeMs,
2739
- onIdleLogout,
2740
- children: /* @__PURE__ */ jsx(
2741
- UnifiedAuthContextProvider,
2742
- {
2743
- appName,
2744
- supabaseClient,
2745
- persistState,
2746
- enablePersistence,
2747
- requireOrganisationContext,
2748
- idleTimeoutMs,
2749
- warnBeforeMs,
2750
- onIdleLogout,
2751
- renderInactivityWarning,
2752
- dangerouslyDisableInactivity,
2753
- children
2754
- }
2755
- )
2756
- }
2757
- )
2758
- }
2759
- )
2760
- }
2761
- );
2762
- }
2763
- function UnifiedAuthProvider({
2764
- children,
2765
- supabaseClient,
2766
- appName,
2767
- persistState = true,
2768
- enablePersistence,
2769
- requireOrganisationContext = true,
2770
- idleTimeoutMs,
2771
- // REQUIRED: No default - must be explicitly provided
2772
- warnBeforeMs,
2773
- // REQUIRED: No default - must be explicitly provided
2774
- onIdleLogout,
2775
- // REQUIRED: No default - must be explicitly provided
2776
- renderInactivityWarning,
2777
- dangerouslyDisableInactivity = false
2778
- }) {
2779
- const clientRef = useRef(supabaseClient);
2780
- useEffect(() => {
2781
- if (clientRef.current !== supabaseClient) {
2782
- logger.warn("UnifiedAuthProvider", "Supabase client reference changed - this may indicate multiple client instances are being created", {
2783
- previousClient: clientRef.current,
2784
- newClient: supabaseClient,
2785
- note: 'Ensure you create the Supabase client once and reuse it. Creating multiple clients can cause performance issues and the "Multiple GoTrueClient instances" warning.'
2786
- });
2787
- clientRef.current = supabaseClient;
2788
- }
2789
- }, [supabaseClient]);
2790
- if (supabaseClient && !isRBACInitialized()) {
2791
- try {
2792
- setupRBAC(supabaseClient);
2793
- logger.debug("UnifiedAuthProvider", "RBAC initialized synchronously");
2794
- } catch (err) {
2795
- logger.error("UnifiedAuthProvider", "Failed to initialize RBAC", err);
2796
- }
2797
- }
2798
- return /* @__PURE__ */ jsx(AuthServiceProvider, { supabaseClient, appName, children: /* @__PURE__ */ jsx(
2799
- ServiceAwareProviders,
2800
- {
2801
- supabaseClient,
2802
- appName,
2803
- persistState,
2804
- enablePersistence,
2805
- requireOrganisationContext,
2806
- idleTimeoutMs,
2807
- warnBeforeMs,
2808
- onIdleLogout,
2809
- renderInactivityWarning,
2810
- dangerouslyDisableInactivity,
2811
- children
2812
- }
2813
- ) });
2814
- }
2815
-
2816
- export { AuthServiceContext, AuthServiceProvider, EventServiceContext, EventServiceProvider, InactivityServiceContext, InactivityServiceProvider, OrganisationServiceContext, OrganisationServiceProvider, UnifiedAuthContext, UnifiedAuthProvider, useAuthService, useEventService, useInactivityService, useOrganisationService, useOrganisations, useSessionRestoration, useUnifiedAuth };