@jmruthers/pace-core 0.5.67 → 0.5.69

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 (384) hide show
  1. package/README.md +26 -0
  2. package/dist/{DataTable-MFUXNGPR.js → DataTable-MPBSXUC6.js} +5 -6
  3. package/dist/{PublicLoadingSpinner-DdKXTkCZ.d.ts → PublicLoadingSpinner-BOdyU3u-.d.ts} +1 -1
  4. package/dist/{UnifiedAuthProvider-CQNiemcB.d.ts → UnifiedAuthProvider-D02AMXgO.d.ts} +3 -3
  5. package/dist/{chunk-CKNY7HYS.js → chunk-2ARQW6VX.js} +3 -3
  6. package/dist/{chunk-T2MQY57J.js → chunk-6JILXFEA.js} +335 -5
  7. package/dist/chunk-6JILXFEA.js.map +1 -0
  8. package/dist/{chunk-D7ARGIA3.js → chunk-6RBH67W7.js} +23 -6
  9. package/dist/chunk-6RBH67W7.js.map +1 -0
  10. package/dist/{chunk-C7GUF747.js → chunk-FJTAWPAQ.js} +3 -5
  11. package/dist/{chunk-C7GUF747.js.map → chunk-FJTAWPAQ.js.map} +1 -1
  12. package/dist/{chunk-4HQ5BOVZ.js → chunk-NO5QHMDX.js} +7 -6
  13. package/dist/chunk-NO5QHMDX.js.map +1 -0
  14. package/dist/{chunk-ZPK5656W.js → chunk-O3NWNXDY.js} +4 -5
  15. package/dist/chunk-O3NWNXDY.js.map +1 -0
  16. package/dist/{chunk-BTCA3ENN.js → chunk-Q2UP3ZWQ.js} +4 -4
  17. package/dist/{chunk-QVEOQVD4.js → chunk-RVYGJPOD.js} +173 -20
  18. package/dist/chunk-RVYGJPOD.js.map +1 -0
  19. package/dist/{chunk-FVDOEGGG.js → chunk-UCMHBF7Y.js} +3 -5
  20. package/dist/{chunk-FVDOEGGG.js.map → chunk-UCMHBF7Y.js.map} +1 -1
  21. package/dist/{chunk-T6HVDA24.js → chunk-V3QO3LL7.js} +5 -7
  22. package/dist/chunk-V3QO3LL7.js.map +1 -0
  23. package/dist/{chunk-ZB6AEA7I.js → chunk-ZXJGZLLO.js} +17 -17
  24. package/dist/{chunk-ZB6AEA7I.js.map → chunk-ZXJGZLLO.js.map} +1 -1
  25. package/dist/components.d.ts +2 -2
  26. package/dist/components.js +8 -9
  27. package/dist/components.js.map +1 -1
  28. package/dist/hooks.d.ts +1 -1
  29. package/dist/hooks.js +9 -6
  30. package/dist/hooks.js.map +1 -1
  31. package/dist/index.d.ts +4 -4
  32. package/dist/index.js +16 -16
  33. package/dist/index.js.map +1 -1
  34. package/dist/providers.d.ts +1 -1
  35. package/dist/providers.js +5 -7
  36. package/dist/rbac/index.js +5 -6
  37. package/dist/{usePublicRouteParams-CdoFxnJK.d.ts → usePublicRouteParams-Ua1Vz-HG.d.ts} +35 -1
  38. package/dist/utils.d.ts +4 -1
  39. package/dist/utils.js +3 -3
  40. package/docs/DOCUMENTATION_CHECKLIST.md +281 -0
  41. package/docs/README.md +22 -10
  42. package/docs/api/README.md +26 -0
  43. package/docs/api/classes/ColumnFactory.md +1 -1
  44. package/docs/api/classes/ErrorBoundary.md +1 -1
  45. package/docs/api/classes/InvalidScopeError.md +1 -1
  46. package/docs/api/classes/MissingUserContextError.md +1 -1
  47. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  48. package/docs/api/classes/PermissionDeniedError.md +1 -1
  49. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  50. package/docs/api/classes/RBACAuditManager.md +1 -1
  51. package/docs/api/classes/RBACCache.md +1 -1
  52. package/docs/api/classes/RBACEngine.md +1 -1
  53. package/docs/api/classes/RBACError.md +1 -1
  54. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  55. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  56. package/docs/api/classes/StorageUtils.md +1 -1
  57. package/docs/api/interfaces/AggregateConfig.md +1 -1
  58. package/docs/api/interfaces/ButtonProps.md +1 -1
  59. package/docs/api/interfaces/CardProps.md +1 -1
  60. package/docs/api/interfaces/ColorPalette.md +1 -1
  61. package/docs/api/interfaces/ColorShade.md +1 -1
  62. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  63. package/docs/api/interfaces/DataTableAction.md +1 -1
  64. package/docs/api/interfaces/DataTableColumn.md +1 -1
  65. package/docs/api/interfaces/DataTableProps.md +1 -1
  66. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  67. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  68. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  69. package/docs/api/interfaces/EventContextType.md +1 -1
  70. package/docs/api/interfaces/EventLogoProps.md +1 -1
  71. package/docs/api/interfaces/EventProviderProps.md +1 -1
  72. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  73. package/docs/api/interfaces/FileUploadProps.md +1 -1
  74. package/docs/api/interfaces/FooterProps.md +1 -1
  75. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  76. package/docs/api/interfaces/InputProps.md +1 -1
  77. package/docs/api/interfaces/LabelProps.md +1 -1
  78. package/docs/api/interfaces/LoginFormProps.md +1 -1
  79. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  80. package/docs/api/interfaces/NavigationContextType.md +1 -1
  81. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  82. package/docs/api/interfaces/NavigationItem.md +1 -1
  83. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  84. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  85. package/docs/api/interfaces/Organisation.md +1 -1
  86. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  87. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  88. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  89. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  90. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  91. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  92. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  93. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  94. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  95. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  96. package/docs/api/interfaces/PaletteData.md +1 -1
  97. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  98. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  99. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  100. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  101. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  102. package/docs/api/interfaces/PublicPageHeaderProps.md +2 -2
  103. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  104. package/docs/api/interfaces/RBACConfig.md +1 -1
  105. package/docs/api/interfaces/RBACContextType.md +1 -1
  106. package/docs/api/interfaces/RBACLogger.md +1 -1
  107. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  108. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  109. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  110. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  111. package/docs/api/interfaces/RouteConfig.md +1 -1
  112. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  113. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  114. package/docs/api/interfaces/StorageConfig.md +1 -1
  115. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  116. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  117. package/docs/api/interfaces/StorageListOptions.md +1 -1
  118. package/docs/api/interfaces/StorageListResult.md +1 -1
  119. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  120. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  121. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  122. package/docs/api/interfaces/StyleImport.md +1 -1
  123. package/docs/api/interfaces/SwitchProps.md +1 -1
  124. package/docs/api/interfaces/ToastActionElement.md +1 -1
  125. package/docs/api/interfaces/ToastProps.md +1 -1
  126. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  127. package/docs/api/interfaces/UnifiedAuthProviderProps.md +4 -4
  128. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  129. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  130. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  131. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  132. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  133. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  134. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  135. package/docs/api/interfaces/UserEventAccess.md +1 -1
  136. package/docs/api/interfaces/UserMenuProps.md +1 -1
  137. package/docs/api/interfaces/UserProfile.md +1 -1
  138. package/docs/api/modules.md +39 -14
  139. package/docs/api-reference/providers.md +16 -7
  140. package/docs/architecture/services.md +374 -0
  141. package/docs/best-practices/README.md +1 -1
  142. package/docs/best-practices/testing.md +1 -1
  143. package/docs/breaking-changes.md +182 -0
  144. package/docs/common-patterns.md +445 -0
  145. package/docs/core-concepts/authentication.md +26 -11
  146. package/docs/core-concepts/events.md +2 -0
  147. package/docs/core-concepts/organisations.md +2 -0
  148. package/docs/core-concepts/permissions.md +2 -0
  149. package/docs/{INDEX.md → documentation-index.md} +26 -38
  150. package/docs/faq.md +286 -0
  151. package/docs/{FILE_REFERENCE_SYSTEM.md → file-reference-system.md} +1 -1
  152. package/docs/getting-started/installation-guide.md +284 -0
  153. package/docs/getting-started/quick-start.md +8 -1
  154. package/docs/implementation-guides/app-layout.md +3 -1
  155. package/docs/implementation-guides/data-tables.md +2 -0
  156. package/docs/implementation-guides/dynamic-colors.md +47 -2
  157. package/docs/implementation-guides/event-theming-summary.md +220 -0
  158. package/docs/implementation-guides/forms.md +9 -7
  159. package/docs/implementation-guides/navigation.md +2 -0
  160. package/docs/migration/service-architecture.md +351 -0
  161. package/docs/migration-guides/unified-auth-provider-mandatory-timeouts.md +226 -0
  162. package/docs/rbac/README-rbac-rls-integration.md +2 -2
  163. package/docs/rbac/README.md +1 -1
  164. package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
  165. package/docs/rbac/quick-start.md +2 -0
  166. package/docs/rbac/rbac-rls-integration.md +2 -2
  167. package/docs/security/README.md +5 -1
  168. package/docs/style-guide.md +136 -1
  169. package/docs/testing/README.md +1 -1
  170. package/docs/troubleshooting/authentication-issues.md +334 -0
  171. package/docs/troubleshooting/common-issues.md +2 -0
  172. package/docs/troubleshooting/styling-issues.md +199 -144
  173. package/docs/usage.md +23 -2
  174. package/package.json +1 -1
  175. package/src/__tests__/{TESTING_GUIDELINES.md → TEST_GUIDE_CURSOR.md} +20 -0
  176. package/src/__tests__/TEST_GUIDE_HUMAN.md +103 -0
  177. package/src/__tests__/fixtures/test-data.ts +90 -0
  178. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +260 -0
  179. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +224 -0
  180. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +273 -0
  181. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +98 -0
  182. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +436 -0
  183. package/src/__tests__/helpers/__tests__/timer-utils.test.ts +371 -0
  184. package/src/__tests__/helpers/component-test-utils.tsx +14 -4
  185. package/src/__tests__/helpers/optimized-test-setup.ts +68 -0
  186. package/src/__tests__/helpers/test-providers.tsx +329 -0
  187. package/src/__tests__/helpers/test-utils.tsx +91 -45
  188. package/src/__tests__/helpers/timer-utils.ts +71 -0
  189. package/src/__tests__/hooks/usePermissions.test.ts +1 -5
  190. package/src/__tests__/integration/UserProfile.test.tsx +1 -5
  191. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +42 -12
  192. package/src/__tests__/setup.ts +34 -28
  193. package/src/components/Alert/Alert.test.tsx +1 -5
  194. package/src/components/Avatar/Avatar.test.tsx +1 -5
  195. package/src/components/Button/Button.test.tsx +4 -20
  196. package/src/components/Card/Card.test.tsx +1 -5
  197. package/src/components/Checkbox/Checkbox.test.tsx +1 -5
  198. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -5
  199. package/src/components/DataTable/__tests__/DataTable.test.tsx +45 -49
  200. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +1 -5
  201. package/src/components/DataTable/__tests__/styles.test.ts +382 -0
  202. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +409 -0
  203. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +634 -0
  204. package/src/components/DataTable/core/__tests__/DataManager.test.ts +519 -0
  205. package/src/components/DataTable/core/__tests__/StateManager.test.ts +714 -0
  206. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +592 -0
  207. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +354 -0
  208. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +539 -0
  209. package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +1 -5
  210. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +1 -8
  211. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +34 -38
  212. package/src/components/Footer/Footer.test.tsx +1 -5
  213. package/src/components/Form/Form.test.tsx +22 -35
  214. package/src/components/Header/Header.test.tsx +1 -9
  215. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +1 -5
  216. package/src/components/Input/Input.test.tsx +2 -10
  217. package/src/components/LoginForm/LoginForm.test.tsx +1 -5
  218. package/src/components/NavigationMenu/NavigationMenu.test.tsx +24 -24
  219. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +1 -6
  220. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +6 -16
  221. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +1 -5
  222. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +1 -5
  223. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +1 -7
  224. package/src/components/PasswordReset/PasswordChangeForm.test.tsx +1 -9
  225. package/src/components/PasswordReset/PasswordResetForm.test.tsx +1 -9
  226. package/src/components/PublicLayout/PublicErrorBoundary.tsx +4 -5
  227. package/src/components/PublicLayout/PublicPageHeader.tsx +13 -9
  228. package/src/components/PublicLayout/__tests__/EventLogo.test.tsx +666 -0
  229. package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +457 -0
  230. package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +393 -0
  231. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +351 -0
  232. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +374 -0
  233. package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +388 -0
  234. package/src/components/Select/Select.bug-test.tsx +69 -0
  235. package/src/components/Select/Select.refactored.tsx +497 -0
  236. package/src/components/Select/Select.test.tsx +42 -49
  237. package/src/components/Select/Select.tsx +5 -2
  238. package/src/components/Select/hooks.ts +254 -0
  239. package/src/components/Switch/Switch.test.tsx +1 -5
  240. package/src/components/Table/__tests__/Table.test.tsx +775 -0
  241. package/src/components/Toast/Toast.test.tsx +15 -8
  242. package/src/components/Tooltip/Tooltip.test.tsx +1 -5
  243. package/src/components/UserMenu/UserMenu.test.tsx +3 -15
  244. package/src/components/__tests__/FileDisplay.test.tsx +575 -0
  245. package/src/components/__tests__/FileUpload.test.tsx +446 -0
  246. package/src/components/__tests__/SuperAdminGuard.test.tsx +422 -354
  247. package/src/hooks/__tests__/ServiceHooks.test.tsx +613 -0
  248. package/src/hooks/__tests__/hooks.integration.test.tsx +1 -10
  249. package/src/hooks/__tests__/useApiFetch.unit.test.ts +10 -14
  250. package/src/hooks/__tests__/useAppConfig.unit.test.ts +307 -0
  251. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +1 -6
  252. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +1 -5
  253. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +6 -9
  254. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +321 -0
  255. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +583 -0
  256. package/src/hooks/__tests__/usePublicEventLogo.unit.test.ts +640 -0
  257. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +435 -0
  258. package/src/hooks/__tests__/useRBAC.unit.test.ts +10 -10
  259. package/src/hooks/__tests__/useStorage.unit.test.ts +751 -0
  260. package/src/hooks/index.ts +3 -0
  261. package/src/hooks/public/usePublicEvent.ts +181 -13
  262. package/src/hooks/public/usePublicRouteParams.ts +13 -3
  263. package/src/hooks/services/useAuth.ts +50 -0
  264. package/src/hooks/services/useAuthService.ts +30 -0
  265. package/src/hooks/services/useCurrentEvent.ts +36 -0
  266. package/src/hooks/services/useCurrentOrganisation.ts +52 -0
  267. package/src/hooks/services/useEventService.ts +30 -0
  268. package/src/hooks/services/useInactivityService.ts +30 -0
  269. package/src/hooks/services/useOrganisationService.ts +30 -0
  270. package/src/hooks/services/usePermissions.ts +70 -0
  271. package/src/hooks/services/useRBACService.ts +30 -0
  272. package/src/hooks/useCounter.test.ts +1 -5
  273. package/src/hooks/useEventTheme.ts +86 -0
  274. package/src/hooks/useOrganisationPermissions.test.ts +2 -5
  275. package/src/hooks/useOrganisationSecurity.test.ts +1 -5
  276. package/src/hooks/usePermissionCache.test.ts +1 -5
  277. package/src/hooks/usePermissionCheck.ts +150 -0
  278. package/src/hooks/useSecureDataAccess.test.ts +1 -5
  279. package/src/index.ts +1 -0
  280. package/src/providers/OrganisationProvider.test.tsx +1 -5
  281. package/src/providers/OrganisationProvider.tsx +56 -4
  282. package/src/providers/UnifiedAuthProvider.test.simple.tsx +42 -6
  283. package/src/providers/UnifiedAuthProvider.test.tsx +1 -5
  284. package/src/providers/UnifiedAuthProvider.tsx +4 -4
  285. package/src/providers/__tests__/AuthProvider.test.tsx +105 -439
  286. package/src/providers/__tests__/AuthProvider.test.tsx.backup +771 -0
  287. package/src/providers/__tests__/EventProvider.test.tsx +211 -110
  288. package/src/providers/__tests__/EventProvider.test.tsx.backup +824 -0
  289. package/src/providers/__tests__/InactivityProvider.test.tsx +1 -5
  290. package/src/providers/__tests__/OrganisationProvider.test.tsx +97 -261
  291. package/src/providers/__tests__/OrganisationProvider.test.tsx.backup +820 -0
  292. package/src/providers/__tests__/ServiceProviders.test.tsx +477 -0
  293. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +72 -504
  294. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup +911 -0
  295. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup2 +166 -0
  296. package/src/providers/services/AuthServiceProvider.tsx +65 -0
  297. package/src/providers/services/EventServiceProvider.tsx +83 -0
  298. package/src/providers/services/InactivityServiceProvider.tsx +83 -0
  299. package/src/providers/services/OrganisationServiceProvider.tsx +77 -0
  300. package/src/providers/services/RBACServiceProvider.tsx +79 -0
  301. package/src/providers/services/UnifiedAuthProvider.tsx +368 -0
  302. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +210 -0
  303. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +269 -0
  304. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +892 -0
  305. package/src/rbac/__tests__/engine.comprehensive.test.ts +954 -0
  306. package/src/rbac/__tests__/integration.authflow.test.tsx +1 -5
  307. package/src/rbac/__tests__/integration.navigation.test.tsx +1 -4
  308. package/src/rbac/__tests__/rbac-core.test.tsx +2 -7
  309. package/src/rbac/__tests__/rbac-functions.test.ts +1 -9
  310. package/src/rbac/__tests__/rbac-integration.test.ts +1 -9
  311. package/src/rbac/api.test.ts +1 -9
  312. package/src/rbac/cache.test.ts +10 -8
  313. package/src/rbac/cli/__tests__/policy-manager.test.ts +339 -0
  314. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +1 -5
  315. package/src/rbac/components/NavigationProvider.test.tsx +1 -5
  316. package/src/rbac/components/PagePermissionProvider.test.tsx +1 -5
  317. package/src/rbac/components/SecureDataProvider.test.tsx +1 -5
  318. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +25 -29
  319. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +27 -30
  320. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +23 -27
  321. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +18 -22
  322. package/src/rbac/config.test.ts +1 -5
  323. package/src/rbac/hooks/useCan.test.ts +262 -9
  324. package/src/rbac/hooks/usePermissions.test.ts +246 -6
  325. package/src/rbac/hooks/useRBAC.simple.test.ts +1 -5
  326. package/src/rbac/hooks/useRBAC.test.ts +472 -198
  327. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +1 -9
  328. package/src/services/AuthService.ts +416 -0
  329. package/src/services/EventService.ts +366 -0
  330. package/src/services/InactivityService.ts +388 -0
  331. package/src/services/OrganisationService.ts +592 -0
  332. package/src/services/RBACService.ts +522 -0
  333. package/src/services/__tests__/AuthService.test.ts +356 -0
  334. package/src/services/__tests__/BaseService.test.ts +314 -0
  335. package/src/services/__tests__/EventService.test.ts +489 -0
  336. package/src/services/__tests__/InactivityService.test.ts +403 -0
  337. package/src/services/__tests__/OrganisationService.test.ts +660 -0
  338. package/src/services/__tests__/RBACService.test.ts +492 -0
  339. package/src/services/base/BaseService.ts +87 -0
  340. package/src/services/interfaces/IAuthService.ts +39 -0
  341. package/src/services/interfaces/IEventService.ts +30 -0
  342. package/src/services/interfaces/IInactivityService.ts +31 -0
  343. package/src/services/interfaces/IOrganisationService.ts +41 -0
  344. package/src/services/interfaces/IRBACService.ts +62 -0
  345. package/src/theming/__tests__/runtime.test.ts +540 -0
  346. package/src/types/__tests__/file-reference.test.ts +447 -0
  347. package/src/types/__tests__/organisation.test.ts +1133 -0
  348. package/src/types/__tests__/theme.test.ts +830 -0
  349. package/src/types/__tests__/type-validation.test.ts +527 -0
  350. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +1 -5
  351. package/src/utils/__tests__/debugLogger.test.ts +417 -0
  352. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -6
  353. package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -5
  354. package/src/utils/__tests__/lazyLoad.unit.test.tsx +35 -35
  355. package/src/utils/__tests__/organisationContext.unit.test.ts +1 -5
  356. package/src/utils/__tests__/performanceBudgets.unit.test.ts +5 -11
  357. package/src/utils/__tests__/secureErrors.unit.test.ts +1 -6
  358. package/src/utils/__tests__/secureStorage.unit.test.ts +1 -5
  359. package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -5
  360. package/src/utils/__tests__/sessionTracking.unit.test.ts +1 -5
  361. package/src/utils/appIdResolver.test.ts +6 -10
  362. package/src/utils/appNameResolver.simple.test.ts +142 -0
  363. package/src/utils/appNameResolver.test.ts +31 -458
  364. package/src/utils/appNameResolver.test.ts.backup +494 -0
  365. package/src/utils/debugLogger.ts +26 -5
  366. package/src/utils/formatDate.test.ts +1 -5
  367. package/src/utils/organisationContext.test.ts +1 -5
  368. package/src/utils/performanceBudgets.ts +3 -4
  369. package/src/utils/secureDataAccess.test.ts +1 -5
  370. package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -5
  371. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +1 -5
  372. package/dist/chunk-4HQ5BOVZ.js.map +0 -1
  373. package/dist/chunk-D7ARGIA3.js.map +0 -1
  374. package/dist/chunk-QVEOQVD4.js.map +0 -1
  375. package/dist/chunk-T2MQY57J.js.map +0 -1
  376. package/dist/chunk-T6HVDA24.js.map +0 -1
  377. package/dist/chunk-VTJ5HCZB.js +0 -315
  378. package/dist/chunk-VTJ5HCZB.js.map +0 -1
  379. package/dist/chunk-ZPK5656W.js.map +0 -1
  380. package/docs/getting-started/installation.md +0 -269
  381. package/src/__tests__/REBUILD_PLAN.md +0 -223
  382. /package/dist/{DataTable-MFUXNGPR.js.map → DataTable-MPBSXUC6.js.map} +0 -0
  383. /package/dist/{chunk-CKNY7HYS.js.map → chunk-2ARQW6VX.js.map} +0 -0
  384. /package/dist/{chunk-BTCA3ENN.js.map → chunk-Q2UP3ZWQ.js.map} +0 -0
@@ -0,0 +1,492 @@
1
+ /**
2
+ * @file RBACService Unit Tests
3
+ * @package @jmruthers/pace-core
4
+ * @module Services/__tests__
5
+ * @since 0.1.0
6
+ *
7
+ * Unit tests for RBACService class.
8
+ * Tests role-based access control operations, permission checking, and state management.
9
+ */
10
+
11
+ import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
12
+ import { RBACService } from '../RBACService';
13
+ import { AccessLevel } from '../../types/unified';
14
+
15
+ // Mock Supabase client
16
+ const createMockSupabaseClient = () => ({
17
+ rpc: vi.fn(),
18
+ from: vi.fn(() => ({
19
+ select: vi.fn(() => ({
20
+ eq: vi.fn(() => ({
21
+ eq: vi.fn(() => ({
22
+ single: vi.fn()
23
+ }))
24
+ }))
25
+ }))
26
+ })),
27
+ });
28
+
29
+ // Mock user and session
30
+ const mockUser = {
31
+ id: 'user-1',
32
+ email: 'test@example.com',
33
+ user_metadata: { globalRole: 'user' }
34
+ };
35
+
36
+ const mockSession = {
37
+ access_token: 'token',
38
+ user: mockUser
39
+ };
40
+
41
+ describe('RBACService', () => {
42
+ let mockSupabase: ReturnType<typeof createMockSupabaseClient>;
43
+ let rbacService: RBACService;
44
+
45
+ beforeEach(() => {
46
+ mockSupabase = createMockSupabaseClient();
47
+ rbacService = new RBACService(mockSupabase as any, mockUser, mockSession, 'test-app');
48
+ });
49
+
50
+ afterEach(() => {
51
+ rbacService.cleanup();
52
+ vi.clearAllMocks();
53
+ });
54
+
55
+ describe('Initialization', () => {
56
+ it('should initialize with default state', () => {
57
+ expect(rbacService.getPermissions()).toEqual({});
58
+ expect(rbacService.getRoles()).toEqual([]);
59
+ expect(rbacService.getAccessLevel()).toBe(AccessLevel.VIEWER);
60
+ expect(rbacService.isLoading()).toBe(false);
61
+ expect(rbacService.getError()).toBeNull();
62
+ expect(rbacService.getSelectedEventId()).toBeNull();
63
+ expect(rbacService.getAppConfig()).toBeNull();
64
+ expect(rbacService.getUserEventAccess()).toEqual([]);
65
+ expect(rbacService.isEventAccessLoading()).toBe(false);
66
+ expect(rbacService.getSelectedOrganisationId()).toBeNull();
67
+ });
68
+
69
+ it('should set super admin role from user metadata', async () => {
70
+ const superAdminUser = {
71
+ ...mockUser,
72
+ user_metadata: { globalRole: 'super_admin' }
73
+ };
74
+
75
+ const service = new RBACService(mockSupabase as any, superAdminUser, mockSession, 'test-app');
76
+ await service.initialize();
77
+
78
+ expect(service.getRoles()).toContain('super_admin');
79
+ expect(service.getAccessLevel()).toBe(AccessLevel.ADMIN);
80
+ expect(service.getPermissions()).toHaveProperty('admin:create', true);
81
+ });
82
+ });
83
+
84
+ describe('Permission Checking', () => {
85
+ beforeEach(async () => {
86
+ // Mock app config loading
87
+ mockSupabase.from.mockReturnValue({
88
+ select: vi.fn().mockReturnValue({
89
+ eq: vi.fn().mockReturnValue({
90
+ eq: vi.fn().mockReturnValue({
91
+ single: vi.fn().mockResolvedValue({
92
+ data: { id: 'app-1' },
93
+ error: null
94
+ })
95
+ })
96
+ })
97
+ })
98
+ });
99
+
100
+ // Mock get_app_config RPC
101
+ mockSupabase.rpc.mockImplementation((rpcName, params) => {
102
+ if (rpcName === 'get_app_config') {
103
+ return Promise.resolve({
104
+ data: [{
105
+ supports_direct_access: false,
106
+ requires_event: true
107
+ }],
108
+ error: null
109
+ });
110
+ }
111
+ // Mock rbac_permissions_get for permission checking
112
+ return Promise.resolve({
113
+ data: [
114
+ {
115
+ permission_type: 'event_app_access',
116
+ role_name: 'planner',
117
+ permission: 'events:read'
118
+ }
119
+ ],
120
+ error: null
121
+ });
122
+ });
123
+
124
+ // Set event ID before initialization so permissions are loaded
125
+ rbacService.setSelectedEventId('event-1');
126
+ await rbacService.initialize();
127
+ });
128
+
129
+ it('should check permissions correctly', async () => {
130
+ expect(rbacService.hasPermission('events:read')).toBe(true);
131
+ expect(rbacService.hasPermission('events:write')).toBe(false);
132
+ });
133
+
134
+ it('should check roles correctly', async () => {
135
+ expect(rbacService.hasRole('planner')).toBe(true);
136
+ expect(rbacService.hasRole('admin')).toBe(false);
137
+ });
138
+
139
+ it('should check access levels correctly', async () => {
140
+ expect(rbacService.hasAccessLevel(AccessLevel.VIEWER)).toBe(true);
141
+ expect(rbacService.hasAccessLevel(AccessLevel.PLANNER)).toBe(true);
142
+ expect(rbacService.hasAccessLevel(AccessLevel.ADMIN)).toBe(false);
143
+ });
144
+
145
+ it('should check resource access correctly', async () => {
146
+ expect(rbacService.canAccess('events', 'read')).toBe(true);
147
+ expect(rbacService.canAccess('events', 'write')).toBe(false);
148
+ });
149
+
150
+ it('should validate permissions asynchronously', async () => {
151
+ const result = await rbacService.validatePermission('events:read');
152
+ expect(result).toBe(true);
153
+ });
154
+
155
+ it('should validate access asynchronously', async () => {
156
+ const result = await rbacService.validateAccess('events', 'read');
157
+ expect(result).toBe(true);
158
+ });
159
+ });
160
+
161
+ describe('Event Management', () => {
162
+ it('should set selected event ID', () => {
163
+ rbacService.setSelectedEventId('event-123');
164
+
165
+ expect(rbacService.getSelectedEventId()).toBe('event-123');
166
+ });
167
+
168
+ it('should get user event access for specific event', async () => {
169
+ const mockEventAccess = [
170
+ {
171
+ event_id: 'event-1',
172
+ event_name: 'Test Event',
173
+ event_description: 'Test Description',
174
+ start_date: '2024-01-01',
175
+ end_date: '2024-01-02',
176
+ event_status: 'active',
177
+ app_id: 'app-1',
178
+ access_level: 'planner',
179
+ granted_at: '2024-01-01T00:00:00Z',
180
+ organisation_id: 'org-1'
181
+ }
182
+ ];
183
+
184
+ // Mock the rbac_apps and rbac_event_app_roles queries
185
+ mockSupabase.from.mockImplementation((table: string) => {
186
+ if (table === 'rbac_apps') {
187
+ return {
188
+ select: vi.fn().mockReturnValue({
189
+ eq: vi.fn().mockReturnValue({
190
+ eq: vi.fn().mockReturnValue({
191
+ single: vi.fn().mockResolvedValue({
192
+ data: { id: 'app-1' },
193
+ error: null
194
+ })
195
+ })
196
+ })
197
+ })
198
+ };
199
+ }
200
+ if (table === 'rbac_event_app_roles') {
201
+ return {
202
+ select: vi.fn().mockReturnValue({
203
+ eq: vi.fn().mockReturnValue({
204
+ eq: vi.fn().mockResolvedValue({
205
+ data: mockEventAccess,
206
+ error: null
207
+ })
208
+ })
209
+ })
210
+ };
211
+ }
212
+ return mockSupabase.from();
213
+ });
214
+
215
+ await rbacService.loadUserEventAccess();
216
+
217
+ const eventAccess = rbacService.getUserEventAccessById('event-1');
218
+ expect(eventAccess).toEqual(mockEventAccess[0]);
219
+ });
220
+ });
221
+
222
+ describe('Organisation Context', () => {
223
+ it('should require organisation context', () => {
224
+ expect(() => rbacService.requireOrganisationContext()).toThrow('Organisation context is required but not available');
225
+ });
226
+
227
+ it('should return organisation context when set', () => {
228
+ rbacService.setSelectedEventId('event-1'); // This sets the organisation context internally
229
+
230
+ // Mock the organisation context
231
+ const orgId = 'org-1';
232
+ // Note: In a real implementation, this would be set by the OrganisationService
233
+ // For testing, we'll simulate it
234
+ (rbacService as any).selectedOrganisationId = orgId;
235
+
236
+ expect(rbacService.requireOrganisationContext()).toBe(orgId);
237
+ });
238
+ });
239
+
240
+ describe('Data Operations', () => {
241
+ it('should refresh permissions for event', async () => {
242
+ // Mock the rbac_apps query
243
+ mockSupabase.from.mockReturnValue({
244
+ select: vi.fn().mockReturnValue({
245
+ eq: vi.fn().mockReturnValue({
246
+ eq: vi.fn().mockReturnValue({
247
+ single: vi.fn().mockResolvedValue({
248
+ data: { id: 'app-1' },
249
+ error: null
250
+ })
251
+ })
252
+ })
253
+ })
254
+ });
255
+
256
+ mockSupabase.rpc.mockImplementation((rpcName, params) => {
257
+ if (rpcName === 'get_app_config') {
258
+ return Promise.resolve({
259
+ data: [{
260
+ supports_direct_access: false,
261
+ requires_event: true
262
+ }],
263
+ error: null
264
+ });
265
+ }
266
+ return Promise.resolve({
267
+ data: [
268
+ {
269
+ permission_type: 'event_app_access',
270
+ role_name: 'planner',
271
+ permission: 'events:read'
272
+ }
273
+ ],
274
+ error: null
275
+ });
276
+ });
277
+
278
+ // Ensure app config is loaded
279
+ await rbacService.initialize();
280
+
281
+ // Clear the RPC mock call count from initialization
282
+ vi.clearAllMocks();
283
+
284
+ // Re-setup mocks for the refresh call
285
+ mockSupabase.from.mockReturnValue({
286
+ select: vi.fn().mockReturnValue({
287
+ eq: vi.fn().mockReturnValue({
288
+ eq: vi.fn().mockReturnValue({
289
+ single: vi.fn().mockResolvedValue({
290
+ data: { id: 'app-1' },
291
+ error: null
292
+ })
293
+ })
294
+ })
295
+ })
296
+ });
297
+
298
+ mockSupabase.rpc.mockResolvedValue({
299
+ data: [
300
+ {
301
+ permission_type: 'event_app_access',
302
+ role_name: 'planner',
303
+ permission: 'events:read'
304
+ }
305
+ ],
306
+ error: null
307
+ });
308
+
309
+ await rbacService.refreshPermissions('event-1');
310
+
311
+ expect(mockSupabase.rpc).toHaveBeenCalledWith('rbac_permissions_get', {
312
+ p_user_id: mockUser.id,
313
+ p_app_id: 'app-1',
314
+ p_event_id: 'event-1',
315
+ p_organisation_id: null
316
+ });
317
+ });
318
+
319
+ it('should load user event access', async () => {
320
+ const mockEventAccess = [
321
+ {
322
+ event_id: 'event-1',
323
+ role: 'planner',
324
+ granted_at: '2024-01-01T00:00:00Z'
325
+ }
326
+ ];
327
+
328
+ // Mock the rbac_apps and rbac_event_app_roles queries
329
+ mockSupabase.from.mockImplementation((table: string) => {
330
+ if (table === 'rbac_apps') {
331
+ return {
332
+ select: vi.fn().mockReturnValue({
333
+ eq: vi.fn().mockReturnValue({
334
+ eq: vi.fn().mockReturnValue({
335
+ single: vi.fn().mockResolvedValue({
336
+ data: { id: 'app-1' },
337
+ error: null
338
+ })
339
+ })
340
+ })
341
+ })
342
+ };
343
+ }
344
+ if (table === 'rbac_event_app_roles') {
345
+ return {
346
+ select: vi.fn().mockReturnValue({
347
+ eq: vi.fn().mockReturnValue({
348
+ eq: vi.fn().mockResolvedValue({
349
+ data: mockEventAccess,
350
+ error: null
351
+ })
352
+ })
353
+ })
354
+ };
355
+ }
356
+ return mockSupabase.from();
357
+ });
358
+
359
+ await rbacService.loadUserEventAccess();
360
+
361
+ expect(rbacService.getUserEventAccess()).toHaveLength(1);
362
+ expect(rbacService.getUserEventAccess()[0].event_id).toBe('event-1');
363
+ });
364
+
365
+ it('should handle RPC errors gracefully', async () => {
366
+ // Mock the rbac_apps query
367
+ mockSupabase.from.mockReturnValue({
368
+ select: vi.fn().mockReturnValue({
369
+ eq: vi.fn().mockReturnValue({
370
+ eq: vi.fn().mockReturnValue({
371
+ single: vi.fn().mockResolvedValue({
372
+ data: { id: 'app-1' },
373
+ error: null
374
+ })
375
+ })
376
+ })
377
+ })
378
+ });
379
+
380
+ // Mock the RPC call to return app config first, then error
381
+ mockSupabase.rpc.mockImplementation((rpcName, params) => {
382
+ if (rpcName === 'get_app_config') {
383
+ return Promise.resolve({
384
+ data: [{
385
+ supports_direct_access: false,
386
+ requires_event: true
387
+ }],
388
+ error: null
389
+ });
390
+ }
391
+ if (rpcName === 'rbac_permissions_get') {
392
+ return Promise.resolve({
393
+ data: null,
394
+ error: { message: 'RPC error' }
395
+ });
396
+ }
397
+ return Promise.resolve({ data: null, error: null });
398
+ });
399
+
400
+ // Ensure app config is loaded
401
+ await rbacService.initialize();
402
+
403
+ await rbacService.refreshPermissions('event-1');
404
+
405
+ expect(rbacService.getError()).toBeDefined();
406
+ expect(rbacService.getError()?.message).toBe('RPC error');
407
+ });
408
+ });
409
+
410
+ describe('State Management', () => {
411
+ it('should notify subscribers when state changes', () => {
412
+ const subscriber = vi.fn();
413
+ const unsubscribe = rbacService.subscribe(subscriber);
414
+
415
+ rbacService.setSelectedEventId('event-1');
416
+
417
+ expect(subscriber).toHaveBeenCalled();
418
+
419
+ unsubscribe();
420
+ });
421
+
422
+ it('should cleanup subscriptions on cleanup', () => {
423
+ const subscriber = vi.fn();
424
+ rbacService.subscribe(subscriber);
425
+
426
+ rbacService.cleanup();
427
+
428
+ // After cleanup, new state changes shouldn't notify subscribers
429
+ rbacService.setSelectedEventId('event-1');
430
+
431
+ expect(subscriber).not.toHaveBeenCalled();
432
+ });
433
+ });
434
+
435
+ describe('Super Admin Override', () => {
436
+ it('should grant all permissions to super admin', async () => {
437
+ const superAdminUser = {
438
+ ...mockUser,
439
+ user_metadata: { globalRole: 'super_admin' }
440
+ };
441
+
442
+ const service = new RBACService(mockSupabase as any, superAdminUser, mockSession, 'test-app');
443
+ await service.initialize();
444
+
445
+ expect(service.hasPermission('admin:create')).toBe(true);
446
+ expect(service.hasPermission('admin:read')).toBe(true);
447
+ expect(service.hasPermission('admin:update')).toBe(true);
448
+ expect(service.hasPermission('admin:delete')).toBe(true);
449
+ expect(service.hasPermission('users:create')).toBe(true);
450
+ expect(service.hasPermission('users:read')).toBe(true);
451
+ expect(service.hasPermission('users:update')).toBe(true);
452
+ expect(service.hasPermission('users:delete')).toBe(true);
453
+ expect(service.hasPermission('events:create')).toBe(true);
454
+ expect(service.hasPermission('events:read')).toBe(true);
455
+ expect(service.hasPermission('events:update')).toBe(true);
456
+ expect(service.hasPermission('events:delete')).toBe(true);
457
+ });
458
+
459
+ it('should recognize super admin role', async () => {
460
+ const superAdminUser = {
461
+ ...mockUser,
462
+ user_metadata: { globalRole: 'super_admin' }
463
+ };
464
+
465
+ const service = new RBACService(mockSupabase as any, superAdminUser, mockSession, 'test-app');
466
+ await service.initialize();
467
+
468
+ expect(service.hasRole('super_admin')).toBe(true);
469
+ expect(service.hasRole('super')).toBe(true);
470
+ });
471
+ });
472
+
473
+ describe('Error Handling', () => {
474
+ it('should handle missing dependencies gracefully', async () => {
475
+ const serviceWithoutUser = new RBACService(mockSupabase as any, null, null, 'test-app', true);
476
+
477
+ await serviceWithoutUser.refreshPermissions();
478
+
479
+ expect(serviceWithoutUser.getPermissions()).toEqual({});
480
+ expect(serviceWithoutUser.getRoles()).toEqual([]);
481
+ expect(serviceWithoutUser.getAccessLevel()).toBe(AccessLevel.VIEWER);
482
+ });
483
+
484
+ it('should handle network errors', async () => {
485
+ mockSupabase.from().select().eq().eq().single.mockRejectedValue(new Error('Network error'));
486
+
487
+ await rbacService.initialize();
488
+
489
+ expect(rbacService.getError()).toBeDefined();
490
+ });
491
+ });
492
+ });
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @file Base Service Class
3
+ * @package @jmruthers/pace-core
4
+ * @module Services/Base
5
+ * @since 0.1.0
6
+ *
7
+ * Base service class implementing the observable pattern for React subscriptions.
8
+ * All services extend this class to provide state change notifications.
9
+ */
10
+
11
+ export type StateChangeCallback = () => void;
12
+
13
+ export abstract class BaseService {
14
+ private subscribers: Array<StateChangeCallback> = [];
15
+ private isInitialized = false;
16
+
17
+ /**
18
+ * Subscribe to state changes
19
+ * @param callback Function to call when state changes
20
+ * @returns Unsubscribe function
21
+ */
22
+ subscribe(callback: StateChangeCallback): () => void {
23
+ this.subscribers.push(callback);
24
+
25
+ // Return unsubscribe function that removes only the first occurrence
26
+ return () => {
27
+ const index = this.subscribers.indexOf(callback);
28
+ if (index > -1) {
29
+ this.subscribers.splice(index, 1);
30
+ }
31
+ };
32
+ }
33
+
34
+ /**
35
+ * Notify all subscribers of state changes
36
+ * This triggers React re-renders
37
+ */
38
+ protected notify(): void {
39
+ this.subscribers.forEach(callback => {
40
+ try {
41
+ callback();
42
+ } catch (error) {
43
+ console.error('[BaseService] Error in subscriber callback:', error);
44
+ }
45
+ });
46
+ }
47
+
48
+ /**
49
+ * Initialize the service
50
+ * Override in subclasses to implement initialization logic
51
+ */
52
+ async initialize(): Promise<void> {
53
+ if (this.isInitialized) {
54
+ return;
55
+ }
56
+
57
+ await this.doInitialize();
58
+ this.isInitialized = true;
59
+ }
60
+
61
+ /**
62
+ * Cleanup the service
63
+ * Override in subclasses to implement cleanup logic
64
+ */
65
+ cleanup(): void {
66
+ this.subscribers = [];
67
+ this.doCleanup();
68
+ this.isInitialized = false;
69
+ }
70
+
71
+ /**
72
+ * Check if service is initialized
73
+ */
74
+ protected getInitialized(): boolean {
75
+ return this.isInitialized;
76
+ }
77
+
78
+ /**
79
+ * Override in subclasses to implement initialization logic
80
+ */
81
+ protected abstract doInitialize(): Promise<void>;
82
+
83
+ /**
84
+ * Override in subclasses to implement cleanup logic
85
+ */
86
+ protected abstract doCleanup(): void;
87
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @file Authentication Service Interface
3
+ * @package @jmruthers/pace-core
4
+ * @module Services/Interfaces
5
+ * @since 0.1.0
6
+ *
7
+ * Interface for authentication service operations.
8
+ * Defines the contract for authentication-related functionality.
9
+ */
10
+
11
+ import { type SupabaseClient, type User, type Session, AuthError } from '@supabase/supabase-js';
12
+
13
+ export interface AuthResult {
14
+ user: User | null;
15
+ session: Session | null;
16
+ error: AuthError | null;
17
+ }
18
+
19
+ export interface IAuthService {
20
+ // Auth state
21
+ getUser(): User | null;
22
+ getSession(): Session | null;
23
+ isAuthenticated(): boolean;
24
+ isLoading(): boolean;
25
+ getError(): AuthError | null;
26
+ getSupabaseClient(): SupabaseClient | null;
27
+
28
+ // Auth methods
29
+ signIn(email: string, password?: string): Promise<AuthResult>;
30
+ signUp(email: string, password: string): Promise<AuthResult>;
31
+ signOut(): Promise<AuthResult>;
32
+ resetPassword(email: string): Promise<AuthResult>;
33
+ updatePassword(password: string): Promise<AuthResult>;
34
+ refreshSession(): Promise<AuthResult>;
35
+
36
+ // Lifecycle
37
+ initialize(): Promise<void>;
38
+ cleanup(): void;
39
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @file Event Service Interface
3
+ * @package @jmruthers/pace-core
4
+ * @module Services/Interfaces
5
+ * @since 0.1.0
6
+ *
7
+ * Interface for event service operations.
8
+ * Defines the contract for event management functionality.
9
+ */
10
+
11
+ import { Event } from '../../types/unified';
12
+
13
+ export interface IEventService {
14
+ // Event state
15
+ getEvents(): Event[];
16
+ getSelectedEvent(): Event | null;
17
+ isLoading(): boolean;
18
+ getError(): Error | null;
19
+
20
+ // Event methods
21
+ setSelectedEvent(event: Event | null): void;
22
+ refreshEvents(): Promise<void>;
23
+ loadPersistedEvent(events: Event[]): Promise<boolean>;
24
+ persistEventSelection(eventId: string): void;
25
+ autoSelectNextEvent(events: Event[]): void;
26
+
27
+ // Lifecycle
28
+ initialize(): Promise<void>;
29
+ cleanup(): void;
30
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @file Inactivity Service Interface
3
+ * @package @jmruthers/pace-core
4
+ * @module Services/Interfaces
5
+ * @since 0.1.0
6
+ *
7
+ * Interface for inactivity service operations.
8
+ * Defines the contract for inactivity tracking functionality.
9
+ */
10
+
11
+ export interface IInactivityService {
12
+ // Inactivity state
13
+ isIdle(): boolean;
14
+ getTimeRemaining(): number;
15
+ isWarningShown(): boolean;
16
+ isTracking(): boolean;
17
+ getShowInactivityWarning(): boolean;
18
+ getInactivityTimeRemaining(): number;
19
+
20
+ // Inactivity methods
21
+ resetActivity(): void;
22
+ startTracking(): void;
23
+ stopTracking(): void;
24
+ handleIdleLogout(): Promise<void>;
25
+ handleStaySignedIn(): void;
26
+ handleSignOutNow(): Promise<void>;
27
+
28
+ // Lifecycle
29
+ initialize(): Promise<void>;
30
+ cleanup(): void;
31
+ }