@jmruthers/pace-core 0.5.181 → 0.5.183

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 (756) 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/usePublicEventLogo.test.ts +147 -0
  470. package/src/hooks/public/usePublicRouteParams.ts +1 -1
  471. package/src/hooks/services/useAuth.ts +2 -4
  472. package/src/hooks/services/useCurrentEvent.ts +1 -1
  473. package/src/hooks/useAppConfig.ts +1 -1
  474. package/src/hooks/useDataTablePerformance.ts +2 -2
  475. package/src/hooks/useEventTheme.ts +1 -1
  476. package/src/hooks/useEvents.ts +51 -10
  477. package/src/hooks/useOrganisationPermissions.test.ts +3 -3
  478. package/src/hooks/useOrganisationPermissions.ts +1 -1
  479. package/src/hooks/useOrganisationSecurity.ts +2 -2
  480. package/src/hooks/usePermissionCache.test.ts +9 -9
  481. package/src/hooks/usePermissionCache.ts +2 -2
  482. package/src/index.ts +19 -12
  483. package/src/providers/OrganisationProvider.tsx +73 -9
  484. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +113 -13
  485. package/src/providers/__tests__/AuthProvider.test.tsx +2 -1
  486. package/src/providers/__tests__/EventProvider.test.tsx +24 -15
  487. package/src/providers/__tests__/OrganisationProvider.test.tsx +87 -36
  488. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +80 -24
  489. package/src/providers/index.ts +0 -3
  490. package/src/providers/services/AuthServiceProvider.tsx +2 -17
  491. package/src/providers/services/EventServiceProvider.tsx +11 -16
  492. package/src/providers/services/InactivityServiceProvider.tsx +9 -12
  493. package/src/providers/services/OrganisationServiceProvider.tsx +9 -12
  494. package/src/providers/services/UnifiedAuthProvider.tsx +85 -18
  495. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +11 -4
  496. package/src/rbac/__tests__/scenarios.user-role.test.tsx +105 -21
  497. package/src/rbac/adapters.tsx +1 -1
  498. package/src/rbac/api.ts +20 -4
  499. package/src/rbac/audit-enhanced.ts +47 -2
  500. package/src/rbac/audit.ts +47 -2
  501. package/src/rbac/components/NavigationGuard.tsx +1 -1
  502. package/src/rbac/components/NavigationProvider.test.tsx +7 -6
  503. package/src/rbac/components/NavigationProvider.tsx +1 -1
  504. package/src/rbac/components/PagePermissionGuard.tsx +1 -1
  505. package/src/rbac/components/PagePermissionProvider.test.tsx +7 -6
  506. package/src/rbac/components/PagePermissionProvider.tsx +1 -1
  507. package/src/rbac/components/PermissionEnforcer.tsx +1 -1
  508. package/src/rbac/components/RoleBasedRouter.tsx +1 -1
  509. package/src/rbac/components/SecureDataProvider.test.tsx +7 -6
  510. package/src/rbac/components/SecureDataProvider.tsx +1 -1
  511. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +6 -6
  512. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +11 -10
  513. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +10 -11
  514. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +19 -15
  515. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +13 -12
  516. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +19 -15
  517. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +18 -18
  518. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +11 -10
  519. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +8 -7
  520. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +10 -11
  521. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +48 -19
  522. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +476 -0
  523. package/src/rbac/hooks/index.ts +3 -0
  524. package/src/rbac/hooks/usePermissions.ts +31 -85
  525. package/src/rbac/hooks/useRBAC.test.ts +13 -1
  526. package/src/rbac/hooks/useRBAC.ts +13 -67
  527. package/src/rbac/hooks/useResolvedScope.ts +11 -0
  528. package/src/rbac/hooks/useSecureSupabase.ts +308 -0
  529. package/src/rbac/index.ts +3 -0
  530. package/src/rbac/secureClient.ts +53 -6
  531. package/src/rbac/security.ts +37 -1
  532. package/src/{types/rbac-functions.ts → rbac/types/functions.ts} +30 -30
  533. package/src/rbac/types.ts +3 -2
  534. package/src/services/AuthService.ts +33 -25
  535. package/src/services/EventService.ts +56 -44
  536. package/src/services/InactivityService.ts +33 -53
  537. package/src/services/OrganisationService.ts +36 -40
  538. package/src/services/__tests__/AuthService.restoreSession.test.ts +6 -2
  539. package/src/services/__tests__/EventService.test.ts +67 -33
  540. package/src/services/interfaces/IEventService.ts +1 -1
  541. package/src/styles/core.css +2 -2
  542. package/src/styles/index.test.ts +21 -0
  543. package/src/styles/index.ts +1 -5
  544. package/src/types/__tests__/guards.test.ts +1 -1
  545. package/src/types/__tests__/organisation.roles.test.ts +55 -0
  546. package/src/types/__tests__/type-validation.test.ts +0 -1
  547. package/src/types/auth.ts +42 -2
  548. package/src/types/core.ts +251 -0
  549. package/src/types/database.ts +11 -496
  550. package/src/types/event.ts +102 -0
  551. package/src/types/file-reference.ts +6 -4
  552. package/src/types/guards.ts +2 -1
  553. package/src/types/index.ts +48 -14
  554. package/src/types/lodash.debounce.d.ts +15 -0
  555. package/src/types/organisation.ts +14 -10
  556. package/src/types/supabase.ts +15 -17
  557. package/src/utils/__tests__/secureErrors.unit.test.ts +1 -1
  558. package/src/utils/__tests__/validationUtils.unit.test.ts +0 -29
  559. package/src/utils/app/appNameResolver.ts +1 -1
  560. package/src/utils/audit/audit.test.ts +65 -0
  561. package/src/utils/device/deviceFingerprint.test.ts +171 -0
  562. package/src/utils/dynamic/dynamicUtils.ts +3 -2
  563. package/src/utils/file-reference/index.ts +25 -6
  564. package/src/utils/security/secureErrors.ts +1 -1
  565. package/src/utils/validation/__tests__/validationUtils.test.ts +72 -0
  566. package/src/utils/validation/index.ts +6 -12
  567. package/src/utils/validation/validationUtils.ts +0 -13
  568. package/dist/UnifiedAuthProvider-B37ATQHE.js +0 -16
  569. package/dist/auth-DReDSLq9.d.ts +0 -16
  570. package/dist/chunk-3JI76CYK.js +0 -2444
  571. package/dist/chunk-3JI76CYK.js.map +0 -1
  572. package/dist/chunk-56XJ3TU6.js +0 -11
  573. package/dist/chunk-56XJ3TU6.js.map +0 -1
  574. package/dist/chunk-5MT24GKJ.js.map +0 -1
  575. package/dist/chunk-7QCC6MCP.js +0 -288
  576. package/dist/chunk-BESYRHQM.js.map +0 -1
  577. package/dist/chunk-BJPBT3CU.js +0 -21
  578. package/dist/chunk-BJPBT3CU.js.map +0 -1
  579. package/dist/chunk-BVYWGZVV.js.map +0 -1
  580. package/dist/chunk-CX5M4ZAG.js.map +0 -1
  581. package/dist/chunk-D7LCGMVS.js.map +0 -1
  582. package/dist/chunk-EGI6MUL6.js +0 -27
  583. package/dist/chunk-EGI6MUL6.js.map +0 -1
  584. package/dist/chunk-ERISIBYU.js.map +0 -1
  585. package/dist/chunk-HRO5HWN2.js.map +0 -1
  586. package/dist/chunk-HZLDFOE4.js.map +0 -1
  587. package/dist/chunk-JISYG63F.js +0 -70
  588. package/dist/chunk-JISYG63F.js.map +0 -1
  589. package/dist/chunk-LIMSTKYD.js +0 -61
  590. package/dist/chunk-LIMSTKYD.js.map +0 -1
  591. package/dist/chunk-OWAG3GSU.js.map +0 -1
  592. package/dist/chunk-PPMP5J6T.js.map +0 -1
  593. package/dist/chunk-Q5QRDWKI.js.map +0 -1
  594. package/dist/chunk-S5OFRT4M.js.map +0 -1
  595. package/dist/chunk-SBVILCCA.js.map +0 -1
  596. package/dist/chunk-TUMEWN34.js +0 -15
  597. package/dist/chunk-TUMEWN34.js.map +0 -1
  598. package/dist/chunk-XDNLUEXI.js +0 -138
  599. package/dist/chunk-XJ2HZOBU.js.map +0 -1
  600. package/dist/chunk-ZYTYSTO5.js.map +0 -1
  601. package/dist/chunk-ZZ2SS7NI.js +0 -237
  602. package/dist/chunk-ZZ2SS7NI.js.map +0 -1
  603. package/dist/database-C6jy7EOu.d.ts +0 -500
  604. package/dist/organisation-D6qRDtbF.d.ts +0 -93
  605. package/dist/schema-DTDZQe2u.d.ts +0 -28
  606. package/dist/unified-DQ4VcT7H.d.ts +0 -198
  607. package/dist/useInactivityTracker-TO6ZOF35.js +0 -11
  608. package/dist/validation.d.ts +0 -47
  609. package/dist/validation.js +0 -24
  610. package/dist/validation.js.map +0 -1
  611. package/docs/DOCUMENTATION_AUDIT.md +0 -172
  612. package/docs/DOCUMENTATION_STANDARD.md +0 -137
  613. package/docs/api/classes/PublicErrorBoundary.md +0 -132
  614. package/docs/api/interfaces/EventLogoProps.md +0 -152
  615. package/docs/api/interfaces/PublicErrorBoundaryProps.md +0 -94
  616. package/docs/api/interfaces/PublicErrorBoundaryState.md +0 -68
  617. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +0 -86
  618. package/docs/architecture/rpc-function-standards.md +0 -1106
  619. package/docs/getting-started/consuming-app-vite-config.md +0 -239
  620. package/docs/implementation-guides/event-theming-summary.md +0 -226
  621. package/docs/implementation-guides/public-pages-advanced.md +0 -1038
  622. package/docs/migration/v0.4.15-tailwind-scanning.md +0 -278
  623. package/docs/migration/v0.4.16-css-first-approach.md +0 -312
  624. package/docs/migration/v0.4.17-source-path-fix.md +0 -235
  625. package/docs/rbac/RBAC_EVENT_CONTEXT_LOADING.md +0 -222
  626. package/docs/rbac/RBAC_LOGIN_SAFETY_FIX.md +0 -95
  627. package/docs/rbac/RBAC_V0.5.147_FIX.md +0 -117
  628. package/docs/rbac/README-rbac-rls-integration.md +0 -374
  629. package/docs/styles/usage.md +0 -227
  630. package/docs/testing/visual-testing.md +0 -120
  631. package/docs/troubleshooting/DEBUG_NETWORK_ERROR.md +0 -152
  632. package/docs/troubleshooting/FIX_SUPABASE_CORS.md +0 -184
  633. package/docs/troubleshooting/cake-page-permission-guard-issue-summary.md +0 -193
  634. package/docs/troubleshooting/database-view-compatibility.md +0 -125
  635. package/docs/troubleshooting/react-hooks-issue-analysis.md +0 -172
  636. package/docs/troubleshooting/tailwind-content-scanning.md +0 -219
  637. package/examples/RBAC/EventBasedApp.tsx +0 -239
  638. package/examples/RBAC/PermissionExample.tsx +0 -151
  639. package/examples/STRUCTURE.md +0 -125
  640. package/examples/components 2/DataTable/HierarchicalExample.tsx +0 -475
  641. package/examples/components 2/Dialog/BasicHtmlTest.tsx +0 -55
  642. package/examples/components 2/Dialog/DebugHtmlExample.tsx +0 -68
  643. package/examples/components 2/Dialog/HtmlDialogExample.tsx +0 -202
  644. package/examples/components 2/Dialog/SimpleHtmlTest.tsx +0 -61
  645. package/examples/components 2/Dialog/SmartDialogExample.tsx +0 -322
  646. package/examples/components 2/index.ts +0 -11
  647. package/examples/features/index.ts +0 -12
  648. package/examples/features/rbac/CompleteRBACExample.tsx +0 -324
  649. package/examples/features/rbac/index.ts +0 -13
  650. package/examples/public-pages/CorrectPublicPageImplementation.tsx +0 -301
  651. package/examples/public-pages/PublicEventPage.tsx +0 -274
  652. package/examples/public-pages/PublicPageApp.tsx +0 -308
  653. package/examples/public-pages/PublicPageUsageExample.tsx +0 -216
  654. package/examples/public-pages/index.ts +0 -14
  655. package/src/__tests__/TEST_STANDARD.md +0 -1008
  656. package/src/components/Checkbox/__mocks__/Checkbox.tsx +0 -2
  657. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +0 -421
  658. package/src/components/DataTable/examples/InitialPageSizeExample.tsx +0 -177
  659. package/src/components/DataTable/examples/PerformanceExample.tsx +0 -506
  660. package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +0 -316
  661. package/src/components/DataTable/examples/__tests__/HierarchicalExample.test.tsx +0 -45
  662. package/src/components/DataTable/examples/__tests__/InitialPageSizeExample.test.tsx +0 -211
  663. package/src/components/DataTable/examples/__tests__/PerformanceExample.test.tsx +0 -126
  664. package/src/components/Dialog/README.md +0 -804
  665. package/src/components/Dialog/examples/BasicHtmlTest.tsx +0 -55
  666. package/src/components/Dialog/examples/DebugHtmlExample.tsx +0 -68
  667. package/src/components/Dialog/examples/ScrollableDialogExample.tsx +0 -290
  668. package/src/components/Dialog/examples/SimpleHtmlTest.tsx +0 -61
  669. package/src/components/Dialog/examples/__tests__/HtmlDialogExample.test.tsx +0 -71
  670. package/src/components/Dialog/examples/__tests__/SimpleHtmlTest.test.tsx +0 -122
  671. package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +0 -147
  672. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +0 -611
  673. package/src/components/Dialog/utils/safeHtml.ts +0 -185
  674. package/src/components/EventSelector/types.ts +0 -79
  675. package/src/components/Form/FormErrorSummary.tsx +0 -113
  676. package/src/components/Form/FormField.tsx +0 -249
  677. package/src/components/Form/FormFieldset.tsx +0 -127
  678. package/src/components/Form/FormLiveRegion.tsx +0 -198
  679. package/src/components/Input/__mocks__/Input.tsx +0 -2
  680. package/src/components/NavigationMenu/types.ts +0 -85
  681. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +0 -326
  682. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -1078
  683. package/src/components/PasswordReset/PasswordResetForm.test.tsx +0 -597
  684. package/src/components/PasswordReset/PasswordResetForm.tsx +0 -201
  685. package/src/components/PasswordReset/index.ts +0 -2
  686. package/src/components/ProtectedRoute/README.md +0 -164
  687. package/src/components/PublicLayout/EventLogo.tsx +0 -175
  688. package/src/components/PublicLayout/PublicErrorBoundary.tsx +0 -282
  689. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +0 -216
  690. package/src/components/PublicLayout/PublicPageContextChecker.tsx +0 -131
  691. package/src/components/PublicLayout/PublicPageDebugger.tsx +0 -104
  692. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +0 -162
  693. package/src/components/PublicLayout/PublicPageFooter.tsx +0 -124
  694. package/src/components/PublicLayout/PublicPageHeader.tsx +0 -209
  695. package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +0 -449
  696. package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +0 -393
  697. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +0 -192
  698. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +0 -351
  699. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +0 -402
  700. package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +0 -460
  701. package/src/components/PublicLayout/__tests__/PublicPageProvider.test.tsx +0 -313
  702. package/src/components/Select/hooks.ts +0 -289
  703. package/src/hooks/useCounter.test.ts +0 -131
  704. package/src/hooks/useDebounce.test.ts +0 -375
  705. package/src/providers/AuthProvider.tsx +0 -15
  706. package/src/providers/EventProvider.tsx +0 -16
  707. package/src/providers/InactivityProvider.tsx +0 -15
  708. package/src/providers/OrganisationProvider.context.test.tsx +0 -169
  709. package/src/providers/UnifiedAuthProvider.tsx +0 -15
  710. package/src/types/theme.ts +0 -6
  711. package/src/types/unified.ts +0 -265
  712. package/src/utils/appConfig.ts +0 -47
  713. package/src/utils/appIdResolver.test.ts +0 -499
  714. package/src/utils/appIdResolver.ts +0 -130
  715. package/src/utils/appNameResolver.simple.test.ts +0 -212
  716. package/src/utils/appNameResolver.test.ts +0 -121
  717. package/src/utils/appNameResolver.ts +0 -191
  718. package/src/utils/audit.ts +0 -127
  719. package/src/utils/auth-utils.ts +0 -96
  720. package/src/utils/bundleAnalysis.ts +0 -129
  721. package/src/utils/debugLogger.ts +0 -67
  722. package/src/utils/deviceFingerprint.ts +0 -215
  723. package/src/utils/dynamicUtils.ts +0 -105
  724. package/src/utils/file-reference.test.ts +0 -788
  725. package/src/utils/file-reference.ts +0 -519
  726. package/src/utils/formatDate.test.ts +0 -237
  727. package/src/utils/formatting.ts +0 -170
  728. package/src/utils/lazyLoad.tsx +0 -44
  729. package/src/utils/logger.ts +0 -179
  730. package/src/utils/organisationContext.test.ts +0 -322
  731. package/src/utils/organisationContext.ts +0 -153
  732. package/src/utils/performanceBenchmark.ts +0 -64
  733. package/src/utils/performanceBudgets.ts +0 -110
  734. package/src/utils/permissionTypes.ts +0 -37
  735. package/src/utils/permissionUtils.test.ts +0 -393
  736. package/src/utils/permissionUtils.ts +0 -34
  737. package/src/utils/sanitization.ts +0 -264
  738. package/src/utils/schemaUtils.ts +0 -37
  739. package/src/utils/secureDataAccess.test.ts +0 -711
  740. package/src/utils/secureDataAccess.ts +0 -377
  741. package/src/utils/secureErrors.ts +0 -79
  742. package/src/utils/security.ts +0 -156
  743. package/src/utils/securityMonitor.ts +0 -45
  744. package/src/utils/sessionTracking.ts +0 -126
  745. package/src/utils/validation.ts +0 -111
  746. package/src/utils/validationUtils.ts +0 -120
  747. package/src/validation/index.ts +0 -12
  748. /package/dist/{DataTable-UA6CL4JI.js.map → DataTable-QAB34V6K.js.map} +0 -0
  749. /package/dist/{UnifiedAuthProvider-B37ATQHE.js.map → UnifiedAuthProvider-7F6T4B6K.js.map} +0 -0
  750. /package/dist/{api-45XYYO2A.js.map → api-ROMBCNKU.js.map} +0 -0
  751. /package/dist/{audit-64X3VJXB.js.map → audit-WRS3KJKI.js.map} +0 -0
  752. /package/dist/{chunk-PLDDJCW6.js.map → chunk-7D4SUZUM.js.map} +0 -0
  753. /package/dist/{useInactivityTracker-TO6ZOF35.js.map → chunk-KQCRWDSA.js.map} +0 -0
  754. /package/examples/{components 2/DataTable → DataTable}/InitialPageSizeExample.tsx +0 -0
  755. /package/examples/{features/public-pages → PublicPages}/index.ts +0 -0
  756. /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