@jmruthers/pace-core 0.5.181 → 0.5.182

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 (750) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +16 -2
  3. package/dist/{AuthService-DYuQPJj6.d.ts → AuthService-B-cd2MA4.d.ts} +9 -11
  4. package/dist/{DataTable-CWAZZcXC.d.ts → DataTable-Bz8ffqyA.d.ts} +1 -1
  5. package/dist/{DataTable-UA6CL4JI.js → DataTable-QAB34V6K.js} +14 -15
  6. package/dist/UnifiedAuthProvider-7F6T4B6K.js +13 -0
  7. package/dist/{UnifiedAuthProvider-DJxGTftH.d.ts → UnifiedAuthProvider-F86d7dSi.d.ts} +5 -6
  8. package/dist/{api-45XYYO2A.js → api-ROMBCNKU.js} +5 -5
  9. package/dist/{audit-64X3VJXB.js → audit-WRS3KJKI.js} +4 -4
  10. package/dist/auth-BZOJqrdd.d.ts +49 -0
  11. package/dist/{chunk-CX5M4ZAG.js → chunk-5DRSZLL2.js} +1 -1
  12. package/dist/chunk-5DRSZLL2.js.map +1 -0
  13. package/dist/{chunk-BESYRHQM.js → chunk-6C4YBBJM.js} +10 -7
  14. package/dist/chunk-6C4YBBJM.js.map +1 -0
  15. package/dist/{chunk-PLDDJCW6.js → chunk-7D4SUZUM.js} +2 -13
  16. package/dist/{chunk-HRO5HWN2.js → chunk-CSOFYHAG.js} +55 -162
  17. package/dist/chunk-CSOFYHAG.js.map +1 -0
  18. package/dist/{chunk-ANBQRTPX.js → chunk-E66EQZE6.js} +3 -5
  19. package/dist/{chunk-ANBQRTPX.js.map → chunk-E66EQZE6.js.map} +1 -1
  20. package/dist/{chunk-Q5QRDWKI.js → chunk-F2IMUDXZ.js} +4 -6
  21. package/dist/chunk-F2IMUDXZ.js.map +1 -0
  22. package/dist/{chunk-SBVILCCA.js → chunk-FSFQFJCU.js} +28 -6
  23. package/dist/chunk-FSFQFJCU.js.map +1 -0
  24. package/dist/chunk-FUEYYMX5.js +2296 -0
  25. package/dist/chunk-FUEYYMX5.js.map +1 -0
  26. package/dist/{chunk-FFKNH6U5.js → chunk-HKIT6O7W.js} +3 -5
  27. package/dist/{chunk-FFKNH6U5.js.map → chunk-HKIT6O7W.js.map} +1 -1
  28. package/dist/chunk-KQCRWDSA.js +1 -0
  29. package/dist/{chunk-S5OFRT4M.js → chunk-KUEN3HFB.js} +6 -6
  30. package/dist/chunk-KUEN3HFB.js.map +1 -0
  31. package/dist/chunk-LMC26NLJ.js +84 -0
  32. package/dist/chunk-LMC26NLJ.js.map +1 -0
  33. package/dist/{chunk-BVYWGZVV.js → chunk-M7W4CP3M.js} +52 -19
  34. package/dist/chunk-M7W4CP3M.js.map +1 -0
  35. package/dist/{chunk-HZLDFOE4.js → chunk-MI7HBHN3.js} +164 -243
  36. package/dist/chunk-MI7HBHN3.js.map +1 -0
  37. package/dist/{chunk-PPMP5J6T.js → chunk-PWAHJW4G.js} +180 -29
  38. package/dist/chunk-PWAHJW4G.js.map +1 -0
  39. package/dist/chunk-PWLANIRT.js +127 -0
  40. package/dist/{chunk-XDNLUEXI.js.map → chunk-PWLANIRT.js.map} +1 -1
  41. package/dist/chunk-QCDXODCA.js +75 -0
  42. package/dist/chunk-QCDXODCA.js.map +1 -0
  43. package/dist/{chunk-D7LCGMVS.js → chunk-QETLRQI6.js} +526 -887
  44. package/dist/chunk-QETLRQI6.js.map +1 -0
  45. package/dist/{chunk-5MT24GKJ.js → chunk-QUVSNGIP.js} +264 -262
  46. package/dist/chunk-QUVSNGIP.js.map +1 -0
  47. package/dist/chunk-QXHPKYJV.js +113 -0
  48. package/dist/chunk-QXHPKYJV.js.map +1 -0
  49. package/dist/{chunk-OWAG3GSU.js → chunk-R77UEZ4E.js} +11 -1
  50. package/dist/chunk-R77UEZ4E.js.map +1 -0
  51. package/dist/{chunk-ZYTYSTO5.js → chunk-RA3JUFMW.js} +314 -161
  52. package/dist/chunk-RA3JUFMW.js.map +1 -0
  53. package/dist/{chunk-ERISIBYU.js → chunk-SQGMNID3.js} +3 -8
  54. package/dist/chunk-SQGMNID3.js.map +1 -0
  55. package/dist/{chunk-XJ2HZOBU.js → chunk-UHNYIBXL.js} +1 -1
  56. package/dist/chunk-UHNYIBXL.js.map +1 -0
  57. package/{src/utils/secureStorage.ts → dist/chunk-VBXEHIUJ.js} +113 -88
  58. package/dist/{chunk-7QCC6MCP.js.map → chunk-VBXEHIUJ.js.map} +1 -1
  59. package/dist/{chunk-VZ4VDGTB.js → chunk-W22JP75J.js} +5 -13
  60. package/dist/{chunk-VZ4VDGTB.js.map → chunk-W22JP75J.js.map} +1 -1
  61. package/dist/components.d.ts +12 -93
  62. package/dist/components.js +23 -106
  63. package/dist/components.js.map +1 -1
  64. package/dist/core-CUElvH_C.d.ts +164 -0
  65. package/dist/database.generated-CBmg2950.d.ts +8284 -0
  66. package/dist/event-CW5YB_2p.d.ts +239 -0
  67. package/dist/{file-reference-C6Gkn77H.d.ts → file-reference-D06mEEWW.d.ts} +7 -5
  68. package/dist/functions-D_kgHktt.d.ts +208 -0
  69. package/dist/hooks.d.ts +54 -7
  70. package/dist/hooks.js +204 -17
  71. package/dist/hooks.js.map +1 -1
  72. package/dist/{EventLogo-B3V3otev.d.ts → index-Bl--n7-T.d.ts} +387 -397
  73. package/dist/index.d.ts +94 -261
  74. package/dist/index.js +314 -126
  75. package/dist/index.js.map +1 -1
  76. package/dist/providers.d.ts +7 -8
  77. package/dist/providers.js +6 -13
  78. package/dist/rbac/index.d.ts +171 -101
  79. package/dist/rbac/index.js +23 -17
  80. package/dist/styles/index.d.ts +1 -3
  81. package/dist/styles/index.js +2 -17
  82. package/dist/theming/runtime.js +3 -3
  83. package/dist/types-UU913iLA.d.ts +102 -0
  84. package/dist/{types-Dfz9dmVH.d.ts → types-_x1f4QBF.d.ts} +6 -6
  85. package/dist/types.d.ts +88 -227
  86. package/dist/types.js +64 -112
  87. package/dist/types.js.map +1 -1
  88. package/dist/{usePublicRouteParams-B7PabvuH.d.ts → usePublicRouteParams-JJczomYq.d.ts} +203 -6
  89. package/dist/utils.d.ts +299 -13
  90. package/dist/utils.js +481 -55
  91. package/dist/utils.js.map +1 -1
  92. package/dist/validation-643vUDZW.d.ts +177 -0
  93. package/docs/DOCUMENTATION_REVIEW_TRACKER.md +511 -0
  94. package/docs/README.md +9 -8
  95. package/docs/api/README.md +16 -2
  96. package/docs/api/classes/ColumnFactory.md +1 -1
  97. package/docs/api/classes/ErrorBoundary.md +1 -1
  98. package/docs/api/classes/InvalidScopeError.md +4 -4
  99. package/docs/api/classes/MissingUserContextError.md +4 -4
  100. package/docs/api/classes/OrganisationContextRequiredError.md +4 -4
  101. package/docs/api/classes/PermissionDeniedError.md +4 -4
  102. package/docs/api/classes/RBACAuditManager.md +14 -14
  103. package/docs/api/classes/RBACCache.md +1 -1
  104. package/docs/api/classes/RBACEngine.md +2 -2
  105. package/docs/api/classes/RBACError.md +4 -4
  106. package/docs/api/classes/RBACNotInitializedError.md +4 -4
  107. package/docs/api/classes/SecureSupabaseClient.md +29 -9
  108. package/docs/api/classes/StorageUtils.md +1 -1
  109. package/docs/api/enums/FileCategory.md +17 -17
  110. package/docs/api/enums/RBACErrorCode.md +228 -0
  111. package/docs/api/enums/RPCFunction.md +118 -0
  112. package/docs/api/interfaces/AggregateConfig.md +1 -1
  113. package/docs/api/interfaces/BadgeProps.md +1 -1
  114. package/docs/api/interfaces/ButtonProps.md +2 -2
  115. package/docs/api/interfaces/CalendarProps.md +1 -1
  116. package/docs/api/interfaces/CardProps.md +29 -3
  117. package/docs/api/interfaces/ColorPalette.md +1 -1
  118. package/docs/api/interfaces/ColorShade.md +1 -1
  119. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  120. package/docs/api/interfaces/DataRecord.md +1 -1
  121. package/docs/api/interfaces/DataTableAction.md +2 -2
  122. package/docs/api/interfaces/DataTableColumn.md +6 -6
  123. package/docs/api/interfaces/DataTableProps.md +1 -1
  124. package/docs/api/interfaces/DataTableToolbarButton.md +2 -2
  125. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  126. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  127. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  128. package/docs/api/interfaces/ExportColumn.md +5 -5
  129. package/docs/api/interfaces/ExportOptions.md +4 -4
  130. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  131. package/docs/api/interfaces/FileMetadata.md +13 -13
  132. package/docs/api/interfaces/FileReference.md +12 -12
  133. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  134. package/docs/api/interfaces/FileUploadOptions.md +10 -10
  135. package/docs/api/interfaces/FileUploadProps.md +19 -19
  136. package/docs/api/interfaces/FooterProps.md +1 -1
  137. package/docs/api/interfaces/FormFieldProps.md +166 -0
  138. package/docs/api/interfaces/FormProps.md +113 -0
  139. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  140. package/docs/api/interfaces/InactivityWarningModalProps.md +8 -8
  141. package/docs/api/interfaces/InputProps.md +2 -2
  142. package/docs/api/interfaces/LabelProps.md +8 -8
  143. package/docs/api/interfaces/LoginFormProps.md +1 -1
  144. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  145. package/docs/api/interfaces/NavigationContextType.md +1 -1
  146. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  147. package/docs/api/interfaces/NavigationItem.md +17 -73
  148. package/docs/api/interfaces/NavigationMenuProps.md +38 -53
  149. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  150. package/docs/api/interfaces/Organisation.md +13 -13
  151. package/docs/api/interfaces/OrganisationContextType.md +21 -21
  152. package/docs/api/interfaces/OrganisationMembership.md +15 -15
  153. package/docs/api/interfaces/OrganisationProviderProps.md +59 -2
  154. package/docs/api/interfaces/OrganisationSecurityError.md +5 -5
  155. package/docs/api/interfaces/PaceAppLayoutProps.md +26 -39
  156. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  157. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  158. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  159. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  160. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  161. package/docs/api/interfaces/PaletteData.md +1 -1
  162. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  163. package/docs/api/interfaces/ProgressProps.md +50 -0
  164. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  165. package/docs/api/interfaces/PublicPageFooterProps.md +9 -9
  166. package/docs/api/interfaces/PublicPageHeaderProps.md +10 -10
  167. package/docs/api/interfaces/PublicPageLayoutProps.md +15 -15
  168. package/docs/api/interfaces/RBACAccessValidateParams.md +52 -0
  169. package/docs/api/interfaces/RBACAccessValidateResult.md +41 -0
  170. package/docs/api/interfaces/RBACAuditLogParams.md +85 -0
  171. package/docs/api/interfaces/RBACAuditLogResult.md +52 -0
  172. package/docs/api/interfaces/RBACConfig.md +2 -2
  173. package/docs/api/interfaces/RBACContext.md +52 -0
  174. package/docs/api/interfaces/RBACLogger.md +1 -1
  175. package/docs/api/interfaces/RBACPageAccessCheckParams.md +74 -0
  176. package/docs/api/interfaces/RBACPermissionCheckParams.md +74 -0
  177. package/docs/api/interfaces/RBACPermissionCheckResult.md +52 -0
  178. package/docs/api/interfaces/RBACPermissionsGetParams.md +63 -0
  179. package/docs/api/interfaces/RBACPermissionsGetResult.md +63 -0
  180. package/docs/api/interfaces/RBACResult.md +58 -0
  181. package/docs/api/interfaces/RBACRoleGrantParams.md +63 -0
  182. package/docs/api/interfaces/RBACRoleGrantResult.md +52 -0
  183. package/docs/api/interfaces/RBACRoleRevokeParams.md +63 -0
  184. package/docs/api/interfaces/RBACRoleRevokeResult.md +52 -0
  185. package/docs/api/interfaces/RBACRoleValidateParams.md +52 -0
  186. package/docs/api/interfaces/RBACRoleValidateResult.md +63 -0
  187. package/docs/api/interfaces/RBACRolesListParams.md +52 -0
  188. package/docs/api/interfaces/RBACRolesListResult.md +74 -0
  189. package/docs/api/interfaces/RBACSessionTrackParams.md +74 -0
  190. package/docs/api/interfaces/RBACSessionTrackResult.md +52 -0
  191. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  192. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  193. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  194. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  195. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  196. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  197. package/docs/api/interfaces/RouteConfig.md +1 -1
  198. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  199. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  200. package/docs/api/interfaces/SessionRestorationLoaderProps.md +15 -2
  201. package/docs/api/interfaces/StorageConfig.md +1 -1
  202. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  203. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  204. package/docs/api/interfaces/StorageListOptions.md +1 -1
  205. package/docs/api/interfaces/StorageListResult.md +1 -1
  206. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  207. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  208. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  209. package/docs/api/interfaces/StyleImport.md +1 -1
  210. package/docs/api/interfaces/SwitchProps.md +1 -1
  211. package/docs/api/interfaces/TabsContentProps.md +1 -1
  212. package/docs/api/interfaces/TabsListProps.md +1 -1
  213. package/docs/api/interfaces/TabsProps.md +1 -1
  214. package/docs/api/interfaces/TabsTriggerProps.md +43 -2
  215. package/docs/api/interfaces/TextareaProps.md +2 -2
  216. package/docs/api/interfaces/ToastActionElement.md +1 -1
  217. package/docs/api/interfaces/ToastProps.md +1 -1
  218. package/docs/api/interfaces/UnifiedAuthContextType.md +61 -61
  219. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  220. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  221. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  222. package/docs/api/interfaces/UsePublicEventLogoOptions.md +87 -0
  223. package/docs/api/interfaces/UsePublicEventLogoReturn.md +81 -0
  224. package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
  225. package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
  226. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
  227. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  228. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  229. package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
  230. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  231. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  232. package/docs/api/interfaces/UserEventAccess.md +1 -1
  233. package/docs/api/interfaces/UserMenuProps.md +4 -4
  234. package/docs/api/interfaces/UserProfile.md +7 -7
  235. package/docs/api/modules.md +484 -462
  236. package/docs/api-reference/components.md +186 -15
  237. package/docs/api-reference/deprecated.md +376 -0
  238. package/docs/api-reference/hooks.md +149 -19
  239. package/docs/api-reference/providers.md +61 -6
  240. package/docs/api-reference/rpc-functions.md +397 -0
  241. package/docs/api-reference/types.md +135 -78
  242. package/docs/api-reference/utilities.md +51 -380
  243. package/docs/architecture/README.md +49 -3
  244. package/docs/architecture/database-schema-requirements.md +40 -3
  245. package/docs/architecture/rbac-security-architecture.md +41 -4
  246. package/docs/architecture/services.md +127 -42
  247. package/docs/best-practices/README.md +51 -5
  248. package/docs/best-practices/accessibility.md +32 -3
  249. package/docs/best-practices/common-patterns.md +50 -3
  250. package/docs/best-practices/deployment.md +50 -4
  251. package/docs/best-practices/performance.md +50 -3
  252. package/docs/best-practices/security.md +94 -41
  253. package/docs/best-practices/testing.md +33 -4
  254. package/docs/core-concepts/authentication.md +5 -5
  255. package/docs/core-concepts/events.md +3 -3
  256. package/docs/core-concepts/organisations.md +3 -3
  257. package/docs/core-concepts/permissions.md +3 -3
  258. package/docs/core-concepts/rbac-system.md +5 -5
  259. package/docs/documentation-index.md +30 -8
  260. package/docs/getting-started/documentation-index.md +1 -1
  261. package/docs/getting-started/examples/README.md +7 -5
  262. package/docs/getting-started/examples/basic-auth-app.md +3 -0
  263. package/docs/getting-started/examples/full-featured-app.md +5 -3
  264. package/docs/getting-started/faq.md +6 -6
  265. package/docs/getting-started/installation-guide.md +192 -13
  266. package/docs/getting-started/local-development.md +303 -0
  267. package/docs/getting-started/quick-reference.md +3 -3
  268. package/docs/getting-started/quick-start.md +517 -0
  269. package/docs/implementation-guides/app-layout.md +45 -3
  270. package/docs/implementation-guides/authentication.md +66 -7
  271. package/docs/implementation-guides/component-styling.md +53 -3
  272. package/docs/implementation-guides/data-tables.md +76 -7
  273. package/docs/implementation-guides/datatable-filtering.md +1 -2
  274. package/docs/implementation-guides/datatable-rbac-usage.md +0 -1
  275. package/docs/implementation-guides/dynamic-colors.md +155 -4
  276. package/docs/implementation-guides/file-reference-system.md +72 -3
  277. package/docs/implementation-guides/file-upload-storage.md +72 -3
  278. package/docs/implementation-guides/forms.md +53 -3
  279. package/docs/implementation-guides/inactivity-tracking.md +53 -3
  280. package/docs/implementation-guides/large-datasets.md +1 -1
  281. package/docs/implementation-guides/navigation.md +55 -5
  282. package/docs/implementation-guides/organisation-security.md +72 -3
  283. package/docs/implementation-guides/performance.md +57 -1
  284. package/docs/implementation-guides/permission-enforcement.md +81 -8
  285. package/docs/implementation-guides/public-pages.md +560 -14
  286. package/docs/migration/MIGRATION_GUIDE.md +409 -50
  287. package/docs/migration/README.md +37 -3
  288. package/docs/migration/organisation-context-timing-fix.md +39 -4
  289. package/docs/migration/quick-migration-guide.md +41 -5
  290. package/docs/migration/rbac-migration.md +59 -3
  291. package/docs/migration/service-architecture.md +77 -14
  292. package/docs/rbac/README.md +79 -3
  293. package/docs/rbac/advanced-patterns.md +47 -3
  294. package/docs/rbac/api-reference.md +77 -8
  295. package/docs/rbac/event-based-apps.md +50 -5
  296. package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
  297. package/docs/rbac/examples.md +39 -3
  298. package/docs/rbac/getting-started.md +63 -4
  299. package/docs/rbac/quick-start.md +57 -5
  300. package/docs/rbac/rbac-rls-integration.md +68 -6
  301. package/docs/rbac/super-admin-guide.md +47 -3
  302. package/docs/rbac/troubleshooting.md +3 -3
  303. package/docs/security/README.md +68 -3
  304. package/docs/security/checklist.md +50 -3
  305. package/docs/standards/01-architecture-standard.md +39 -0
  306. package/docs/standards/02-api-and-rpc-standard.md +39 -0
  307. package/docs/standards/03-component-standard.md +32 -0
  308. package/docs/standards/04-code-style-standard.md +32 -0
  309. package/docs/standards/05-security-standard.md +30 -0
  310. package/docs/standards/06-testing-and-docs-standard.md +29 -0
  311. package/docs/standards/README.md +35 -0
  312. package/docs/styles/README.md +89 -8
  313. package/docs/testing/README.md +175 -24
  314. package/docs/troubleshooting/README.md +50 -3
  315. package/docs/troubleshooting/common-issues.md +271 -5
  316. package/docs/troubleshooting/debugging.md +54 -1
  317. package/docs/troubleshooting/migration.md +54 -1
  318. package/docs/troubleshooting/organisation-context-setup.md +29 -3
  319. package/docs/troubleshooting/styling-issues.md +246 -4
  320. package/{src/components/DataTable/examples → examples/DataTable}/GroupingAggregationExample.tsx +1 -1
  321. package/examples/{components 2/DataTable/HierarchicalActionsExample.tsx → DataTable/HierarchicalActionsExample.tsx} +7 -6
  322. package/{src/components/DataTable/examples → examples/DataTable}/HierarchicalExample.tsx +8 -6
  323. package/examples/{components 2/DataTable/PerformanceExample.tsx → DataTable/PerformanceExample.tsx} +2 -2
  324. package/examples/{components 2/DataTable/index.ts → DataTable/index.ts} +1 -0
  325. package/{src/components/Dialog/examples → examples/Dialog}/HtmlDialogExample.tsx +3 -3
  326. package/examples/{components 2/Dialog/ScrollableDialogExample.tsx → Dialog/ScrollableDialogExample.tsx} +1 -1
  327. package/{src/components/Dialog/examples → examples/Dialog}/SmartDialogExample.tsx +1 -1
  328. package/examples/{components 2/Dialog/index.ts → Dialog/index.ts} +0 -3
  329. package/examples/{features/public-pages → PublicPages}/CorrectPublicPageImplementation.tsx +52 -17
  330. package/examples/{features/public-pages → PublicPages}/PublicEventPage.tsx +65 -35
  331. package/examples/{features/public-pages → PublicPages}/PublicPageApp.tsx +52 -18
  332. package/examples/{features/public-pages → PublicPages}/PublicPageUsageExample.tsx +28 -15
  333. package/examples/README.md +81 -33
  334. package/examples/index.ts +14 -12
  335. package/examples/{RBAC → rbac}/CompleteRBACExample.tsx +1 -1
  336. package/examples/{features/rbac → rbac}/EventBasedApp.tsx +4 -4
  337. package/examples/{features/rbac → rbac}/PermissionExample.tsx +5 -3
  338. package/package.json +21 -27
  339. package/src/__tests__/helpers/test-utils.tsx +29 -3
  340. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +7 -5
  341. package/src/components/Alert/Alert.test.tsx +2 -2
  342. package/src/components/Alert/Alert.tsx +4 -4
  343. package/src/components/Avatar/Avatar.test.tsx +17 -6
  344. package/src/components/Badge/Badge.test.tsx +1 -1
  345. package/src/components/Badge/Badge.tsx +2 -2
  346. package/src/components/Button/Button.test.tsx +2 -2
  347. package/src/components/Button/Button.tsx +11 -7
  348. package/src/components/Calendar/Calendar.test.tsx +41 -8
  349. package/src/components/Calendar/Calendar.tsx +39 -36
  350. package/src/components/Card/Card.tsx +51 -13
  351. package/src/components/Checkbox/Checkbox.test.tsx +36 -12
  352. package/src/components/DataTable/DataTable.test.tsx +1 -1
  353. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +13 -7
  354. package/src/components/DataTable/__tests__/DataTable.default-state.test.tsx +14 -42
  355. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +13 -10
  356. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +14 -11
  357. package/src/components/DataTable/__tests__/DataTable.hooks.test.tsx +4 -2
  358. package/src/components/DataTable/__tests__/DataTable.test.tsx +13 -7
  359. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +13 -10
  360. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +15 -11
  361. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +12 -6
  362. package/src/components/DataTable/__tests__/keyboard.test.tsx +12 -6
  363. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +10 -6
  364. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +1 -1
  365. package/src/components/DataTable/components/DataTableBody.tsx +10 -25
  366. package/src/components/DataTable/components/DataTableCore.tsx +1 -1
  367. package/src/components/DataTable/components/FilterRow.tsx +3 -1
  368. package/src/components/DataTable/components/ImportModal.tsx +1 -1
  369. package/src/components/DataTable/components/VirtualizedDataTable.tsx +9 -9
  370. package/src/components/DataTable/core/ColumnFactory.ts +6 -6
  371. package/src/components/DataTable/core/DataTableContext.tsx +14 -10
  372. package/src/components/DataTable/core/LocalDataAdapter.ts +2 -1
  373. package/src/components/DataTable/core/PluginRegistry.ts +3 -3
  374. package/src/components/DataTable/core/StateManager.ts +12 -11
  375. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +104 -0
  376. package/src/components/DataTable/core/__tests__/DataManager.test.ts +101 -0
  377. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +84 -0
  378. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +102 -0
  379. package/src/components/DataTable/core/__tests__/StateManager.test.ts +104 -0
  380. package/src/components/DataTable/core/interfaces.ts +17 -17
  381. package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +124 -0
  382. package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +117 -0
  383. package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +102 -0
  384. package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +53 -0
  385. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +0 -2
  386. package/src/components/DataTable/hooks/useDataTablePermissions.ts +9 -8
  387. package/src/components/DataTable/types.ts +5 -5
  388. package/src/components/DataTable/utils/aggregationUtils.ts +4 -4
  389. package/src/components/DataTable/utils/columnUtils.ts +3 -2
  390. package/src/components/DataTable/utils/debugTools.ts +1 -1
  391. package/src/components/DataTable/utils/exportUtils.ts +6 -6
  392. package/src/components/DataTable/utils/hierarchicalSorting.ts +6 -6
  393. package/src/components/DataTable/utils/hierarchicalUtils.ts +0 -8
  394. package/src/components/DataTable/utils/index.ts +0 -1
  395. package/src/components/DataTable/utils/performanceUtils.ts +9 -4
  396. package/src/components/Dialog/Dialog.test.tsx +49 -27
  397. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +13 -8
  398. package/src/components/EventSelector/EventSelector.test.tsx +60 -12
  399. package/src/components/EventSelector/EventSelector.tsx +38 -15
  400. package/src/components/EventSelector/index.ts +2 -2
  401. package/src/components/FileDisplay/FileDisplay.test.tsx +143 -85
  402. package/src/components/FileDisplay/FileDisplay.tsx +1 -0
  403. package/src/components/FileUpload/FileUpload.test.tsx +532 -152
  404. package/src/components/FileUpload/FileUpload.tsx +43 -8
  405. package/src/components/Footer/Footer.test.tsx +19 -14
  406. package/src/components/Form/Form.test.tsx +96 -14
  407. package/src/components/Form/Form.tsx +210 -1
  408. package/src/components/Form/index.ts +3 -7
  409. package/src/components/Header/Header.test.tsx +24 -17
  410. package/src/components/Header/Header.tsx +3 -1
  411. package/src/components/InactivityWarningModal/InactivityWarningModal.tsx +2 -4
  412. package/src/components/Input/Input.test.tsx +61 -36
  413. package/src/components/Label/{__tests__/Label.test.tsx → Label.test.tsx} +2 -2
  414. package/src/components/Label/Label.tsx +2 -3
  415. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +6 -5
  416. package/src/components/LoadingSpinner/LoadingSpinner.tsx +6 -2
  417. package/src/components/LoginForm/LoginForm.test.tsx +14 -13
  418. package/src/components/LoginForm/LoginForm.tsx +1 -1
  419. package/src/components/LoginForm/index.ts +7 -0
  420. package/src/components/NavigationMenu/NavigationMenu.test.tsx +233 -20
  421. package/src/components/NavigationMenu/NavigationMenu.tsx +191 -55
  422. package/src/components/NavigationMenu/index.ts +1 -1
  423. package/src/components/OrganisationSelector/OrganisationSelector.test.tsx +20 -11
  424. package/src/components/OrganisationSelector/OrganisationSelector.tsx +1 -1
  425. package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.integration.test.tsx → PaceAppLayout.integration.test.tsx} +272 -79
  426. package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.performance.test.tsx → PaceAppLayout.performance.test.tsx} +155 -32
  427. package/src/components/PaceAppLayout/{__tests__/PaceAppLayout.security.test.tsx → PaceAppLayout.security.test.tsx} +211 -65
  428. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +498 -210
  429. package/src/components/PaceAppLayout/PaceAppLayout.tsx +63 -64
  430. package/src/components/PaceAppLayout/test-setup.tsx +192 -0
  431. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +193 -39
  432. package/src/components/{PasswordReset → PasswordChange}/PasswordChangeForm.test.tsx +2 -2
  433. package/src/components/{PasswordReset → PasswordChange}/PasswordChangeForm.tsx +10 -4
  434. package/src/components/PasswordChange/index.ts +2 -0
  435. package/src/components/Progress/Progress.test.tsx +11 -0
  436. package/src/components/Progress/Progress.tsx +1 -1
  437. package/src/components/Progress/index.ts +10 -0
  438. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +2 -1
  439. package/src/components/PublicLayout/PublicLayout.test.tsx +1210 -0
  440. package/src/components/PublicLayout/PublicPageLayout.tsx +190 -36
  441. package/src/components/PublicLayout/PublicPageProvider.tsx +8 -7
  442. package/src/components/PublicLayout/index.ts +10 -28
  443. package/src/components/Select/Select.test.tsx +7 -7
  444. package/src/components/Select/Select.tsx +277 -11
  445. package/src/components/Select/index.ts +1 -2
  446. package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +232 -0
  447. package/src/components/SessionRestorationLoader/SessionRestorationLoader.tsx +40 -19
  448. package/src/components/Table/{__tests__/Table.test.tsx → Table.test.tsx} +94 -41
  449. package/src/components/Tabs/Tabs.test.tsx +10 -9
  450. package/src/components/Tabs/Tabs.tsx +61 -33
  451. package/src/components/Textarea/Textarea.test.tsx +31 -18
  452. package/src/components/Toast/Toast.tsx +2 -2
  453. package/src/components/Tooltip/Tooltip.test.tsx +1 -1
  454. package/src/components/UserMenu/UserMenu.test.tsx +7 -6
  455. package/src/components/UserMenu/UserMenu.tsx +2 -2
  456. package/src/components/index.ts +5 -4
  457. package/src/constants/performance.ts +19 -8
  458. package/src/hooks/__tests__/useAppConfig.unit.test.ts +21 -22
  459. package/src/hooks/__tests__/useEvents.unit.test.ts +5 -4
  460. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +2 -2
  461. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -0
  462. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +16 -11
  463. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +1 -3
  464. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +1 -3
  465. package/src/hooks/__tests__/useRBAC.unit.test.ts +24 -2
  466. package/src/hooks/index.ts +4 -0
  467. package/src/hooks/public/index.ts +2 -0
  468. package/src/hooks/public/usePublicEvent.ts +4 -6
  469. package/src/hooks/public/usePublicRouteParams.ts +1 -1
  470. package/src/hooks/services/useAuth.ts +2 -4
  471. package/src/hooks/services/useCurrentEvent.ts +1 -1
  472. package/src/hooks/useAppConfig.ts +1 -1
  473. package/src/hooks/useDataTablePerformance.ts +2 -2
  474. package/src/hooks/useEventTheme.ts +1 -1
  475. package/src/hooks/useEvents.ts +51 -10
  476. package/src/hooks/useOrganisationPermissions.test.ts +3 -3
  477. package/src/hooks/useOrganisationPermissions.ts +1 -1
  478. package/src/hooks/useOrganisationSecurity.ts +2 -2
  479. package/src/hooks/usePermissionCache.test.ts +9 -9
  480. package/src/hooks/usePermissionCache.ts +2 -2
  481. package/src/index.ts +19 -12
  482. package/src/providers/OrganisationProvider.tsx +73 -9
  483. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +113 -13
  484. package/src/providers/__tests__/AuthProvider.test.tsx +2 -1
  485. package/src/providers/__tests__/EventProvider.test.tsx +24 -15
  486. package/src/providers/__tests__/OrganisationProvider.test.tsx +87 -36
  487. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +80 -24
  488. package/src/providers/index.ts +0 -3
  489. package/src/providers/services/AuthServiceProvider.tsx +2 -17
  490. package/src/providers/services/EventServiceProvider.tsx +11 -16
  491. package/src/providers/services/InactivityServiceProvider.tsx +9 -12
  492. package/src/providers/services/OrganisationServiceProvider.tsx +9 -12
  493. package/src/providers/services/UnifiedAuthProvider.tsx +85 -18
  494. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +11 -4
  495. package/src/rbac/__tests__/scenarios.user-role.test.tsx +105 -21
  496. package/src/rbac/adapters.tsx +1 -1
  497. package/src/rbac/api.ts +20 -4
  498. package/src/rbac/audit-enhanced.ts +47 -2
  499. package/src/rbac/audit.ts +47 -2
  500. package/src/rbac/components/NavigationGuard.tsx +1 -1
  501. package/src/rbac/components/NavigationProvider.test.tsx +7 -6
  502. package/src/rbac/components/NavigationProvider.tsx +1 -1
  503. package/src/rbac/components/PagePermissionGuard.tsx +1 -1
  504. package/src/rbac/components/PagePermissionProvider.test.tsx +7 -6
  505. package/src/rbac/components/PagePermissionProvider.tsx +1 -1
  506. package/src/rbac/components/PermissionEnforcer.tsx +1 -1
  507. package/src/rbac/components/RoleBasedRouter.tsx +1 -1
  508. package/src/rbac/components/SecureDataProvider.test.tsx +7 -6
  509. package/src/rbac/components/SecureDataProvider.tsx +1 -1
  510. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +6 -6
  511. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +11 -10
  512. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +10 -11
  513. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +19 -15
  514. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +13 -12
  515. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +19 -15
  516. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +18 -18
  517. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +11 -10
  518. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +8 -7
  519. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +10 -11
  520. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +48 -19
  521. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +476 -0
  522. package/src/rbac/hooks/index.ts +3 -0
  523. package/src/rbac/hooks/usePermissions.ts +31 -85
  524. package/src/rbac/hooks/useRBAC.test.ts +13 -1
  525. package/src/rbac/hooks/useRBAC.ts +13 -67
  526. package/src/rbac/hooks/useResolvedScope.ts +11 -0
  527. package/src/rbac/hooks/useSecureSupabase.ts +308 -0
  528. package/src/rbac/index.ts +3 -0
  529. package/src/rbac/secureClient.ts +53 -6
  530. package/src/rbac/security.ts +37 -1
  531. package/src/{types/rbac-functions.ts → rbac/types/functions.ts} +30 -30
  532. package/src/rbac/types.ts +3 -2
  533. package/src/services/AuthService.ts +33 -25
  534. package/src/services/EventService.ts +56 -44
  535. package/src/services/InactivityService.ts +33 -53
  536. package/src/services/OrganisationService.ts +36 -40
  537. package/src/services/__tests__/AuthService.restoreSession.test.ts +6 -2
  538. package/src/services/__tests__/EventService.test.ts +67 -33
  539. package/src/services/interfaces/IEventService.ts +1 -1
  540. package/src/styles/core.css +2 -2
  541. package/src/styles/index.ts +1 -5
  542. package/src/types/__tests__/guards.test.ts +1 -1
  543. package/src/types/__tests__/type-validation.test.ts +0 -1
  544. package/src/types/auth.ts +42 -2
  545. package/src/types/core.ts +251 -0
  546. package/src/types/database.ts +11 -496
  547. package/src/types/event.ts +102 -0
  548. package/src/types/file-reference.ts +6 -4
  549. package/src/types/guards.ts +2 -1
  550. package/src/types/index.ts +48 -14
  551. package/src/types/lodash.debounce.d.ts +15 -0
  552. package/src/types/organisation.ts +14 -10
  553. package/src/types/supabase.ts +15 -17
  554. package/src/utils/__tests__/secureErrors.unit.test.ts +1 -1
  555. package/src/utils/__tests__/validationUtils.unit.test.ts +0 -29
  556. package/src/utils/app/appNameResolver.ts +1 -1
  557. package/src/utils/dynamic/dynamicUtils.ts +3 -2
  558. package/src/utils/file-reference/index.ts +25 -6
  559. package/src/utils/security/secureErrors.ts +1 -1
  560. package/src/utils/validation/index.ts +6 -12
  561. package/src/utils/validation/validationUtils.ts +0 -13
  562. package/dist/UnifiedAuthProvider-B37ATQHE.js +0 -16
  563. package/dist/auth-DReDSLq9.d.ts +0 -16
  564. package/dist/chunk-3JI76CYK.js +0 -2444
  565. package/dist/chunk-3JI76CYK.js.map +0 -1
  566. package/dist/chunk-56XJ3TU6.js +0 -11
  567. package/dist/chunk-56XJ3TU6.js.map +0 -1
  568. package/dist/chunk-5MT24GKJ.js.map +0 -1
  569. package/dist/chunk-7QCC6MCP.js +0 -288
  570. package/dist/chunk-BESYRHQM.js.map +0 -1
  571. package/dist/chunk-BJPBT3CU.js +0 -21
  572. package/dist/chunk-BJPBT3CU.js.map +0 -1
  573. package/dist/chunk-BVYWGZVV.js.map +0 -1
  574. package/dist/chunk-CX5M4ZAG.js.map +0 -1
  575. package/dist/chunk-D7LCGMVS.js.map +0 -1
  576. package/dist/chunk-EGI6MUL6.js +0 -27
  577. package/dist/chunk-EGI6MUL6.js.map +0 -1
  578. package/dist/chunk-ERISIBYU.js.map +0 -1
  579. package/dist/chunk-HRO5HWN2.js.map +0 -1
  580. package/dist/chunk-HZLDFOE4.js.map +0 -1
  581. package/dist/chunk-JISYG63F.js +0 -70
  582. package/dist/chunk-JISYG63F.js.map +0 -1
  583. package/dist/chunk-LIMSTKYD.js +0 -61
  584. package/dist/chunk-LIMSTKYD.js.map +0 -1
  585. package/dist/chunk-OWAG3GSU.js.map +0 -1
  586. package/dist/chunk-PPMP5J6T.js.map +0 -1
  587. package/dist/chunk-Q5QRDWKI.js.map +0 -1
  588. package/dist/chunk-S5OFRT4M.js.map +0 -1
  589. package/dist/chunk-SBVILCCA.js.map +0 -1
  590. package/dist/chunk-TUMEWN34.js +0 -15
  591. package/dist/chunk-TUMEWN34.js.map +0 -1
  592. package/dist/chunk-XDNLUEXI.js +0 -138
  593. package/dist/chunk-XJ2HZOBU.js.map +0 -1
  594. package/dist/chunk-ZYTYSTO5.js.map +0 -1
  595. package/dist/chunk-ZZ2SS7NI.js +0 -237
  596. package/dist/chunk-ZZ2SS7NI.js.map +0 -1
  597. package/dist/database-C6jy7EOu.d.ts +0 -500
  598. package/dist/organisation-D6qRDtbF.d.ts +0 -93
  599. package/dist/schema-DTDZQe2u.d.ts +0 -28
  600. package/dist/unified-DQ4VcT7H.d.ts +0 -198
  601. package/dist/useInactivityTracker-TO6ZOF35.js +0 -11
  602. package/dist/validation.d.ts +0 -47
  603. package/dist/validation.js +0 -24
  604. package/dist/validation.js.map +0 -1
  605. package/docs/DOCUMENTATION_AUDIT.md +0 -172
  606. package/docs/DOCUMENTATION_STANDARD.md +0 -137
  607. package/docs/api/classes/PublicErrorBoundary.md +0 -132
  608. package/docs/api/interfaces/EventLogoProps.md +0 -152
  609. package/docs/api/interfaces/PublicErrorBoundaryProps.md +0 -94
  610. package/docs/api/interfaces/PublicErrorBoundaryState.md +0 -68
  611. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +0 -86
  612. package/docs/architecture/rpc-function-standards.md +0 -1106
  613. package/docs/getting-started/consuming-app-vite-config.md +0 -239
  614. package/docs/implementation-guides/event-theming-summary.md +0 -226
  615. package/docs/implementation-guides/public-pages-advanced.md +0 -1038
  616. package/docs/migration/v0.4.15-tailwind-scanning.md +0 -278
  617. package/docs/migration/v0.4.16-css-first-approach.md +0 -312
  618. package/docs/migration/v0.4.17-source-path-fix.md +0 -235
  619. package/docs/rbac/RBAC_EVENT_CONTEXT_LOADING.md +0 -222
  620. package/docs/rbac/RBAC_LOGIN_SAFETY_FIX.md +0 -95
  621. package/docs/rbac/RBAC_V0.5.147_FIX.md +0 -117
  622. package/docs/rbac/README-rbac-rls-integration.md +0 -374
  623. package/docs/styles/usage.md +0 -227
  624. package/docs/testing/visual-testing.md +0 -120
  625. package/docs/troubleshooting/DEBUG_NETWORK_ERROR.md +0 -152
  626. package/docs/troubleshooting/FIX_SUPABASE_CORS.md +0 -184
  627. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +0 -193
  628. package/docs/troubleshooting/database-view-compatibility.md +0 -125
  629. package/docs/troubleshooting/react-hooks-issue-analysis.md +0 -172
  630. package/docs/troubleshooting/tailwind-content-scanning.md +0 -219
  631. package/examples/RBAC/EventBasedApp.tsx +0 -239
  632. package/examples/RBAC/PermissionExample.tsx +0 -151
  633. package/examples/STRUCTURE.md +0 -125
  634. package/examples/components 2/DataTable/HierarchicalExample.tsx +0 -475
  635. package/examples/components 2/Dialog/BasicHtmlTest.tsx +0 -55
  636. package/examples/components 2/Dialog/DebugHtmlExample.tsx +0 -68
  637. package/examples/components 2/Dialog/HtmlDialogExample.tsx +0 -202
  638. package/examples/components 2/Dialog/SimpleHtmlTest.tsx +0 -61
  639. package/examples/components 2/Dialog/SmartDialogExample.tsx +0 -322
  640. package/examples/components 2/index.ts +0 -11
  641. package/examples/features/index.ts +0 -12
  642. package/examples/features/rbac/CompleteRBACExample.tsx +0 -324
  643. package/examples/features/rbac/index.ts +0 -13
  644. package/examples/public-pages/CorrectPublicPageImplementation.tsx +0 -301
  645. package/examples/public-pages/PublicEventPage.tsx +0 -274
  646. package/examples/public-pages/PublicPageApp.tsx +0 -308
  647. package/examples/public-pages/PublicPageUsageExample.tsx +0 -216
  648. package/examples/public-pages/index.ts +0 -14
  649. package/src/__tests__/TEST_STANDARD.md +0 -1008
  650. package/src/components/Checkbox/__mocks__/Checkbox.tsx +0 -2
  651. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +0 -421
  652. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +0 -177
  653. package/src/components/DataTable/examples/PerformanceExample.tsx +0 -506
  654. package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +0 -316
  655. package/src/components/DataTable/examples/__tests__/HierarchicalExample.test.tsx +0 -45
  656. package/src/components/DataTable/examples/__tests__/InitialPageSizeExample.test.tsx +0 -211
  657. package/src/components/DataTable/examples/__tests__/PerformanceExample.test.tsx +0 -126
  658. package/src/components/Dialog/README.md +0 -804
  659. package/src/components/Dialog/examples/BasicHtmlTest.tsx +0 -55
  660. package/src/components/Dialog/examples/DebugHtmlExample.tsx +0 -68
  661. package/src/components/Dialog/examples/ScrollableDialogExample.tsx +0 -290
  662. package/src/components/Dialog/examples/SimpleHtmlTest.tsx +0 -61
  663. package/src/components/Dialog/examples/__tests__/HtmlDialogExample.test.tsx +0 -71
  664. package/src/components/Dialog/examples/__tests__/SimpleHtmlTest.test.tsx +0 -122
  665. package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +0 -147
  666. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +0 -611
  667. package/src/components/Dialog/utils/safeHtml.ts +0 -185
  668. package/src/components/EventSelector/types.ts +0 -79
  669. package/src/components/Form/FormErrorSummary.tsx +0 -113
  670. package/src/components/Form/FormField.tsx +0 -249
  671. package/src/components/Form/FormFieldset.tsx +0 -127
  672. package/src/components/Form/FormLiveRegion.tsx +0 -198
  673. package/src/components/Input/__mocks__/Input.tsx +0 -2
  674. package/src/components/NavigationMenu/types.ts +0 -85
  675. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +0 -326
  676. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -1078
  677. package/src/components/PasswordReset/PasswordResetForm.test.tsx +0 -597
  678. package/src/components/PasswordReset/PasswordResetForm.tsx +0 -201
  679. package/src/components/PasswordReset/index.ts +0 -2
  680. package/src/components/ProtectedRoute/README.md +0 -164
  681. package/src/components/PublicLayout/EventLogo.tsx +0 -175
  682. package/src/components/PublicLayout/PublicErrorBoundary.tsx +0 -282
  683. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +0 -216
  684. package/src/components/PublicLayout/PublicPageContextChecker.tsx +0 -131
  685. package/src/components/PublicLayout/PublicPageDebugger.tsx +0 -104
  686. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +0 -162
  687. package/src/components/PublicLayout/PublicPageFooter.tsx +0 -124
  688. package/src/components/PublicLayout/PublicPageHeader.tsx +0 -209
  689. package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +0 -449
  690. package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +0 -393
  691. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +0 -192
  692. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +0 -351
  693. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +0 -402
  694. package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +0 -460
  695. package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +0 -313
  696. package/src/components/Select/hooks.ts +0 -289
  697. package/src/hooks/useCounter.test.ts +0 -131
  698. package/src/hooks/useDebounce.test.ts +0 -375
  699. package/src/providers/AuthProvider.tsx +0 -15
  700. package/src/providers/EventProvider.tsx +0 -16
  701. package/src/providers/InactivityProvider.tsx +0 -15
  702. package/src/providers/OrganisationProvider.context.test.tsx +0 -169
  703. package/src/providers/UnifiedAuthProvider.tsx +0 -15
  704. package/src/types/theme.ts +0 -6
  705. package/src/types/unified.ts +0 -265
  706. package/src/utils/appConfig.ts +0 -47
  707. package/src/utils/appIdResolver.test.ts +0 -499
  708. package/src/utils/appIdResolver.ts +0 -130
  709. package/src/utils/appNameResolver.simple.test.ts +0 -212
  710. package/src/utils/appNameResolver.test.ts +0 -121
  711. package/src/utils/appNameResolver.ts +0 -191
  712. package/src/utils/audit.ts +0 -127
  713. package/src/utils/auth-utils.ts +0 -96
  714. package/src/utils/bundleAnalysis.ts +0 -129
  715. package/src/utils/debugLogger.ts +0 -67
  716. package/src/utils/deviceFingerprint.ts +0 -215
  717. package/src/utils/dynamicUtils.ts +0 -105
  718. package/src/utils/file-reference.test.ts +0 -788
  719. package/src/utils/file-reference.ts +0 -519
  720. package/src/utils/formatDate.test.ts +0 -237
  721. package/src/utils/formatting.ts +0 -170
  722. package/src/utils/lazyLoad.tsx +0 -44
  723. package/src/utils/logger.ts +0 -179
  724. package/src/utils/organisationContext.test.ts +0 -322
  725. package/src/utils/organisationContext.ts +0 -153
  726. package/src/utils/performanceBenchmark.ts +0 -64
  727. package/src/utils/performanceBudgets.ts +0 -110
  728. package/src/utils/permissionTypes.ts +0 -37
  729. package/src/utils/permissionUtils.test.ts +0 -393
  730. package/src/utils/permissionUtils.ts +0 -34
  731. package/src/utils/sanitization.ts +0 -264
  732. package/src/utils/schemaUtils.ts +0 -37
  733. package/src/utils/secureDataAccess.test.ts +0 -711
  734. package/src/utils/secureDataAccess.ts +0 -377
  735. package/src/utils/secureErrors.ts +0 -79
  736. package/src/utils/security.ts +0 -156
  737. package/src/utils/securityMonitor.ts +0 -45
  738. package/src/utils/sessionTracking.ts +0 -126
  739. package/src/utils/validation.ts +0 -111
  740. package/src/utils/validationUtils.ts +0 -120
  741. package/src/validation/index.ts +0 -12
  742. /package/dist/{DataTable-UA6CL4JI.js.map → DataTable-QAB34V6K.js.map} +0 -0
  743. /package/dist/{UnifiedAuthProvider-B37ATQHE.js.map → UnifiedAuthProvider-7F6T4B6K.js.map} +0 -0
  744. /package/dist/{api-45XYYO2A.js.map → api-ROMBCNKU.js.map} +0 -0
  745. /package/dist/{audit-64X3VJXB.js.map → audit-WRS3KJKI.js.map} +0 -0
  746. /package/dist/{chunk-PLDDJCW6.js.map → chunk-7D4SUZUM.js.map} +0 -0
  747. /package/dist/{useInactivityTracker-TO6ZOF35.js.map → chunk-KQCRWDSA.js.map} +0 -0
  748. /package/examples/{components 2/DataTable → DataTable}/InitialPageSizeExample.tsx +0 -0
  749. /package/examples/{features/public-pages → PublicPages}/index.ts +0 -0
  750. /package/examples/{RBAC → rbac}/index.ts +0 -0
@@ -0,0 +1,2296 @@
1
+ import {
2
+ assertOrganisationId,
3
+ assertUserId
4
+ } from "./chunk-QXHPKYJV.js";
5
+ import {
6
+ secureStorage,
7
+ setOrganisationContext
8
+ } from "./chunk-VBXEHIUJ.js";
9
+ import {
10
+ createLogger,
11
+ logger
12
+ } from "./chunk-PWLANIRT.js";
13
+
14
+ // src/providers/services/UnifiedAuthProvider.tsx
15
+ import { createContext as createContext5, useContext as useContext6, useMemo as useMemo6, useCallback, useRef as useRef4, useEffect as useEffect10, useState as useState3 } from "react";
16
+
17
+ // src/providers/services/AuthServiceProvider.tsx
18
+ import { createContext, useMemo, useEffect, useState } from "react";
19
+
20
+ // src/services/AuthService.ts
21
+ import { AuthError } from "@supabase/supabase-js";
22
+
23
+ // src/services/base/BaseService.ts
24
+ var BaseService = class {
25
+ constructor() {
26
+ this.subscribers = [];
27
+ this.isInitialized = false;
28
+ }
29
+ /**
30
+ * Subscribe to state changes
31
+ * @param callback Function to call when state changes
32
+ * @returns Unsubscribe function
33
+ */
34
+ subscribe(callback) {
35
+ this.subscribers.push(callback);
36
+ return () => {
37
+ const index = this.subscribers.indexOf(callback);
38
+ if (index > -1) {
39
+ this.subscribers.splice(index, 1);
40
+ }
41
+ };
42
+ }
43
+ /**
44
+ * Notify all subscribers of state changes
45
+ * This triggers React re-renders
46
+ */
47
+ notify() {
48
+ this.subscribers.forEach((callback) => {
49
+ try {
50
+ callback();
51
+ } catch (error) {
52
+ logger.error("BaseService", "Error in subscriber callback:", error);
53
+ }
54
+ });
55
+ }
56
+ /**
57
+ * Initialize the service
58
+ * Override in subclasses to implement initialization logic
59
+ */
60
+ async initialize() {
61
+ if (this.isInitialized) {
62
+ return;
63
+ }
64
+ await this.doInitialize();
65
+ this.isInitialized = true;
66
+ }
67
+ /**
68
+ * Cleanup the service
69
+ * Override in subclasses to implement cleanup logic
70
+ */
71
+ cleanup() {
72
+ this.subscribers = [];
73
+ this.doCleanup();
74
+ this.isInitialized = false;
75
+ }
76
+ /**
77
+ * Check if service is initialized
78
+ */
79
+ getInitialized() {
80
+ return this.isInitialized;
81
+ }
82
+ /**
83
+ * Reset initialization state (allows re-initialization)
84
+ * Use when dependencies change and service needs to re-initialize
85
+ */
86
+ resetInitialization() {
87
+ this.isInitialized = false;
88
+ }
89
+ };
90
+
91
+ // src/services/AuthService.ts
92
+ var AuthService = class extends BaseService {
93
+ constructor(supabaseClient, appName) {
94
+ super();
95
+ this.user = null;
96
+ this.session = null;
97
+ this.authLoading = false;
98
+ this.authError = null;
99
+ this.supabaseClient = null;
100
+ this.authStateSubscription = null;
101
+ this.sessionRestorationState = {
102
+ isRestoring: false,
103
+ restorationComplete: false,
104
+ restorationError: null
105
+ };
106
+ this.restorationTimeoutId = null;
107
+ this.restorationTimeoutMs = 5e3;
108
+ this.restorationStartTime = null;
109
+ this.appName = void 0;
110
+ this.errorHandler = null;
111
+ this.unhandledRejectionHandler = null;
112
+ this.supabaseClient = supabaseClient;
113
+ this.appName = appName;
114
+ }
115
+ // Auth state getters
116
+ getUser() {
117
+ return this.user;
118
+ }
119
+ getSession() {
120
+ return this.session;
121
+ }
122
+ isAuthenticated() {
123
+ return !!(this.user && this.session);
124
+ }
125
+ isLoading() {
126
+ return this.authLoading;
127
+ }
128
+ getError() {
129
+ return this.authError;
130
+ }
131
+ getSupabaseClient() {
132
+ return this.supabaseClient;
133
+ }
134
+ getSessionRestorationState() {
135
+ return { ...this.sessionRestorationState };
136
+ }
137
+ // Auth methods
138
+ async signIn(email, password) {
139
+ if (!this.supabaseClient) {
140
+ const error = new AuthError("Supabase client not available");
141
+ this.authError = error;
142
+ this.notify();
143
+ return { user: null, session: null, error };
144
+ }
145
+ try {
146
+ const { data, error } = await this.supabaseClient.auth.signInWithPassword({
147
+ email,
148
+ password: password || ""
149
+ });
150
+ if (error) {
151
+ this.authError = error;
152
+ this.user = null;
153
+ this.session = null;
154
+ } else {
155
+ this.authError = null;
156
+ this.user = data.user;
157
+ this.session = data.session;
158
+ }
159
+ this.notify();
160
+ return { user: data.user, session: data.session, error };
161
+ } catch (error) {
162
+ const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
163
+ this.authError = authError;
164
+ this.user = null;
165
+ this.session = null;
166
+ this.notify();
167
+ return { user: null, session: null, error: authError };
168
+ }
169
+ }
170
+ async signUp(email, password) {
171
+ if (!this.supabaseClient) {
172
+ const error = new AuthError("Supabase client not available");
173
+ this.authError = error;
174
+ this.notify();
175
+ return { user: null, session: null, error };
176
+ }
177
+ try {
178
+ const { data, error } = await this.supabaseClient.auth.signUp({
179
+ email,
180
+ password
181
+ });
182
+ if (error) {
183
+ this.authError = error;
184
+ this.user = null;
185
+ this.session = null;
186
+ } else {
187
+ this.authError = null;
188
+ this.user = data.user;
189
+ this.session = data.session;
190
+ }
191
+ this.notify();
192
+ return { user: data.user, session: data.session, error };
193
+ } catch (error) {
194
+ const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
195
+ this.authError = authError;
196
+ this.user = null;
197
+ this.session = null;
198
+ this.notify();
199
+ return { user: null, session: null, error: authError };
200
+ }
201
+ }
202
+ async signOut() {
203
+ if (!this.supabaseClient) {
204
+ const error = new AuthError("Supabase client not available");
205
+ this.authError = error;
206
+ this.notify();
207
+ return { user: null, session: null, error };
208
+ }
209
+ try {
210
+ const { error } = await this.supabaseClient.auth.signOut();
211
+ if (error) {
212
+ this.authError = error;
213
+ } else {
214
+ this.authError = null;
215
+ this.user = null;
216
+ this.session = null;
217
+ }
218
+ this.notify();
219
+ return { user: null, session: null, error };
220
+ } catch (error) {
221
+ const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
222
+ this.authError = authError;
223
+ this.user = null;
224
+ this.session = null;
225
+ this.notify();
226
+ return { user: null, session: null, error: authError };
227
+ }
228
+ }
229
+ async resetPassword(email) {
230
+ if (!this.supabaseClient) {
231
+ const error = new AuthError("Supabase client not available");
232
+ this.authError = error;
233
+ this.notify();
234
+ return { user: null, session: null, error };
235
+ }
236
+ try {
237
+ const { error } = await this.supabaseClient.auth.resetPasswordForEmail(email);
238
+ if (error) {
239
+ this.authError = error;
240
+ } else {
241
+ this.authError = null;
242
+ }
243
+ this.notify();
244
+ return { user: null, session: null, error };
245
+ } catch (error) {
246
+ const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
247
+ this.authError = authError;
248
+ this.notify();
249
+ return { user: null, session: null, error: authError };
250
+ }
251
+ }
252
+ async updatePassword(password) {
253
+ if (!this.supabaseClient) {
254
+ const error = new AuthError("Supabase client not available");
255
+ this.authError = error;
256
+ this.notify();
257
+ return { user: null, session: null, error };
258
+ }
259
+ try {
260
+ const { error } = await this.supabaseClient.auth.updateUser({
261
+ password
262
+ });
263
+ if (error) {
264
+ this.authError = error;
265
+ } else {
266
+ this.authError = null;
267
+ }
268
+ this.notify();
269
+ return { user: null, session: null, error };
270
+ } catch (error) {
271
+ const authError = error;
272
+ this.authError = authError;
273
+ this.notify();
274
+ return { user: null, session: null, error: authError };
275
+ }
276
+ }
277
+ async refreshSession() {
278
+ if (!this.supabaseClient) {
279
+ const error = new AuthError("Supabase client not available");
280
+ this.authError = error;
281
+ this.notify();
282
+ return { user: null, session: null, error };
283
+ }
284
+ try {
285
+ const { data, error } = await this.supabaseClient.auth.refreshSession();
286
+ if (error) {
287
+ this.authError = error;
288
+ this.user = null;
289
+ this.session = null;
290
+ } else {
291
+ this.authError = null;
292
+ if (data?.user && data?.session) {
293
+ this.user = data.user;
294
+ this.session = data.session;
295
+ } else {
296
+ this.user = null;
297
+ this.session = null;
298
+ }
299
+ }
300
+ this.notify();
301
+ return {
302
+ user: data?.user && data?.session ? data.user : null,
303
+ session: data?.session ?? null,
304
+ error
305
+ };
306
+ } catch (error) {
307
+ const authError = error instanceof AuthError ? error : new AuthError(error instanceof Error ? error.message : "Authentication failed");
308
+ this.authError = authError;
309
+ this.user = null;
310
+ this.session = null;
311
+ this.notify();
312
+ return { user: null, session: null, error: authError };
313
+ }
314
+ }
315
+ // Lifecycle methods
316
+ async initialize() {
317
+ await super.initialize();
318
+ await this.setupAuthStateListener();
319
+ await this.restoreSession();
320
+ }
321
+ cleanup() {
322
+ if (this.authStateSubscription) {
323
+ this.authStateSubscription.unsubscribe();
324
+ this.authStateSubscription = null;
325
+ }
326
+ this.clearRestorationTimeout();
327
+ this.restorationStartTime = null;
328
+ this.sessionRestorationState = {
329
+ isRestoring: false,
330
+ restorationComplete: false,
331
+ restorationError: null
332
+ };
333
+ this.authLoading = false;
334
+ super.cleanup();
335
+ }
336
+ async doInitialize() {
337
+ this.setupErrorHandlers();
338
+ }
339
+ doCleanup() {
340
+ this.removeErrorHandlers();
341
+ }
342
+ startSessionRestoration() {
343
+ this.clearRestorationTimeout();
344
+ this.sessionRestorationState = {
345
+ isRestoring: true,
346
+ restorationComplete: false,
347
+ restorationError: null
348
+ };
349
+ this.authLoading = true;
350
+ this.restorationStartTime = Date.now();
351
+ this.notify();
352
+ this.restorationTimeoutId = setTimeout(() => {
353
+ logger.warn("AuthService", "Session restoration timed out after", this.restorationTimeoutMs, "ms");
354
+ const timeoutError = new Error(`Session restoration timed out after ${this.restorationTimeoutMs}ms`);
355
+ timeoutError.name = "SessionRestorationTimeoutError";
356
+ this.finishSessionRestoration(timeoutError);
357
+ }, this.restorationTimeoutMs);
358
+ }
359
+ finishSessionRestoration(error) {
360
+ if (!this.sessionRestorationState.isRestoring && !error) {
361
+ return;
362
+ }
363
+ this.clearRestorationTimeout();
364
+ const completedAt = Date.now();
365
+ const duration = this.restorationStartTime ? completedAt - this.restorationStartTime : null;
366
+ this.restorationStartTime = null;
367
+ const restorationComplete = !error;
368
+ this.sessionRestorationState = {
369
+ isRestoring: false,
370
+ restorationComplete,
371
+ restorationError: error ?? null
372
+ };
373
+ this.authLoading = false;
374
+ if (error) {
375
+ logger.warn("AuthService", "Session restoration finished with error:", error);
376
+ }
377
+ this.notify();
378
+ }
379
+ clearRestorationTimeout() {
380
+ if (this.restorationTimeoutId) {
381
+ clearTimeout(this.restorationTimeoutId);
382
+ this.restorationTimeoutId = null;
383
+ }
384
+ }
385
+ async setupAuthStateListener() {
386
+ if (!this.supabaseClient) {
387
+ this.authLoading = false;
388
+ this.notify();
389
+ return;
390
+ }
391
+ try {
392
+ const subscription = this.supabaseClient.auth.onAuthStateChange(
393
+ (event, session) => {
394
+ try {
395
+ if (event === "SIGNED_OUT") {
396
+ this.session = null;
397
+ this.user = null;
398
+ this.authError = null;
399
+ if (session?.user) {
400
+ this.trackSession("logout", session).catch((err) => {
401
+ logger.warn("AuthService", "Failed to track logout session:", err);
402
+ });
403
+ }
404
+ } else if (event === "SIGNED_IN" || event === "TOKEN_REFRESHED") {
405
+ this.session = session;
406
+ this.user = session?.user ?? null;
407
+ if (session) {
408
+ this.authError = null;
409
+ }
410
+ if (event === "SIGNED_IN" && session?.user) {
411
+ this.trackSession("login", session).catch((err) => {
412
+ logger.warn("AuthService", "Failed to track login session:", err);
413
+ });
414
+ }
415
+ } else if (event === "INITIAL_SESSION") {
416
+ if (session) {
417
+ this.session = session;
418
+ this.user = session.user ?? null;
419
+ this.authError = null;
420
+ const hasTimeoutError = this.sessionRestorationState.restorationError?.name === "SessionRestorationTimeoutError";
421
+ if (this.sessionRestorationState.isRestoring || this.sessionRestorationState.restorationError || hasTimeoutError && session) {
422
+ this.finishSessionRestoration();
423
+ return;
424
+ }
425
+ }
426
+ if (this.sessionRestorationState.isRestoring) {
427
+ this.finishSessionRestoration();
428
+ return;
429
+ }
430
+ }
431
+ this.authLoading = false;
432
+ this.notify();
433
+ } catch (error) {
434
+ logger.warn("AuthService", "Error in auth state change handler:", error);
435
+ this.authLoading = false;
436
+ this.notify();
437
+ }
438
+ }
439
+ );
440
+ this.authStateSubscription = subscription.data.subscription;
441
+ } catch (error) {
442
+ logger.error("AuthService", "Failed to setup auth state listener:", error);
443
+ throw error;
444
+ }
445
+ }
446
+ async restoreSession() {
447
+ if (!this.supabaseClient) {
448
+ const error = new Error("Supabase client not available during session restoration");
449
+ logger.error("AuthService", "Unable to restore session:", error);
450
+ this.finishSessionRestoration(error);
451
+ return;
452
+ }
453
+ this.startSessionRestoration();
454
+ try {
455
+ let currentSession = null;
456
+ let sessionError = null;
457
+ try {
458
+ const { data, error } = await this.supabaseClient.auth.getSession();
459
+ currentSession = data?.session ?? null;
460
+ sessionError = error ?? null;
461
+ } catch (error) {
462
+ currentSession = null;
463
+ sessionError = null;
464
+ }
465
+ if (sessionError) {
466
+ this.authError = sessionError;
467
+ try {
468
+ const { data, error } = await this.supabaseClient.auth.getUser();
469
+ const currentUser = data?.user ?? null;
470
+ const userError = error ?? null;
471
+ if (currentUser) {
472
+ this.user = currentUser;
473
+ this.session = null;
474
+ }
475
+ if (userError && !this.authError) {
476
+ this.authError = userError;
477
+ }
478
+ } catch (getUserError) {
479
+ }
480
+ }
481
+ if (currentSession) {
482
+ this.session = currentSession;
483
+ this.user = currentSession.user;
484
+ this.authError = null;
485
+ } else if (!sessionError) {
486
+ this.session = null;
487
+ this.user = null;
488
+ this.authError = null;
489
+ }
490
+ this.finishSessionRestoration();
491
+ } catch (error) {
492
+ const restorationError = error instanceof Error ? error : new Error("Unknown error during auth initialization");
493
+ logger.error("AuthService", "Error during auth initialization:", restorationError);
494
+ if (restorationError instanceof AuthError) {
495
+ this.authError = restorationError;
496
+ }
497
+ this.finishSessionRestoration(restorationError);
498
+ }
499
+ }
500
+ /**
501
+ * Automatically track user session using rbac_session_track
502
+ * This method is called automatically on SIGNED_IN and SIGNED_OUT events.
503
+ * It's non-blocking and failures are logged as warnings.
504
+ */
505
+ async trackSession(sessionType, session) {
506
+ if (!this.supabaseClient || !session?.user) {
507
+ return;
508
+ }
509
+ try {
510
+ let appId = void 0;
511
+ if (this.appName) {
512
+ const { data, error: error2 } = await this.supabaseClient.from("rbac_apps").select("id").eq("name", this.appName).eq("is_active", true).single();
513
+ if (!error2 && data) {
514
+ appId = data.id;
515
+ }
516
+ }
517
+ const ipAddress = void 0;
518
+ const userAgent = typeof navigator !== "undefined" ? navigator.userAgent : void 0;
519
+ const deviceFingerprint = void 0;
520
+ const { error } = await this.supabaseClient.rpc("rbac_session_track", {
521
+ p_user_id: session.user.id,
522
+ p_session_type: sessionType,
523
+ p_event_id: null,
524
+ // Event ID should come from context, not auth service
525
+ p_app_id: appId,
526
+ p_ip_address: ipAddress,
527
+ p_user_agent: userAgent,
528
+ p_device_fingerprint: deviceFingerprint
529
+ });
530
+ if (error) {
531
+ logger.warn("AuthService", `Failed to track ${sessionType} session:`, error);
532
+ }
533
+ } catch (error) {
534
+ logger.warn("AuthService", `Error tracking ${sessionType} session:`, error);
535
+ }
536
+ }
537
+ setupErrorHandlers() {
538
+ if (typeof window === "undefined") return;
539
+ this.errorHandler = (event) => {
540
+ if (event.error?.message?.includes("AuthSessionMissingError") || event.error?.message?.includes("Auth session missing")) {
541
+ logger.warn("AuthService", "Suppressing AuthSessionMissingError during logout");
542
+ event.preventDefault();
543
+ return false;
544
+ }
545
+ };
546
+ this.unhandledRejectionHandler = (event) => {
547
+ if (event.reason?.message?.includes("AuthSessionMissingError") || event.reason?.message?.includes("Auth session missing")) {
548
+ logger.warn("AuthService", "Suppressing unhandled AuthSessionMissingError");
549
+ event.preventDefault();
550
+ return false;
551
+ }
552
+ };
553
+ window.addEventListener("error", this.errorHandler);
554
+ window.addEventListener("unhandledrejection", this.unhandledRejectionHandler);
555
+ }
556
+ removeErrorHandlers() {
557
+ if (typeof window === "undefined") return;
558
+ if (this.errorHandler) {
559
+ window.removeEventListener("error", this.errorHandler);
560
+ this.errorHandler = null;
561
+ }
562
+ if (this.unhandledRejectionHandler) {
563
+ window.removeEventListener("unhandledrejection", this.unhandledRejectionHandler);
564
+ this.unhandledRejectionHandler = null;
565
+ }
566
+ }
567
+ };
568
+
569
+ // src/providers/services/AuthServiceProvider.tsx
570
+ import { jsx } from "react/jsx-runtime";
571
+ var AuthServiceContext = createContext(null);
572
+ function AuthServiceProvider({ children, supabaseClient, appName }) {
573
+ const authService = useMemo(
574
+ () => new AuthService(supabaseClient, appName),
575
+ [supabaseClient, appName]
576
+ );
577
+ const [sessionRestoration, setSessionRestoration] = useState(
578
+ () => authService.getSessionRestorationState()
579
+ );
580
+ useEffect(() => {
581
+ const unsubscribe = authService.subscribe(() => {
582
+ const restorationState = authService.getSessionRestorationState();
583
+ setSessionRestoration(restorationState);
584
+ });
585
+ return () => {
586
+ unsubscribe();
587
+ };
588
+ }, [authService]);
589
+ useEffect(() => {
590
+ authService.initialize().catch((error) => {
591
+ logger.error("AuthServiceProvider", "Failed to initialize auth service:", error);
592
+ });
593
+ return () => {
594
+ authService.cleanup();
595
+ };
596
+ }, [authService]);
597
+ const contextValue = useMemo(() => ({
598
+ authService,
599
+ sessionRestoration
600
+ }), [authService, sessionRestoration]);
601
+ return /* @__PURE__ */ jsx(AuthServiceContext.Provider, { value: contextValue, children });
602
+ }
603
+
604
+ // src/providers/services/OrganisationServiceProvider.tsx
605
+ import { createContext as createContext2, useMemo as useMemo2, useEffect as useEffect2, useRef } from "react";
606
+
607
+ // src/services/OrganisationService.ts
608
+ var OrganisationService = class extends BaseService {
609
+ constructor(supabaseClient, user, session) {
610
+ super();
611
+ this._selectedOrganisation = null;
612
+ this._organisations = [];
613
+ this._userMemberships = [];
614
+ this._roleMapState = /* @__PURE__ */ new Map();
615
+ this._isLoading = false;
616
+ this._error = null;
617
+ this._isContextReady = false;
618
+ this.retryCount = 0;
619
+ // Dependencies
620
+ this.supabaseClient = null;
621
+ this.user = null;
622
+ this.session = null;
623
+ // Internal state management
624
+ this.isLoadingRef = false;
625
+ this.lastLoadTimeRef = 0;
626
+ this.hasFailedRef = false;
627
+ this.abortControllerRef = null;
628
+ this.supabaseClient = supabaseClient;
629
+ this.user = user;
630
+ this.session = session;
631
+ }
632
+ // Interface implementation
633
+ getSelectedOrganisation() {
634
+ return this._selectedOrganisation;
635
+ }
636
+ getOrganisations() {
637
+ return this._organisations;
638
+ }
639
+ getUserMemberships() {
640
+ return this._userMemberships;
641
+ }
642
+ isLoading() {
643
+ return this._isLoading;
644
+ }
645
+ getError() {
646
+ return this._error;
647
+ }
648
+ hasValidOrganisationContext() {
649
+ return !!(this._selectedOrganisation && !this._isLoading && !this._error && this._isContextReady);
650
+ }
651
+ isContextReady() {
652
+ return this._isContextReady;
653
+ }
654
+ // Additional methods for testing
655
+ setSelectedOrganisation(organisation) {
656
+ this._selectedOrganisation = organisation;
657
+ if (organisation) {
658
+ localStorage.setItem("pace-core-selected-organisation", JSON.stringify(organisation));
659
+ this.setDatabaseOrganisationContext(organisation);
660
+ } else {
661
+ localStorage.removeItem("pace-core-selected-organisation");
662
+ this._isContextReady = false;
663
+ }
664
+ this.notify();
665
+ }
666
+ // For testing: expose dependencies
667
+ getDependencies() {
668
+ return {
669
+ user: this.user,
670
+ session: this.session,
671
+ supabaseClient: this.supabaseClient
672
+ };
673
+ }
674
+ // For testing: manually set state
675
+ setTestState(organisations, memberships, roleMap, selectedOrg = null) {
676
+ this._organisations = organisations;
677
+ this._userMemberships = memberships;
678
+ this._roleMapState = roleMap;
679
+ if (selectedOrg) {
680
+ this._selectedOrganisation = selectedOrg;
681
+ } else if (organisations.length > 0) {
682
+ this._selectedOrganisation = organisations[0];
683
+ }
684
+ this._isLoading = false;
685
+ this._error = null;
686
+ this.notify();
687
+ }
688
+ // Update dependencies
689
+ updateDependencies(user, session) {
690
+ const wasAuthenticated = !!(this.user && this.session);
691
+ const isAuthenticated = !!(user && session);
692
+ this.user = user;
693
+ this.session = session;
694
+ if (wasAuthenticated && !isAuthenticated) {
695
+ this.resetInitialization();
696
+ }
697
+ this.notify();
698
+ }
699
+ // Organisation methods
700
+ async switchOrganisation(orgId) {
701
+ if (!this.validateOrganisationAccess(orgId)) {
702
+ throw new Error(`User does not have access to organisation ${orgId}`);
703
+ }
704
+ const targetOrg = this._organisations.find((org) => org.id === orgId);
705
+ if (!targetOrg) {
706
+ throw new Error(`Organisation ${orgId} not found in user's organisations`);
707
+ }
708
+ this._selectedOrganisation = targetOrg;
709
+ localStorage.setItem("pace-core-selected-organisation", JSON.stringify(targetOrg));
710
+ await this.setDatabaseOrganisationContext(targetOrg);
711
+ this.notify();
712
+ }
713
+ getUserRole(orgId) {
714
+ const targetOrgId = orgId || this._selectedOrganisation?.id;
715
+ if (!targetOrgId) return "no_access";
716
+ return this._roleMapState.get(targetOrgId) || "no_access";
717
+ }
718
+ validateOrganisationAccess(orgId) {
719
+ return this._userMemberships.some(
720
+ (m) => m.organisation_id === orgId && m.status === "active" && m.revoked_at === null
721
+ );
722
+ }
723
+ async refreshOrganisations() {
724
+ if (!this.user || !this.session || !this.supabaseClient) return;
725
+ this._isLoading = true;
726
+ this.notify();
727
+ await this.loadUserOrganisations();
728
+ }
729
+ ensureOrganisationContext() {
730
+ if (!this._selectedOrganisation) {
731
+ throw new Error("Organisation context is required but not available");
732
+ }
733
+ return this._selectedOrganisation;
734
+ }
735
+ isOrganisationSecure() {
736
+ return !!(this._selectedOrganisation && this.user);
737
+ }
738
+ getPrimaryOrganisation() {
739
+ const rolePriority = ["org_admin", "leader", "member"];
740
+ for (const role of rolePriority) {
741
+ const membership = this._userMemberships.find((m) => m.role === role);
742
+ if (membership) {
743
+ return this._organisations.find((org) => org.id === membership.organisation_id) || null;
744
+ }
745
+ }
746
+ return null;
747
+ }
748
+ buildOrganisationHierarchy(orgs) {
749
+ const orgMap = /* @__PURE__ */ new Map();
750
+ orgs.forEach((org) => orgMap.set(org.id, org));
751
+ const roots = [];
752
+ orgs.forEach((org) => {
753
+ if (!org.parent_id) {
754
+ roots.push({
755
+ organisation: org,
756
+ children: [],
757
+ depth: 0
758
+ });
759
+ }
760
+ });
761
+ return roots;
762
+ }
763
+ // Lifecycle methods
764
+ async initialize() {
765
+ await super.initialize();
766
+ if (!this.isLoadingRef) {
767
+ await this.loadUserOrganisations();
768
+ }
769
+ }
770
+ cleanup() {
771
+ this.isLoadingRef = false;
772
+ this.hasFailedRef = false;
773
+ this.lastLoadTimeRef = 0;
774
+ if (this.abortControllerRef) {
775
+ this.abortControllerRef = null;
776
+ }
777
+ this._selectedOrganisation = null;
778
+ this._organisations = [];
779
+ this._userMemberships = [];
780
+ this._roleMapState = /* @__PURE__ */ new Map();
781
+ this._isLoading = false;
782
+ this._error = null;
783
+ this._isContextReady = false;
784
+ super.cleanup();
785
+ }
786
+ async doInitialize() {
787
+ }
788
+ doCleanup() {
789
+ }
790
+ async setDatabaseOrganisationContext(organisation) {
791
+ if (!this.supabaseClient || !this.session) {
792
+ logger.warn("OrganisationService", "No Supabase client or session available for setting organisation context");
793
+ this._isContextReady = false;
794
+ this.notify();
795
+ return;
796
+ }
797
+ try {
798
+ const timeoutPromise = new Promise((_, reject) => {
799
+ setTimeout(() => reject(new Error("Context setting timeout after 5 seconds")), 5e3);
800
+ });
801
+ const contextPromise = setOrganisationContext(this.supabaseClient, organisation.id);
802
+ await Promise.race([contextPromise, timeoutPromise]);
803
+ this._isContextReady = true;
804
+ this.notify();
805
+ } catch (error) {
806
+ logger.error("OrganisationService", "Failed to set database organisation context:", error);
807
+ this._isContextReady = true;
808
+ this.notify();
809
+ }
810
+ }
811
+ async loadUserOrganisations() {
812
+ if (!this.user || !this.session || !this.supabaseClient) {
813
+ this._selectedOrganisation = null;
814
+ this._organisations = [];
815
+ this._userMemberships = [];
816
+ this._isLoading = false;
817
+ this._error = null;
818
+ this.notify();
819
+ return;
820
+ }
821
+ if (this.isLoadingRef) {
822
+ this._isLoading = true;
823
+ this.notify();
824
+ return;
825
+ }
826
+ const now = Date.now();
827
+ if (now - this.lastLoadTimeRef < 2e3) {
828
+ if (this._organisations.length > 0 || this._selectedOrganisation) {
829
+ this._isLoading = false;
830
+ } else {
831
+ this._isLoading = true;
832
+ }
833
+ this.notify();
834
+ return;
835
+ }
836
+ if (this.abortControllerRef) {
837
+ this.abortControllerRef.abort();
838
+ }
839
+ this.abortControllerRef = new AbortController();
840
+ const abortSignal = this.abortControllerRef.signal;
841
+ this.lastLoadTimeRef = now;
842
+ this.isLoadingRef = true;
843
+ this._isLoading = true;
844
+ this._error = null;
845
+ this.notify();
846
+ try {
847
+ let memberships, membershipError;
848
+ try {
849
+ const timeoutPromise = new Promise((_, reject) => {
850
+ const timeoutId = setTimeout(() => reject(new Error("RPC call timeout after 10 seconds")), 1e4);
851
+ abortSignal.addEventListener("abort", () => {
852
+ clearTimeout(timeoutId);
853
+ reject(new Error("Request aborted"));
854
+ });
855
+ });
856
+ const rpcPromise = this.supabaseClient.rpc("data_user_organisation_roles_get", {
857
+ p_user_id: this.user.id,
858
+ p_organisation_id: null
859
+ });
860
+ if (abortSignal.aborted) {
861
+ throw new Error("Request aborted");
862
+ }
863
+ const result = await Promise.race([rpcPromise, timeoutPromise]);
864
+ memberships = result.data?.filter(
865
+ (role) => ["org_admin", "leader", "member"].includes(role.role)
866
+ ).map((m) => ({
867
+ ...m,
868
+ user_id: assertUserId(m.user_id),
869
+ organisation_id: assertOrganisationId(m.organisation_id)
870
+ })) || [];
871
+ membershipError = result.error;
872
+ } catch (queryError) {
873
+ membershipError = queryError instanceof Error ? queryError : new Error(String(queryError));
874
+ }
875
+ if (membershipError) {
876
+ logger.error("OrganisationService", "Error loading memberships:", membershipError);
877
+ if (membershipError.message?.includes("timeout")) {
878
+ try {
879
+ if (abortSignal.aborted) {
880
+ throw new Error("Request aborted");
881
+ }
882
+ const { data: fallbackData, error: fallbackError } = await this.supabaseClient.from("rbac_organisation_roles").select(`
883
+ id,
884
+ user_id,
885
+ organisation_id,
886
+ role,
887
+ status,
888
+ granted_at,
889
+ granted_by,
890
+ revoked_at,
891
+ revoked_by,
892
+ notes,
893
+ created_at,
894
+ updated_at,
895
+ organisations!inner(
896
+ id,
897
+ name,
898
+ display_name,
899
+ subscription_tier,
900
+ settings,
901
+ is_active,
902
+ parent_id,
903
+ created_at,
904
+ updated_at
905
+ )
906
+ `).eq("user_id", this.user.id).eq("status", "active").is("revoked_at", null).in("role", ["org_admin", "leader", "member"]);
907
+ if (fallbackError) {
908
+ logger.error("OrganisationService", "Fallback query also failed:", fallbackError);
909
+ throw membershipError;
910
+ }
911
+ memberships = fallbackData?.map((m) => ({
912
+ ...m,
913
+ user_id: assertUserId(m.user_id),
914
+ organisation_id: assertOrganisationId(m.organisation_id)
915
+ })) || [];
916
+ membershipError = null;
917
+ } catch (fallbackErr) {
918
+ logger.error("OrganisationService", "Fallback query failed:", fallbackErr);
919
+ throw membershipError;
920
+ }
921
+ } else {
922
+ throw membershipError;
923
+ }
924
+ }
925
+ if (!memberships || memberships.length === 0) {
926
+ throw new Error("User has no active organisation memberships");
927
+ }
928
+ const organisationIds = memberships.map((m) => m.organisation_id).filter((id) => {
929
+ if (!id || typeof id !== "string") {
930
+ logger.warn("OrganisationService", "Invalid organisation ID (not string):", id);
931
+ return false;
932
+ }
933
+ const trimmedId = id.trim();
934
+ if (trimmedId === "") {
935
+ logger.warn("OrganisationService", "Empty organisation ID found");
936
+ return false;
937
+ }
938
+ const isValidUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(trimmedId);
939
+ if (!isValidUuid) {
940
+ logger.warn("OrganisationService", "Invalid UUID format:", trimmedId);
941
+ }
942
+ return isValidUuid;
943
+ });
944
+ if (organisationIds.length === 0) {
945
+ logger.warn("OrganisationService", "No valid organisation IDs found in memberships:", memberships);
946
+ throw new Error("No valid organisation IDs found in memberships");
947
+ }
948
+ if (abortSignal.aborted) {
949
+ throw new Error("Request aborted");
950
+ }
951
+ const { data: allOrganisations, error: orgError } = await this.supabaseClient.from("organisations").select("id, name, display_name, subscription_tier, settings, is_active, parent_id, created_at, updated_at");
952
+ if (orgError) {
953
+ logger.error("OrganisationService", "Error loading organisations:", orgError);
954
+ throw orgError;
955
+ }
956
+ const organisations = allOrganisations?.filter(
957
+ (org) => organisationIds.includes(org.id)
958
+ ) || [];
959
+ const roleMap = /* @__PURE__ */ new Map();
960
+ memberships?.forEach((membership) => {
961
+ roleMap.set(membership.organisation_id, membership.role);
962
+ });
963
+ const orgs = organisations;
964
+ const activeOrgs = orgs.filter((org) => org.is_active);
965
+ if (activeOrgs.length === 0) {
966
+ throw new Error("User has no access to active organisations");
967
+ }
968
+ this._organisations = activeOrgs;
969
+ this._userMemberships = memberships;
970
+ this._roleMapState = roleMap;
971
+ let initialOrg = null;
972
+ try {
973
+ const persistedOrgString = localStorage.getItem("pace-core-selected-organisation");
974
+ if (persistedOrgString) {
975
+ const persistedOrg = JSON.parse(persistedOrgString);
976
+ if (persistedOrg.id && typeof persistedOrg.id === "string" && persistedOrg.id.trim() !== "") {
977
+ const validPersistedOrg = activeOrgs.find((org) => org.id === persistedOrg.id);
978
+ if (validPersistedOrg) {
979
+ initialOrg = validPersistedOrg;
980
+ } else {
981
+ logger.warn("OrganisationService", "Persisted organisation not found in active orgs, clearing cache");
982
+ localStorage.removeItem("pace-core-selected-organisation");
983
+ }
984
+ } else {
985
+ logger.warn("OrganisationService", "Invalid persisted organisation ID, clearing cache");
986
+ localStorage.removeItem("pace-core-selected-organisation");
987
+ }
988
+ }
989
+ } catch (storageError) {
990
+ logger.warn("OrganisationService", "Failed to restore persisted organisation:", storageError);
991
+ localStorage.removeItem("pace-core-selected-organisation");
992
+ }
993
+ if (!initialOrg) {
994
+ const adminMembership = memberships.find((m) => m.role === "org_admin");
995
+ if (adminMembership) {
996
+ const foundOrg = organisations.find((org) => org.id === adminMembership.organisation_id);
997
+ if (foundOrg) {
998
+ initialOrg = foundOrg;
999
+ }
1000
+ }
1001
+ }
1002
+ if (!initialOrg) {
1003
+ initialOrg = activeOrgs[0];
1004
+ }
1005
+ if (!initialOrg) {
1006
+ throw new Error("No valid organisation found for user");
1007
+ }
1008
+ this._selectedOrganisation = initialOrg;
1009
+ localStorage.setItem("pace-core-selected-organisation", JSON.stringify(initialOrg));
1010
+ await this.setDatabaseOrganisationContext(initialOrg);
1011
+ this.retryCount = 0;
1012
+ this.hasFailedRef = false;
1013
+ } catch (err) {
1014
+ logger.error("OrganisationService", "Failed to load organisations:", err);
1015
+ this._error = err;
1016
+ this.retryCount = this.retryCount + 1;
1017
+ this.hasFailedRef = true;
1018
+ this.clearAllCachedData();
1019
+ } finally {
1020
+ this.isLoadingRef = false;
1021
+ this._isLoading = false;
1022
+ this.abortControllerRef = null;
1023
+ this.notify();
1024
+ }
1025
+ }
1026
+ clearAllCachedData() {
1027
+ localStorage.removeItem("pace-core-selected-organisation");
1028
+ localStorage.removeItem("pace-core-organisation-context");
1029
+ this._selectedOrganisation = null;
1030
+ this._organisations = [];
1031
+ this._userMemberships = [];
1032
+ this._roleMapState = /* @__PURE__ */ new Map();
1033
+ this.retryCount = 0;
1034
+ this._isContextReady = false;
1035
+ }
1036
+ };
1037
+
1038
+ // src/providers/services/OrganisationServiceProvider.tsx
1039
+ import { jsx as jsx2 } from "react/jsx-runtime";
1040
+ var OrganisationServiceContext = createContext2(null);
1041
+ function OrganisationServiceProvider({
1042
+ children,
1043
+ supabaseClient,
1044
+ user,
1045
+ session
1046
+ }) {
1047
+ const organisationServiceRef = useRef(null);
1048
+ if (!organisationServiceRef.current) {
1049
+ organisationServiceRef.current = new OrganisationService(supabaseClient, user, session);
1050
+ }
1051
+ const organisationService = organisationServiceRef.current;
1052
+ useEffect2(() => {
1053
+ organisationService.updateDependencies(user, session);
1054
+ let isMounted = true;
1055
+ organisationService.initialize().catch((error) => {
1056
+ if (isMounted) {
1057
+ logger.error("OrganisationServiceProvider", "Failed to initialize organisation service:", error);
1058
+ }
1059
+ });
1060
+ return () => {
1061
+ isMounted = false;
1062
+ };
1063
+ }, [organisationService, user, session]);
1064
+ useEffect2(() => {
1065
+ return () => {
1066
+ organisationService.cleanup();
1067
+ };
1068
+ }, [organisationService]);
1069
+ const contextValue = useMemo2(() => ({
1070
+ organisationService
1071
+ }), [organisationService]);
1072
+ return /* @__PURE__ */ jsx2(OrganisationServiceContext.Provider, { value: contextValue, children });
1073
+ }
1074
+
1075
+ // src/providers/services/EventServiceProvider.tsx
1076
+ import { createContext as createContext3, useMemo as useMemo3, useEffect as useEffect3, useRef as useRef2 } from "react";
1077
+
1078
+ // src/services/EventService.ts
1079
+ var EventService = class extends BaseService {
1080
+ constructor(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId) {
1081
+ super();
1082
+ this.events = [];
1083
+ this.selectedEvent = null;
1084
+ this._isLoading = false;
1085
+ // Start as false to avoid blocking UI
1086
+ this.error = null;
1087
+ // Dependencies
1088
+ this.supabaseClient = null;
1089
+ this.user = null;
1090
+ this.session = null;
1091
+ this.appName = "";
1092
+ this.selectedOrganisation = null;
1093
+ this.setSelectedEventId = null;
1094
+ // Internal state management
1095
+ this.isInitializedRef = false;
1096
+ this.isFetchingRef = false;
1097
+ this.hasAutoSelectedRef = false;
1098
+ this.userClearedEventRef = false;
1099
+ this.supabaseClient = supabaseClient;
1100
+ this.user = user;
1101
+ this.session = session;
1102
+ this.appName = appName;
1103
+ this.selectedOrganisation = selectedOrganisation;
1104
+ this.setSelectedEventId = setSelectedEventId;
1105
+ }
1106
+ // Helper method to get user-scoped storage key
1107
+ getStorageKey(userId) {
1108
+ if (!userId) {
1109
+ return "pace-core-selected-event-no-user";
1110
+ }
1111
+ return `pace-core-selected-event-${userId}`;
1112
+ }
1113
+ // Update dependencies
1114
+ async updateDependencies(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId) {
1115
+ const previousOrgId = this.selectedOrganisation?.id;
1116
+ const newOrgId = selectedOrganisation?.id;
1117
+ const previousUserId = this.user?.id || null;
1118
+ const newUserId = user?.id || null;
1119
+ if (previousUserId !== newUserId) {
1120
+ if (previousUserId !== null) {
1121
+ await this.clearEventSelectionForUser(previousUserId);
1122
+ }
1123
+ if (newUserId === null) {
1124
+ this.selectedEvent = null;
1125
+ this.setSelectedEventId?.(null);
1126
+ }
1127
+ }
1128
+ this.supabaseClient = supabaseClient;
1129
+ this.user = user;
1130
+ this.session = session;
1131
+ this.appName = appName;
1132
+ this.selectedOrganisation = selectedOrganisation;
1133
+ this.setSelectedEventId = setSelectedEventId;
1134
+ if (previousOrgId !== newOrgId) {
1135
+ this.resetInitialization();
1136
+ this.isInitializedRef = false;
1137
+ this.isFetchingRef = false;
1138
+ if (previousOrgId !== null && newOrgId !== null && previousOrgId !== newOrgId) {
1139
+ this.events = [];
1140
+ this.selectedEvent = null;
1141
+ } else if (previousOrgId !== null && newOrgId === null) {
1142
+ this.events = [];
1143
+ this.selectedEvent = null;
1144
+ }
1145
+ }
1146
+ this.notify();
1147
+ }
1148
+ // Event state getters
1149
+ getEvents() {
1150
+ return [...this.events];
1151
+ }
1152
+ getSelectedEvent() {
1153
+ return this.selectedEvent;
1154
+ }
1155
+ isLoading() {
1156
+ return this._isLoading;
1157
+ }
1158
+ getError() {
1159
+ return this.error;
1160
+ }
1161
+ // Event methods
1162
+ setSelectedEvent(event) {
1163
+ if (event) {
1164
+ try {
1165
+ if (this.selectedOrganisation && event.organisation_id !== this.selectedOrganisation.id) {
1166
+ logger.error("EventService", "Event organisation_id does not match selected organisation", {
1167
+ eventOrganisationId: event.organisation_id,
1168
+ selectedOrganisationId: this.selectedOrganisation.id,
1169
+ eventName: event.event_name
1170
+ });
1171
+ return;
1172
+ }
1173
+ } catch (error) {
1174
+ logger.error("EventService", "Error during event validation:", error);
1175
+ }
1176
+ this.selectedEvent = event;
1177
+ this.setSelectedEventId?.(event.event_id);
1178
+ this.persistEventSelection(event.event_id).catch((error) => {
1179
+ logger.warn("EventService", "Failed to persist event selection:", error);
1180
+ });
1181
+ this.userClearedEventRef = false;
1182
+ } else {
1183
+ this.selectedEvent = null;
1184
+ this.setSelectedEventId?.(null);
1185
+ this.clearEventSelection().catch((error) => {
1186
+ logger.warn("EventService", "Failed to clear event selection:", error);
1187
+ });
1188
+ this.hasAutoSelectedRef = false;
1189
+ this.userClearedEventRef = true;
1190
+ }
1191
+ this.notify();
1192
+ }
1193
+ async refreshEvents() {
1194
+ this.isInitializedRef = false;
1195
+ this.isFetchingRef = false;
1196
+ await this.fetchEvents();
1197
+ }
1198
+ async loadPersistedEvent(events) {
1199
+ try {
1200
+ const userId = this.user?.id || null;
1201
+ if (!userId) {
1202
+ return false;
1203
+ }
1204
+ const storageKey = this.getStorageKey(userId);
1205
+ const persistedEventId = await secureStorage.getItem(storageKey);
1206
+ if (persistedEventId && events.length > 0) {
1207
+ const persistedEvent = events.find((event) => event.event_id === persistedEventId);
1208
+ if (persistedEvent) {
1209
+ this.setSelectedEvent(persistedEvent);
1210
+ return true;
1211
+ } else {
1212
+ await secureStorage.removeItem(storageKey);
1213
+ }
1214
+ }
1215
+ } catch (error) {
1216
+ logger.warn("EventService", "Failed to load persisted event:", error);
1217
+ }
1218
+ return false;
1219
+ }
1220
+ /**
1221
+ * Restore persisted event after login screen has rendered
1222
+ * This should be called explicitly from login page component
1223
+ *
1224
+ * @returns Promise<boolean> - true if event was successfully restored, false otherwise
1225
+ */
1226
+ async restorePersistedEvent() {
1227
+ if (this.events.length === 0) {
1228
+ return false;
1229
+ }
1230
+ return await this.loadPersistedEvent(this.events);
1231
+ }
1232
+ async persistEventSelection(eventId) {
1233
+ try {
1234
+ const userId = this.user?.id || null;
1235
+ const storageKey = this.getStorageKey(userId);
1236
+ await secureStorage.setItem(storageKey, eventId, { encrypt: true });
1237
+ } catch (error) {
1238
+ logger.warn("EventService", "Failed to persist event selection:", error);
1239
+ }
1240
+ }
1241
+ async clearEventSelection() {
1242
+ try {
1243
+ const userId = this.user?.id || null;
1244
+ const storageKey = this.getStorageKey(userId);
1245
+ await secureStorage.removeItem(storageKey);
1246
+ this.selectedEvent = null;
1247
+ this.setSelectedEventId?.(null);
1248
+ } catch (error) {
1249
+ logger.warn("EventService", "Failed to clear event selection:", error);
1250
+ }
1251
+ }
1252
+ /**
1253
+ * Clear event selection for a specific user (used when user logs out or changes)
1254
+ */
1255
+ async clearEventSelectionForUser(userId) {
1256
+ try {
1257
+ if (!userId) return;
1258
+ const storageKey = this.getStorageKey(userId);
1259
+ await secureStorage.removeItem(storageKey);
1260
+ } catch (error) {
1261
+ logger.warn("EventService", "Failed to clear event selection for user:", error);
1262
+ }
1263
+ }
1264
+ autoSelectNextEvent(events) {
1265
+ const nextEvent = this.getNextEventByDate(events);
1266
+ if (nextEvent) {
1267
+ this.setSelectedEvent(nextEvent);
1268
+ }
1269
+ }
1270
+ // Lifecycle methods
1271
+ async initialize() {
1272
+ await super.initialize();
1273
+ }
1274
+ cleanup() {
1275
+ super.cleanup();
1276
+ }
1277
+ async doInitialize() {
1278
+ if (this.isInitializedRef) {
1279
+ return;
1280
+ }
1281
+ if (this.isFetchingRef) {
1282
+ return;
1283
+ }
1284
+ try {
1285
+ sessionStorage.removeItem("pace-core-selected-event");
1286
+ localStorage.removeItem("pace-core-selected-event");
1287
+ localStorage.removeItem("_sec_pace-core-selected-event");
1288
+ } catch (error) {
1289
+ logger.warn("EventService", "Failed to clean up old storage keys:", error);
1290
+ }
1291
+ if (!this.user || !this.selectedOrganisation) {
1292
+ return;
1293
+ }
1294
+ await this.fetchEvents(false);
1295
+ }
1296
+ doCleanup() {
1297
+ }
1298
+ async fetchEvents(skipLoadPersisted = false) {
1299
+ if (!this.user || !this.session || !this.supabaseClient || !this.appName || !this.selectedOrganisation) {
1300
+ this.notify();
1301
+ return;
1302
+ }
1303
+ this._isLoading = true;
1304
+ this.notify();
1305
+ if (this.isFetchingRef) {
1306
+ return;
1307
+ }
1308
+ this.isFetchingRef = true;
1309
+ let isMounted = true;
1310
+ try {
1311
+ const { data, error: rpcError } = await this.supabaseClient.rpc("data_user_events_get", {
1312
+ p_user_id: this.user.id,
1313
+ p_organisation_id: this.selectedOrganisation.id,
1314
+ p_app_name: this.appName
1315
+ });
1316
+ if (rpcError) {
1317
+ logger.error("EventService", "RPC error fetching events:", rpcError);
1318
+ throw new Error(rpcError.message || "Failed to fetch events");
1319
+ }
1320
+ if (isMounted) {
1321
+ const eventsData = data || [];
1322
+ const transformedEvents = eventsData.map((event) => ({
1323
+ id: event.event_id,
1324
+ event_id: event.event_id,
1325
+ event_name: event.event_name,
1326
+ event_code: event.event_code,
1327
+ event_date: event.event_date,
1328
+ event_venue: event.event_venue,
1329
+ event_participants: event.event_participants,
1330
+ event_colours: event.event_colours,
1331
+ event_logo: "",
1332
+ // No logo field in event table
1333
+ organisation_id: assertOrganisationId(event.organisation_id),
1334
+ is_visible: event.is_visible,
1335
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
1336
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
1337
+ }));
1338
+ this.events = transformedEvents;
1339
+ this.error = null;
1340
+ this.hasAutoSelectedRef = false;
1341
+ if (!skipLoadPersisted) {
1342
+ const persistedEventLoaded = await this.loadPersistedEvent(transformedEvents);
1343
+ if (!persistedEventLoaded && !this.userClearedEventRef) {
1344
+ const nextEvent = this.getNextEventByDate(transformedEvents);
1345
+ if (nextEvent) {
1346
+ this.hasAutoSelectedRef = true;
1347
+ this.setSelectedEvent(nextEvent);
1348
+ }
1349
+ }
1350
+ } else {
1351
+ if (!this.userClearedEventRef) {
1352
+ const nextEvent = this.getNextEventByDate(transformedEvents);
1353
+ if (nextEvent) {
1354
+ this.hasAutoSelectedRef = true;
1355
+ this.setSelectedEvent(nextEvent);
1356
+ }
1357
+ }
1358
+ }
1359
+ }
1360
+ } catch (err) {
1361
+ logger.error("EventService", "Error fetching events:", err);
1362
+ const _error = err instanceof Error ? err : new Error("Unknown error occurred");
1363
+ if (isMounted) {
1364
+ this.error = _error;
1365
+ this.events = [];
1366
+ }
1367
+ } finally {
1368
+ if (isMounted) {
1369
+ this._isLoading = false;
1370
+ }
1371
+ this.isFetchingRef = false;
1372
+ this.notify();
1373
+ }
1374
+ }
1375
+ getNextEventByDate(events) {
1376
+ const eventsToUse = events || this.events;
1377
+ if (!eventsToUse || eventsToUse.length === 0) {
1378
+ return null;
1379
+ }
1380
+ const now = /* @__PURE__ */ new Date();
1381
+ const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
1382
+ const futureEvents = eventsToUse.filter((event) => {
1383
+ if (!event.event_date) return false;
1384
+ const eventDate = new Date(event.event_date);
1385
+ const startOfEventDate = new Date(eventDate.getFullYear(), eventDate.getMonth(), eventDate.getDate()).getTime();
1386
+ return startOfEventDate >= startOfToday;
1387
+ });
1388
+ if (futureEvents.length > 0) {
1389
+ const sortedFutureEvents = futureEvents.sort((a, b) => {
1390
+ const dateA = new Date(a.event_date);
1391
+ const dateB = new Date(b.event_date);
1392
+ return dateA.getTime() - dateB.getTime();
1393
+ });
1394
+ return sortedFutureEvents[0];
1395
+ }
1396
+ const pastEvents = eventsToUse.filter((event) => {
1397
+ if (!event.event_date) return false;
1398
+ const eventDate = new Date(event.event_date);
1399
+ const startOfEventDate = new Date(eventDate.getFullYear(), eventDate.getMonth(), eventDate.getDate()).getTime();
1400
+ return startOfEventDate < startOfToday;
1401
+ });
1402
+ if (pastEvents.length > 0) {
1403
+ const sortedPastEvents = pastEvents.sort((a, b) => {
1404
+ const dateA = new Date(a.event_date);
1405
+ const dateB = new Date(b.event_date);
1406
+ return dateB.getTime() - dateA.getTime();
1407
+ });
1408
+ return sortedPastEvents[0];
1409
+ }
1410
+ return null;
1411
+ }
1412
+ };
1413
+
1414
+ // src/providers/services/EventServiceProvider.tsx
1415
+ import { jsx as jsx3 } from "react/jsx-runtime";
1416
+ var EventServiceContext = createContext3(null);
1417
+ function EventServiceProvider({
1418
+ children,
1419
+ supabaseClient,
1420
+ user,
1421
+ session,
1422
+ appName,
1423
+ selectedOrganisation,
1424
+ setSelectedEventId
1425
+ }) {
1426
+ const eventServiceRef = useRef2(null);
1427
+ if (!eventServiceRef.current) {
1428
+ eventServiceRef.current = new EventService(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);
1429
+ }
1430
+ const eventService = eventServiceRef.current;
1431
+ useEffect3(() => {
1432
+ let isMounted = true;
1433
+ const updateAndInitialize = async () => {
1434
+ await eventService.updateDependencies(supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId);
1435
+ if (!isMounted) return;
1436
+ await eventService.initialize().catch((error) => {
1437
+ if (isMounted) {
1438
+ logger.error("EventServiceProvider", "Failed to initialize event service:", error);
1439
+ }
1440
+ });
1441
+ };
1442
+ updateAndInitialize();
1443
+ return () => {
1444
+ isMounted = false;
1445
+ };
1446
+ }, [eventService, supabaseClient, user, session, appName, selectedOrganisation, setSelectedEventId]);
1447
+ useEffect3(() => {
1448
+ return () => {
1449
+ eventService.cleanup();
1450
+ };
1451
+ }, [eventService]);
1452
+ const contextValue = useMemo3(() => ({
1453
+ eventService
1454
+ }), [eventService]);
1455
+ return /* @__PURE__ */ jsx3(EventServiceContext.Provider, { value: contextValue, children });
1456
+ }
1457
+
1458
+ // src/providers/services/InactivityServiceProvider.tsx
1459
+ import { createContext as createContext4, useMemo as useMemo4, useEffect as useEffect4, useRef as useRef3 } from "react";
1460
+
1461
+ // src/services/InactivityService.ts
1462
+ var InactivityService = class extends BaseService {
1463
+ constructor(supabaseClient, user, session, idleTimeoutMs = 30 * 60 * 1e3, warnBeforeMs = 60 * 1e3, onIdleLogout) {
1464
+ super();
1465
+ this._showInactivityWarning = false;
1466
+ this._inactivityTimeRemaining = 0;
1467
+ this._isIdle = false;
1468
+ this._timeRemaining = 0;
1469
+ this._showWarning = false;
1470
+ this._isTracking = false;
1471
+ // Dependencies
1472
+ this.supabaseClient = null;
1473
+ this.user = null;
1474
+ this.session = null;
1475
+ this.idleTimeoutMs = 30 * 60 * 1e3;
1476
+ // 30 minutes
1477
+ this.warnBeforeMs = 60 * 1e3;
1478
+ // 60 seconds
1479
+ this.onIdleLogout = null;
1480
+ // Internal state management
1481
+ this.inactivityTracker = null;
1482
+ this.isInactivityEnabled = true;
1483
+ this.cleanupHandlers = null;
1484
+ this.supabaseClient = supabaseClient;
1485
+ this.user = user;
1486
+ this.session = session;
1487
+ this.idleTimeoutMs = idleTimeoutMs;
1488
+ this.warnBeforeMs = warnBeforeMs;
1489
+ this.onIdleLogout = onIdleLogout;
1490
+ this._timeRemaining = idleTimeoutMs;
1491
+ }
1492
+ // Interface implementation
1493
+ isIdle() {
1494
+ return this._isIdle;
1495
+ }
1496
+ getTimeRemaining() {
1497
+ return this._timeRemaining;
1498
+ }
1499
+ isWarningShown() {
1500
+ return this._showWarning;
1501
+ }
1502
+ isTracking() {
1503
+ return this._isTracking;
1504
+ }
1505
+ getShowInactivityWarning() {
1506
+ return this._showInactivityWarning;
1507
+ }
1508
+ getInactivityTimeRemaining() {
1509
+ return this._inactivityTimeRemaining;
1510
+ }
1511
+ // Additional getter methods that tests expect
1512
+ getIsIdle() {
1513
+ return this._isIdle;
1514
+ }
1515
+ getIsTracking() {
1516
+ return this._isTracking;
1517
+ }
1518
+ getShowWarning() {
1519
+ return this._showWarning;
1520
+ }
1521
+ // Additional methods for testing
1522
+ setShowInactivityWarning(value) {
1523
+ this._showInactivityWarning = value;
1524
+ this.notify();
1525
+ }
1526
+ setInactivityTimeRemaining(value) {
1527
+ this._inactivityTimeRemaining = value;
1528
+ this.notify();
1529
+ }
1530
+ setIsIdle(value) {
1531
+ this._isIdle = value;
1532
+ this.notify();
1533
+ }
1534
+ setTimeRemaining(value) {
1535
+ this._timeRemaining = value;
1536
+ this.notify();
1537
+ }
1538
+ setShowWarning(value) {
1539
+ this._showWarning = value;
1540
+ this.notify();
1541
+ }
1542
+ setIsTracking(value) {
1543
+ this._isTracking = value;
1544
+ this.notify();
1545
+ }
1546
+ triggerWarning(timeRemaining) {
1547
+ this._showInactivityWarning = true;
1548
+ this._inactivityTimeRemaining = Math.ceil(timeRemaining / 1e3);
1549
+ this._showWarning = true;
1550
+ this.notify();
1551
+ }
1552
+ triggerIdle() {
1553
+ this._isIdle = true;
1554
+ this.handleIdleLogout();
1555
+ this.notify();
1556
+ }
1557
+ // Update dependencies
1558
+ updateDependencies(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout) {
1559
+ this.supabaseClient = supabaseClient;
1560
+ this.user = user;
1561
+ this.session = session;
1562
+ if (idleTimeoutMs !== void 0) this.idleTimeoutMs = idleTimeoutMs;
1563
+ if (warnBeforeMs !== void 0) this.warnBeforeMs = warnBeforeMs;
1564
+ if (onIdleLogout !== void 0) this.onIdleLogout = onIdleLogout;
1565
+ this.notify();
1566
+ }
1567
+ // Inactivity methods
1568
+ resetActivity() {
1569
+ if (this.inactivityTracker) {
1570
+ this.inactivityTracker.resetActivity();
1571
+ }
1572
+ this._isIdle = false;
1573
+ this._showWarning = false;
1574
+ this._showInactivityWarning = false;
1575
+ this._inactivityTimeRemaining = 0;
1576
+ this._timeRemaining = this.idleTimeoutMs;
1577
+ this.notify();
1578
+ }
1579
+ startTracking() {
1580
+ if (this.inactivityTracker) {
1581
+ this.inactivityTracker.startTracking();
1582
+ }
1583
+ this._isTracking = true;
1584
+ this.notify();
1585
+ }
1586
+ stopTracking() {
1587
+ if (this.inactivityTracker) {
1588
+ this.inactivityTracker.stopTracking();
1589
+ }
1590
+ this._isTracking = false;
1591
+ this.notify();
1592
+ }
1593
+ async handleIdleLogout() {
1594
+ this._showInactivityWarning = false;
1595
+ this._inactivityTimeRemaining = 0;
1596
+ this.stopTracking();
1597
+ try {
1598
+ if (this.supabaseClient) {
1599
+ await this.supabaseClient.auth.signOut();
1600
+ }
1601
+ } catch (error) {
1602
+ logger.error("InactivityService", "Error during idle logout:", error);
1603
+ }
1604
+ this.onIdleLogout?.("inactivity");
1605
+ this.notify();
1606
+ }
1607
+ handleStaySignedIn() {
1608
+ this._showInactivityWarning = false;
1609
+ this._inactivityTimeRemaining = 0;
1610
+ this.resetActivity();
1611
+ this.notify();
1612
+ }
1613
+ async handleSignOutNow() {
1614
+ this._showInactivityWarning = false;
1615
+ this._inactivityTimeRemaining = 0;
1616
+ this.stopTracking();
1617
+ try {
1618
+ if (this.supabaseClient) {
1619
+ await this.supabaseClient.auth.signOut();
1620
+ }
1621
+ } catch (error) {
1622
+ logger.error("InactivityService", "Error during manual sign out:", error);
1623
+ }
1624
+ this.onIdleLogout?.("inactivity");
1625
+ this.notify();
1626
+ }
1627
+ // Lifecycle methods
1628
+ async initialize() {
1629
+ await super.initialize();
1630
+ await this.setupInactivityTracker();
1631
+ }
1632
+ cleanup() {
1633
+ if (this.cleanupHandlers) {
1634
+ this.cleanupHandlers();
1635
+ this.cleanupHandlers = null;
1636
+ }
1637
+ if (this.inactivityTracker) {
1638
+ this.inactivityTracker = null;
1639
+ }
1640
+ this._isTracking = false;
1641
+ this._isIdle = false;
1642
+ this._showWarning = false;
1643
+ this._showInactivityWarning = false;
1644
+ this._timeRemaining = 0;
1645
+ this._inactivityTimeRemaining = 0;
1646
+ super.cleanup();
1647
+ }
1648
+ async doInitialize() {
1649
+ if (typeof window !== "undefined") {
1650
+ const isProduction = import.meta.env.MODE === "production";
1651
+ if (isProduction) {
1652
+ logger.warn("InactivityService", "Inactivity feature enabled in production");
1653
+ }
1654
+ }
1655
+ }
1656
+ doCleanup() {
1657
+ }
1658
+ async setupInactivityTracker() {
1659
+ if (typeof window === "undefined") return;
1660
+ this.isInactivityEnabled = !!(this.user && this.session);
1661
+ if (!this.isInactivityEnabled) {
1662
+ return;
1663
+ }
1664
+ this.setupEventHandlers();
1665
+ }
1666
+ setupEventHandlers() {
1667
+ if (typeof window === "undefined") return;
1668
+ let idleTimer = null;
1669
+ let warningTimer = null;
1670
+ let lastActivity = Date.now();
1671
+ const resetTimers = () => {
1672
+ lastActivity = Date.now();
1673
+ if (idleTimer) {
1674
+ clearTimeout(idleTimer);
1675
+ idleTimer = null;
1676
+ }
1677
+ if (warningTimer) {
1678
+ clearTimeout(warningTimer);
1679
+ warningTimer = null;
1680
+ }
1681
+ this._showInactivityWarning = false;
1682
+ this._inactivityTimeRemaining = 0;
1683
+ this._isIdle = false;
1684
+ this._showWarning = false;
1685
+ this.notify();
1686
+ };
1687
+ const startIdleTimer = () => {
1688
+ if (idleTimer) {
1689
+ clearTimeout(idleTimer);
1690
+ }
1691
+ idleTimer = setTimeout(() => {
1692
+ this._isIdle = true;
1693
+ this._showWarning = true;
1694
+ this.notify();
1695
+ warningTimer = setTimeout(() => {
1696
+ this.handleIdleLogout();
1697
+ }, this.warnBeforeMs);
1698
+ }, this.idleTimeoutMs - this.warnBeforeMs);
1699
+ };
1700
+ const startWarningTimer = () => {
1701
+ if (warningTimer) {
1702
+ clearTimeout(warningTimer);
1703
+ }
1704
+ warningTimer = setTimeout(() => {
1705
+ this.handleIdleLogout();
1706
+ }, this.warnBeforeMs);
1707
+ };
1708
+ const activityEvents = ["mousedown", "mousemove", "keypress", "scroll", "touchstart", "click"];
1709
+ const handleActivity = () => {
1710
+ resetTimers();
1711
+ startIdleTimer();
1712
+ };
1713
+ activityEvents.forEach((event) => {
1714
+ document.addEventListener(event, handleActivity, true);
1715
+ });
1716
+ startIdleTimer();
1717
+ this.cleanupHandlers = () => {
1718
+ if (idleTimer) {
1719
+ clearTimeout(idleTimer);
1720
+ idleTimer = null;
1721
+ }
1722
+ if (warningTimer) {
1723
+ clearTimeout(warningTimer);
1724
+ warningTimer = null;
1725
+ }
1726
+ activityEvents.forEach((event) => {
1727
+ document.removeEventListener(event, handleActivity, true);
1728
+ });
1729
+ this._isTracking = false;
1730
+ this._isIdle = false;
1731
+ this._showWarning = false;
1732
+ this._timeRemaining = 0;
1733
+ this._showInactivityWarning = false;
1734
+ this._inactivityTimeRemaining = 0;
1735
+ };
1736
+ this._isTracking = true;
1737
+ this.notify();
1738
+ }
1739
+ };
1740
+
1741
+ // src/providers/services/InactivityServiceProvider.tsx
1742
+ import { jsx as jsx4 } from "react/jsx-runtime";
1743
+ var InactivityServiceContext = createContext4(null);
1744
+ function InactivityServiceProvider({
1745
+ children,
1746
+ supabaseClient,
1747
+ user,
1748
+ session,
1749
+ idleTimeoutMs = 30 * 60 * 1e3,
1750
+ warnBeforeMs = 60 * 1e3,
1751
+ onIdleLogout
1752
+ }) {
1753
+ const inactivityServiceRef = useRef3(null);
1754
+ if (!inactivityServiceRef.current) {
1755
+ inactivityServiceRef.current = new InactivityService(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout);
1756
+ }
1757
+ const inactivityService = inactivityServiceRef.current;
1758
+ useEffect4(() => {
1759
+ inactivityService.updateDependencies(supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout);
1760
+ let isMounted = true;
1761
+ inactivityService.initialize().catch((error) => {
1762
+ if (isMounted) {
1763
+ logger.error("InactivityServiceProvider", "Failed to initialize inactivity service:", error);
1764
+ }
1765
+ });
1766
+ return () => {
1767
+ isMounted = false;
1768
+ };
1769
+ }, [inactivityService, supabaseClient, user, session, idleTimeoutMs, warnBeforeMs, onIdleLogout]);
1770
+ useEffect4(() => {
1771
+ return () => {
1772
+ inactivityService.cleanup();
1773
+ };
1774
+ }, [inactivityService]);
1775
+ const contextValue = useMemo4(() => ({
1776
+ inactivityService
1777
+ }), [inactivityService]);
1778
+ return /* @__PURE__ */ jsx4(InactivityServiceContext.Provider, { value: contextValue, children });
1779
+ }
1780
+
1781
+ // src/hooks/services/useAuthService.ts
1782
+ import { useContext, useReducer, useEffect as useEffect5 } from "react";
1783
+ function useAuthService() {
1784
+ const context = useContext(AuthServiceContext);
1785
+ if (!context) {
1786
+ throw new Error("useAuthService must be used within AuthServiceProvider");
1787
+ }
1788
+ const [, forceUpdate] = useReducer((x) => x + 1, 0);
1789
+ useEffect5(() => {
1790
+ return context.authService.subscribe(() => forceUpdate());
1791
+ }, [context.authService]);
1792
+ return context.authService;
1793
+ }
1794
+
1795
+ // src/hooks/services/useOrganisationService.ts
1796
+ import { useContext as useContext2, useReducer as useReducer2, useEffect as useEffect6 } from "react";
1797
+ function useOrganisationService() {
1798
+ const context = useContext2(OrganisationServiceContext);
1799
+ if (!context) {
1800
+ throw new Error("useOrganisationService must be used within OrganisationServiceProvider");
1801
+ }
1802
+ const [, forceUpdate] = useReducer2((x) => x + 1, 0);
1803
+ useEffect6(() => {
1804
+ return context.organisationService.subscribe(() => forceUpdate());
1805
+ }, [context.organisationService]);
1806
+ return context.organisationService;
1807
+ }
1808
+
1809
+ // src/hooks/services/useEventService.ts
1810
+ import { useContext as useContext3, useReducer as useReducer3, useEffect as useEffect7 } from "react";
1811
+ function useEventService() {
1812
+ const context = useContext3(EventServiceContext);
1813
+ if (!context) {
1814
+ throw new Error("useEventService must be used within EventServiceProvider");
1815
+ }
1816
+ const [, forceUpdate] = useReducer3((x) => x + 1, 0);
1817
+ useEffect7(() => {
1818
+ return context.eventService.subscribe(() => forceUpdate());
1819
+ }, [context.eventService]);
1820
+ return context.eventService;
1821
+ }
1822
+
1823
+ // src/hooks/services/useInactivityService.ts
1824
+ import { useContext as useContext4, useReducer as useReducer4, useEffect as useEffect8 } from "react";
1825
+ function useInactivityService() {
1826
+ const context = useContext4(InactivityServiceContext);
1827
+ if (!context) {
1828
+ throw new Error("useInactivityService must be used within InactivityServiceProvider");
1829
+ }
1830
+ const [, forceUpdate] = useReducer4((x) => x + 1, 0);
1831
+ useEffect8(() => {
1832
+ return context.inactivityService.subscribe(() => forceUpdate());
1833
+ }, [context.inactivityService]);
1834
+ return context.inactivityService;
1835
+ }
1836
+
1837
+ // src/hooks/useSessionRestoration.ts
1838
+ import { useContext as useContext5, useMemo as useMemo5, useEffect as useEffect9, useState as useState2 } from "react";
1839
+ var log = createLogger("useSessionRestoration");
1840
+ var SESSION_RESTORATION_TIMEOUT_MS = 5e3;
1841
+ function useSessionRestoration() {
1842
+ const context = useContext5(AuthServiceContext);
1843
+ if (!context) {
1844
+ throw new Error("useSessionRestoration must be used within AuthServiceProvider");
1845
+ }
1846
+ const { sessionRestoration } = context;
1847
+ const [hasTimedOut, setHasTimedOut] = useState2(false);
1848
+ useEffect9(() => {
1849
+ let timeoutHandle = null;
1850
+ if (sessionRestoration.isRestoring && !sessionRestoration.restorationComplete && !sessionRestoration.restorationError) {
1851
+ setHasTimedOut(false);
1852
+ timeoutHandle = setTimeout(() => {
1853
+ log.warn("Session restoration timed out");
1854
+ setHasTimedOut(true);
1855
+ }, SESSION_RESTORATION_TIMEOUT_MS);
1856
+ } else {
1857
+ setHasTimedOut(false);
1858
+ }
1859
+ return () => {
1860
+ if (timeoutHandle) {
1861
+ clearTimeout(timeoutHandle);
1862
+ }
1863
+ };
1864
+ }, [
1865
+ sessionRestoration.isRestoring,
1866
+ sessionRestoration.restorationComplete,
1867
+ sessionRestoration.restorationError
1868
+ ]);
1869
+ return useMemo5(() => ({
1870
+ ...sessionRestoration,
1871
+ hasTimedOut,
1872
+ timeoutMs: SESSION_RESTORATION_TIMEOUT_MS
1873
+ }), [sessionRestoration, hasTimedOut]);
1874
+ }
1875
+
1876
+ // src/providers/services/UnifiedAuthProvider.tsx
1877
+ import { jsx as jsx5 } from "react/jsx-runtime";
1878
+ var UnifiedAuthContext = createContext5(void 0);
1879
+ var useUnifiedAuth = () => {
1880
+ const context = useContext6(UnifiedAuthContext);
1881
+ if (!context) {
1882
+ logger.error("useUnifiedAuth", "useUnifiedAuth must be used within a UnifiedAuthProvider");
1883
+ throw new Error("useUnifiedAuth must be used within a UnifiedAuthProvider");
1884
+ }
1885
+ return context;
1886
+ };
1887
+ function UnifiedAuthContextProvider({
1888
+ children,
1889
+ appName,
1890
+ appConfig = { requires_event: true },
1891
+ // Default to requiring events
1892
+ ...props
1893
+ }) {
1894
+ const authService = useAuthService();
1895
+ const organisationService = useOrganisationService();
1896
+ const inactivityService = useInactivityService();
1897
+ const sessionRestorationState = useSessionRestoration();
1898
+ const {
1899
+ hasTimedOut: sessionRestorationTimedOut,
1900
+ timeoutMs: sessionRestorationTimeoutMs,
1901
+ isRestoring,
1902
+ restorationComplete,
1903
+ restorationError
1904
+ } = sessionRestorationState;
1905
+ const sessionRestoration = useMemo6(() => ({
1906
+ isRestoring,
1907
+ restorationComplete,
1908
+ restorationError
1909
+ }), [isRestoring, restorationComplete, restorationError]);
1910
+ let eventService;
1911
+ try {
1912
+ eventService = useEventService();
1913
+ } catch (error) {
1914
+ eventService = {
1915
+ getEvents: () => [],
1916
+ getSelectedEvent: () => null,
1917
+ isLoading: () => false,
1918
+ getError: () => null,
1919
+ setSelectedEvent: () => {
1920
+ },
1921
+ refreshEvents: async () => {
1922
+ }
1923
+ };
1924
+ }
1925
+ const currentUser = authService.getUser();
1926
+ const currentSession = authService.getSession();
1927
+ const isAuth = !!(currentUser && currentSession);
1928
+ const supabase = authService.getSupabaseClient();
1929
+ const [appId, setAppId] = useState3(void 0);
1930
+ const isResolvingAppIdRef = useRef4(false);
1931
+ useEffect10(() => {
1932
+ if (isAuth && currentUser?.id && supabase && appName && !appId && !isResolvingAppIdRef.current) {
1933
+ isResolvingAppIdRef.current = true;
1934
+ const userId = currentUser.id;
1935
+ const appNameValue = appName;
1936
+ import("./api-ROMBCNKU.js").then(async ({ resolveAppContext, setupRBAC }) => {
1937
+ try {
1938
+ setupRBAC(supabase);
1939
+ const result = await resolveAppContext({
1940
+ userId,
1941
+ appName: appNameValue
1942
+ });
1943
+ if (result?.appId) {
1944
+ setAppId(result.appId);
1945
+ logger.debug("UnifiedAuthProvider", "appId resolved on login", {
1946
+ appId: result.appId,
1947
+ appName: appNameValue
1948
+ });
1949
+ }
1950
+ } catch (error) {
1951
+ logger.error("UnifiedAuthProvider", "Failed to resolve appId on login", {
1952
+ error: error instanceof Error ? error.message : String(error),
1953
+ appName: appNameValue,
1954
+ userId
1955
+ });
1956
+ } finally {
1957
+ isResolvingAppIdRef.current = false;
1958
+ }
1959
+ }).catch((importError) => {
1960
+ logger.error("UnifiedAuthProvider", "Failed to import RBAC API", importError);
1961
+ isResolvingAppIdRef.current = false;
1962
+ });
1963
+ }
1964
+ if (!isAuth) {
1965
+ setAppId(void 0);
1966
+ }
1967
+ }, [isAuth, currentUser?.id, supabase, appName, appId]);
1968
+ const authLoading = authService.isLoading();
1969
+ const orgLoading = organisationService.isLoading();
1970
+ const eventLoading = eventService.isLoading();
1971
+ const restorationLoading = sessionRestoration.isRestoring && !sessionRestorationTimedOut && !sessionRestoration.restorationError;
1972
+ const totalLoading = restorationLoading || authLoading || orgLoading || eventLoading;
1973
+ const authError = authService.getError();
1974
+ const selectedOrganisation = organisationService.getSelectedOrganisation();
1975
+ const organisations = organisationService.getOrganisations();
1976
+ const userMemberships = organisationService.getUserMemberships();
1977
+ const organisationError = organisationService.getError();
1978
+ const hasValidOrganisationContext = organisationService.hasValidOrganisationContext();
1979
+ const isContextReady = organisationService.isContextReady();
1980
+ const events = eventService.getEvents();
1981
+ const selectedEvent = eventService.getSelectedEvent();
1982
+ const eventError = eventService.getError();
1983
+ const showInactivityWarning = inactivityService.getShowInactivityWarning();
1984
+ const inactivityTimeRemaining = inactivityService.getInactivityTimeRemaining();
1985
+ const isIdle = inactivityService.isIdle();
1986
+ const timeRemaining = inactivityService.getTimeRemaining();
1987
+ const showWarning = inactivityService.isWarningShown();
1988
+ const isTracking = inactivityService.isTracking();
1989
+ const hasErrors = !!(authError || organisationError || eventError || sessionRestoration.restorationError);
1990
+ const signIn = useCallback((email, password) => authService.signIn(email, password), [authService]);
1991
+ const signUp = useCallback((email, password) => authService.signUp(email, password), [authService]);
1992
+ const signOut = useCallback(() => authService.signOut(), [authService]);
1993
+ const resetPassword = useCallback((email) => authService.resetPassword(email), [authService]);
1994
+ const updatePassword = useCallback((password) => authService.updatePassword(password), [authService]);
1995
+ const refreshSession = useCallback(() => authService.refreshSession(), [authService]);
1996
+ const switchOrganisation = useCallback((orgId) => organisationService.switchOrganisation(orgId), [organisationService]);
1997
+ const getUserRole = useCallback((orgId) => organisationService.getUserRole(orgId), [organisationService]);
1998
+ const validateOrganisationAccess = useCallback((orgId) => organisationService.validateOrganisationAccess(orgId), [organisationService]);
1999
+ const refreshOrganisations = useCallback(() => organisationService.refreshOrganisations(), [organisationService]);
2000
+ const ensureOrganisationContext = useCallback(() => organisationService.ensureOrganisationContext(), [organisationService]);
2001
+ const isOrganisationSecure = useCallback(() => organisationService.isOrganisationSecure(), [organisationService]);
2002
+ const getPrimaryOrganisation = useCallback(() => organisationService.getPrimaryOrganisation(), [organisationService]);
2003
+ const setSelectedEvent = useCallback((event) => eventService.setSelectedEvent(event), [eventService]);
2004
+ const refreshEvents = useCallback(() => eventService.refreshEvents(), [eventService]);
2005
+ const resetActivity = useCallback(() => inactivityService.resetActivity(), [inactivityService]);
2006
+ const startTracking = useCallback(() => inactivityService.startTracking(), [inactivityService]);
2007
+ const stopTracking = useCallback(() => inactivityService.stopTracking(), [inactivityService]);
2008
+ const handleIdleLogout = useCallback(() => inactivityService.handleIdleLogout(), [inactivityService]);
2009
+ const handleStaySignedIn = useCallback(() => inactivityService.handleStaySignedIn(), [inactivityService]);
2010
+ const handleSignOutNow = useCallback(() => inactivityService.handleSignOutNow(), [inactivityService]);
2011
+ const prevStateRef = useRef4(null);
2012
+ const isDev = import.meta.env.DEV || import.meta.env.MODE === "development";
2013
+ if (isDev) {
2014
+ const currentState = {
2015
+ isAuthenticated: isAuth,
2016
+ userEmail: currentUser?.email,
2017
+ totalLoading
2018
+ };
2019
+ const prevState = prevStateRef.current;
2020
+ if (!prevState || prevState.isAuthenticated !== currentState.isAuthenticated || prevState.userEmail !== currentState.userEmail || prevState.totalLoading !== currentState.totalLoading) {
2021
+ prevStateRef.current = currentState;
2022
+ }
2023
+ }
2024
+ const contextValue = useMemo6(() => {
2025
+ return {
2026
+ // Auth state
2027
+ user: currentUser,
2028
+ session: currentSession,
2029
+ isAuthenticated: isAuth,
2030
+ authLoading,
2031
+ authError,
2032
+ supabase,
2033
+ // Auth methods
2034
+ signIn,
2035
+ signUp,
2036
+ signOut,
2037
+ resetPassword,
2038
+ updatePassword,
2039
+ refreshSession,
2040
+ // Organisation state
2041
+ selectedOrganisation,
2042
+ organisations,
2043
+ userMemberships,
2044
+ organisationLoading: orgLoading,
2045
+ organisationError,
2046
+ hasValidOrganisationContext,
2047
+ isContextReady,
2048
+ // Organisation methods
2049
+ switchOrganisation,
2050
+ getUserRole,
2051
+ validateOrganisationAccess,
2052
+ refreshOrganisations,
2053
+ ensureOrganisationContext,
2054
+ isOrganisationSecure,
2055
+ getPrimaryOrganisation,
2056
+ // Event state
2057
+ events,
2058
+ selectedEvent,
2059
+ eventLoading,
2060
+ eventError,
2061
+ // Event methods
2062
+ setSelectedEvent,
2063
+ refreshEvents,
2064
+ // Inactivity state
2065
+ showInactivityWarning,
2066
+ inactivityTimeRemaining,
2067
+ isIdle,
2068
+ timeRemaining,
2069
+ showWarning,
2070
+ isTracking,
2071
+ // Inactivity methods
2072
+ resetActivity,
2073
+ startTracking,
2074
+ stopTracking,
2075
+ handleIdleLogout,
2076
+ handleStaySignedIn,
2077
+ handleSignOutNow,
2078
+ // Additional unified properties
2079
+ appName,
2080
+ appId,
2081
+ // Resolved immediately on login
2082
+ appConfig,
2083
+ isLoading: totalLoading,
2084
+ hasErrors,
2085
+ sessionRestoration,
2086
+ sessionRestorationTimedOut,
2087
+ sessionRestorationTimeoutMs
2088
+ };
2089
+ }, [
2090
+ // All primitive values extracted from services
2091
+ // Note: Arrays/objects from services are stable references (same reference unless data changes)
2092
+ currentUser,
2093
+ currentSession,
2094
+ isAuth,
2095
+ authLoading,
2096
+ authError,
2097
+ supabase,
2098
+ selectedOrganisation,
2099
+ organisations,
2100
+ userMemberships,
2101
+ orgLoading,
2102
+ organisationError,
2103
+ hasValidOrganisationContext,
2104
+ isContextReady,
2105
+ events,
2106
+ selectedEvent,
2107
+ eventLoading,
2108
+ eventError,
2109
+ showInactivityWarning,
2110
+ inactivityTimeRemaining,
2111
+ isIdle,
2112
+ timeRemaining,
2113
+ showWarning,
2114
+ isTracking,
2115
+ totalLoading,
2116
+ hasErrors,
2117
+ appName,
2118
+ appId,
2119
+ appConfig,
2120
+ sessionRestoration,
2121
+ sessionRestorationTimedOut,
2122
+ sessionRestorationTimeoutMs,
2123
+ // Stable function references from useCallback (services are stable, so callbacks are too)
2124
+ signIn,
2125
+ signUp,
2126
+ signOut,
2127
+ resetPassword,
2128
+ updatePassword,
2129
+ refreshSession,
2130
+ switchOrganisation,
2131
+ getUserRole,
2132
+ validateOrganisationAccess,
2133
+ refreshOrganisations,
2134
+ ensureOrganisationContext,
2135
+ isOrganisationSecure,
2136
+ getPrimaryOrganisation,
2137
+ setSelectedEvent,
2138
+ refreshEvents,
2139
+ resetActivity,
2140
+ startTracking,
2141
+ stopTracking,
2142
+ handleIdleLogout,
2143
+ handleStaySignedIn,
2144
+ handleSignOutNow
2145
+ ]);
2146
+ return /* @__PURE__ */ jsx5(UnifiedAuthContext.Provider, { value: contextValue, children });
2147
+ }
2148
+ function EventServiceProviderWrapper({
2149
+ children,
2150
+ supabaseClient,
2151
+ user,
2152
+ session,
2153
+ appName
2154
+ }) {
2155
+ const organisationService = useOrganisationService();
2156
+ const selectedOrganisation = organisationService.getSelectedOrganisation();
2157
+ return /* @__PURE__ */ jsx5(
2158
+ EventServiceProvider,
2159
+ {
2160
+ supabaseClient,
2161
+ user,
2162
+ session,
2163
+ appName,
2164
+ selectedOrganisation,
2165
+ setSelectedEventId: () => {
2166
+ },
2167
+ children
2168
+ }
2169
+ );
2170
+ }
2171
+ function ServiceAwareProviders({
2172
+ children,
2173
+ supabaseClient,
2174
+ appName,
2175
+ appConfig,
2176
+ persistState,
2177
+ enablePersistence,
2178
+ requireOrganisationContext,
2179
+ idleTimeoutMs,
2180
+ warnBeforeMs,
2181
+ onIdleLogout,
2182
+ renderInactivityWarning,
2183
+ dangerouslyDisableInactivity
2184
+ }) {
2185
+ const authService = useAuthService();
2186
+ return /* @__PURE__ */ jsx5(
2187
+ OrganisationServiceProvider,
2188
+ {
2189
+ supabaseClient,
2190
+ user: authService.getUser(),
2191
+ session: authService.getSession(),
2192
+ children: /* @__PURE__ */ jsx5(
2193
+ EventServiceProviderWrapper,
2194
+ {
2195
+ supabaseClient,
2196
+ user: authService.getUser(),
2197
+ session: authService.getSession(),
2198
+ appName,
2199
+ children: /* @__PURE__ */ jsx5(
2200
+ InactivityServiceProvider,
2201
+ {
2202
+ supabaseClient,
2203
+ user: authService.getUser(),
2204
+ session: authService.getSession(),
2205
+ idleTimeoutMs,
2206
+ warnBeforeMs,
2207
+ onIdleLogout,
2208
+ children: /* @__PURE__ */ jsx5(
2209
+ UnifiedAuthContextProvider,
2210
+ {
2211
+ appName,
2212
+ appConfig,
2213
+ supabaseClient,
2214
+ persistState,
2215
+ enablePersistence,
2216
+ requireOrganisationContext,
2217
+ idleTimeoutMs,
2218
+ warnBeforeMs,
2219
+ onIdleLogout,
2220
+ renderInactivityWarning,
2221
+ dangerouslyDisableInactivity,
2222
+ children
2223
+ }
2224
+ )
2225
+ }
2226
+ )
2227
+ }
2228
+ )
2229
+ }
2230
+ );
2231
+ }
2232
+ function UnifiedAuthProvider({
2233
+ children,
2234
+ supabaseClient,
2235
+ appName,
2236
+ appConfig = { requires_event: true },
2237
+ // Default to requiring events
2238
+ persistState = true,
2239
+ enablePersistence,
2240
+ requireOrganisationContext = true,
2241
+ idleTimeoutMs = 30 * 60 * 1e3,
2242
+ // 30 minutes
2243
+ warnBeforeMs = 60 * 1e3,
2244
+ // 60 seconds
2245
+ onIdleLogout,
2246
+ renderInactivityWarning,
2247
+ dangerouslyDisableInactivity = false
2248
+ }) {
2249
+ const clientRef = useRef4(supabaseClient);
2250
+ useEffect10(() => {
2251
+ if (clientRef.current !== supabaseClient) {
2252
+ logger.warn("UnifiedAuthProvider", "Supabase client reference changed - this may indicate multiple client instances are being created", {
2253
+ previousClient: clientRef.current,
2254
+ newClient: supabaseClient,
2255
+ note: 'Ensure you create the Supabase client once and reuse it. Creating multiple clients can cause performance issues and the "Multiple GoTrueClient instances" warning.'
2256
+ });
2257
+ clientRef.current = supabaseClient;
2258
+ }
2259
+ }, [supabaseClient]);
2260
+ return /* @__PURE__ */ jsx5(AuthServiceProvider, { supabaseClient, appName, children: /* @__PURE__ */ jsx5(
2261
+ ServiceAwareProviders,
2262
+ {
2263
+ supabaseClient,
2264
+ appName,
2265
+ appConfig,
2266
+ persistState,
2267
+ enablePersistence,
2268
+ requireOrganisationContext,
2269
+ idleTimeoutMs,
2270
+ warnBeforeMs,
2271
+ onIdleLogout,
2272
+ renderInactivityWarning,
2273
+ dangerouslyDisableInactivity,
2274
+ children
2275
+ }
2276
+ ) });
2277
+ }
2278
+
2279
+ export {
2280
+ AuthServiceContext,
2281
+ AuthServiceProvider,
2282
+ OrganisationServiceContext,
2283
+ OrganisationServiceProvider,
2284
+ EventServiceContext,
2285
+ EventServiceProvider,
2286
+ InactivityServiceContext,
2287
+ InactivityServiceProvider,
2288
+ useAuthService,
2289
+ useOrganisationService,
2290
+ useEventService,
2291
+ useInactivityService,
2292
+ useSessionRestoration,
2293
+ useUnifiedAuth,
2294
+ UnifiedAuthProvider
2295
+ };
2296
+ //# sourceMappingURL=chunk-FUEYYMX5.js.map