@jmruthers/pace-core 0.5.68 → 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 (375) hide show
  1. package/dist/{DataTable-4IUY7BXB.js → DataTable-MPBSXUC6.js} +5 -6
  2. package/dist/{PublicLoadingSpinner-DdKXTkCZ.d.ts → PublicLoadingSpinner-BOdyU3u-.d.ts} +1 -1
  3. package/dist/{chunk-PXWEDX7Y.js → chunk-2ARQW6VX.js} +3 -3
  4. package/dist/{chunk-MOJXHWDE.js → chunk-6JILXFEA.js} +335 -5
  5. package/dist/chunk-6JILXFEA.js.map +1 -0
  6. package/dist/{chunk-D7ARGIA3.js → chunk-6RBH67W7.js} +23 -6
  7. package/dist/chunk-6RBH67W7.js.map +1 -0
  8. package/dist/{chunk-ZMS23NS5.js → chunk-FJTAWPAQ.js} +3 -5
  9. package/dist/{chunk-ZMS23NS5.js.map → chunk-FJTAWPAQ.js.map} +1 -1
  10. package/dist/{chunk-OPCWH3A4.js → chunk-NO5QHMDX.js} +7 -6
  11. package/dist/chunk-NO5QHMDX.js.map +1 -0
  12. package/dist/{chunk-ZPK5656W.js → chunk-O3NWNXDY.js} +4 -5
  13. package/dist/chunk-O3NWNXDY.js.map +1 -0
  14. package/dist/{chunk-UYA6U6H7.js → chunk-Q2UP3ZWQ.js} +4 -4
  15. package/dist/{chunk-KRCRNXPD.js → chunk-RVYGJPOD.js} +79 -18
  16. package/dist/chunk-RVYGJPOD.js.map +1 -0
  17. package/dist/{chunk-NN45OBIS.js → chunk-UCMHBF7Y.js} +3 -5
  18. package/dist/{chunk-NN45OBIS.js.map → chunk-UCMHBF7Y.js.map} +1 -1
  19. package/dist/{chunk-ZPG4XPV5.js → chunk-V3QO3LL7.js} +5 -7
  20. package/dist/chunk-V3QO3LL7.js.map +1 -0
  21. package/dist/{chunk-U6GPOF6J.js → chunk-ZXJGZLLO.js} +17 -17
  22. package/dist/{chunk-U6GPOF6J.js.map → chunk-ZXJGZLLO.js.map} +1 -1
  23. package/dist/components.d.ts +1 -1
  24. package/dist/components.js +8 -9
  25. package/dist/components.js.map +1 -1
  26. package/dist/hooks.d.ts +1 -1
  27. package/dist/hooks.js +9 -6
  28. package/dist/hooks.js.map +1 -1
  29. package/dist/index.d.ts +3 -3
  30. package/dist/index.js +16 -16
  31. package/dist/index.js.map +1 -1
  32. package/dist/providers.js +5 -7
  33. package/dist/rbac/index.js +5 -6
  34. package/dist/{usePublicRouteParams-CdoFxnJK.d.ts → usePublicRouteParams-Ua1Vz-HG.d.ts} +35 -1
  35. package/dist/utils.d.ts +4 -1
  36. package/dist/utils.js +3 -3
  37. package/docs/DOCUMENTATION_CHECKLIST.md +281 -0
  38. package/docs/README.md +22 -10
  39. package/docs/api/classes/ColumnFactory.md +1 -1
  40. package/docs/api/classes/ErrorBoundary.md +1 -1
  41. package/docs/api/classes/InvalidScopeError.md +1 -1
  42. package/docs/api/classes/MissingUserContextError.md +1 -1
  43. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  44. package/docs/api/classes/PermissionDeniedError.md +1 -1
  45. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  46. package/docs/api/classes/RBACAuditManager.md +1 -1
  47. package/docs/api/classes/RBACCache.md +1 -1
  48. package/docs/api/classes/RBACEngine.md +1 -1
  49. package/docs/api/classes/RBACError.md +1 -1
  50. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  51. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  52. package/docs/api/classes/StorageUtils.md +1 -1
  53. package/docs/api/interfaces/AggregateConfig.md +1 -1
  54. package/docs/api/interfaces/ButtonProps.md +1 -1
  55. package/docs/api/interfaces/CardProps.md +1 -1
  56. package/docs/api/interfaces/ColorPalette.md +1 -1
  57. package/docs/api/interfaces/ColorShade.md +1 -1
  58. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  59. package/docs/api/interfaces/DataTableAction.md +1 -1
  60. package/docs/api/interfaces/DataTableColumn.md +1 -1
  61. package/docs/api/interfaces/DataTableProps.md +1 -1
  62. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  63. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  64. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  65. package/docs/api/interfaces/EventContextType.md +1 -1
  66. package/docs/api/interfaces/EventLogoProps.md +1 -1
  67. package/docs/api/interfaces/EventProviderProps.md +1 -1
  68. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  69. package/docs/api/interfaces/FileUploadProps.md +1 -1
  70. package/docs/api/interfaces/FooterProps.md +1 -1
  71. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  72. package/docs/api/interfaces/InputProps.md +1 -1
  73. package/docs/api/interfaces/LabelProps.md +1 -1
  74. package/docs/api/interfaces/LoginFormProps.md +1 -1
  75. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  76. package/docs/api/interfaces/NavigationContextType.md +1 -1
  77. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  78. package/docs/api/interfaces/NavigationItem.md +1 -1
  79. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  80. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  81. package/docs/api/interfaces/Organisation.md +1 -1
  82. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  83. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  84. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  85. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  86. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  87. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  88. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  89. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  90. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  91. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  92. package/docs/api/interfaces/PaletteData.md +1 -1
  93. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  94. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  95. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  96. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  97. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  98. package/docs/api/interfaces/PublicPageHeaderProps.md +2 -2
  99. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  100. package/docs/api/interfaces/RBACConfig.md +1 -1
  101. package/docs/api/interfaces/RBACContextType.md +1 -1
  102. package/docs/api/interfaces/RBACLogger.md +1 -1
  103. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  104. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  105. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  106. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  107. package/docs/api/interfaces/RouteConfig.md +1 -1
  108. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  109. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  110. package/docs/api/interfaces/StorageConfig.md +1 -1
  111. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  112. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  113. package/docs/api/interfaces/StorageListOptions.md +1 -1
  114. package/docs/api/interfaces/StorageListResult.md +1 -1
  115. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  116. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  117. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  118. package/docs/api/interfaces/StyleImport.md +1 -1
  119. package/docs/api/interfaces/SwitchProps.md +1 -1
  120. package/docs/api/interfaces/ToastActionElement.md +1 -1
  121. package/docs/api/interfaces/ToastProps.md +1 -1
  122. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  123. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  124. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  125. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  126. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  127. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  128. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  129. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  130. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  131. package/docs/api/interfaces/UserEventAccess.md +1 -1
  132. package/docs/api/interfaces/UserMenuProps.md +1 -1
  133. package/docs/api/interfaces/UserProfile.md +1 -1
  134. package/docs/api/modules.md +39 -14
  135. package/docs/architecture/services.md +374 -0
  136. package/docs/best-practices/README.md +1 -1
  137. package/docs/best-practices/testing.md +1 -1
  138. package/docs/breaking-changes.md +182 -0
  139. package/docs/common-patterns.md +445 -0
  140. package/docs/core-concepts/authentication.md +26 -11
  141. package/docs/core-concepts/events.md +2 -0
  142. package/docs/core-concepts/organisations.md +2 -0
  143. package/docs/core-concepts/permissions.md +2 -0
  144. package/docs/{INDEX.md → documentation-index.md} +26 -38
  145. package/docs/faq.md +286 -0
  146. package/docs/{FILE_REFERENCE_SYSTEM.md → file-reference-system.md} +1 -1
  147. package/docs/getting-started/installation-guide.md +284 -0
  148. package/docs/getting-started/quick-start.md +8 -1
  149. package/docs/implementation-guides/app-layout.md +3 -1
  150. package/docs/implementation-guides/data-tables.md +2 -0
  151. package/docs/implementation-guides/dynamic-colors.md +47 -2
  152. package/docs/implementation-guides/event-theming-summary.md +220 -0
  153. package/docs/implementation-guides/forms.md +9 -7
  154. package/docs/implementation-guides/navigation.md +2 -0
  155. package/docs/migration/service-architecture.md +351 -0
  156. package/docs/rbac/README-rbac-rls-integration.md +2 -2
  157. package/docs/rbac/README.md +1 -1
  158. package/docs/rbac/examples/rbac-rls-integration-example.md +3 -3
  159. package/docs/rbac/quick-start.md +2 -0
  160. package/docs/rbac/rbac-rls-integration.md +2 -2
  161. package/docs/style-guide.md +136 -1
  162. package/docs/testing/README.md +1 -1
  163. package/docs/troubleshooting/authentication-issues.md +334 -0
  164. package/docs/troubleshooting/common-issues.md +2 -0
  165. package/docs/troubleshooting/styling-issues.md +199 -144
  166. package/docs/usage.md +23 -2
  167. package/package.json +1 -1
  168. package/src/__tests__/{TESTING_GUIDELINES.md → TEST_GUIDE_CURSOR.md} +20 -0
  169. package/src/__tests__/TEST_GUIDE_HUMAN.md +103 -0
  170. package/src/__tests__/fixtures/test-data.ts +90 -0
  171. package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +260 -0
  172. package/src/__tests__/helpers/__tests__/optimized-test-setup.test.ts +224 -0
  173. package/src/__tests__/helpers/__tests__/supabaseMock.test.ts +273 -0
  174. package/src/__tests__/helpers/__tests__/test-providers.test.tsx +98 -0
  175. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +436 -0
  176. package/src/__tests__/helpers/__tests__/timer-utils.test.ts +371 -0
  177. package/src/__tests__/helpers/component-test-utils.tsx +14 -4
  178. package/src/__tests__/helpers/optimized-test-setup.ts +68 -0
  179. package/src/__tests__/helpers/test-providers.tsx +329 -0
  180. package/src/__tests__/helpers/test-utils.tsx +91 -45
  181. package/src/__tests__/helpers/timer-utils.ts +71 -0
  182. package/src/__tests__/hooks/usePermissions.test.ts +1 -5
  183. package/src/__tests__/integration/UserProfile.test.tsx +1 -5
  184. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +42 -12
  185. package/src/__tests__/setup.ts +34 -28
  186. package/src/components/Alert/Alert.test.tsx +1 -5
  187. package/src/components/Avatar/Avatar.test.tsx +1 -5
  188. package/src/components/Button/Button.test.tsx +4 -20
  189. package/src/components/Card/Card.test.tsx +1 -5
  190. package/src/components/Checkbox/Checkbox.test.tsx +1 -5
  191. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -5
  192. package/src/components/DataTable/__tests__/DataTable.test.tsx +45 -49
  193. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +1 -5
  194. package/src/components/DataTable/__tests__/styles.test.ts +382 -0
  195. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +409 -0
  196. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +634 -0
  197. package/src/components/DataTable/core/__tests__/DataManager.test.ts +519 -0
  198. package/src/components/DataTable/core/__tests__/StateManager.test.ts +714 -0
  199. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +592 -0
  200. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +354 -0
  201. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +539 -0
  202. package/src/components/Dialog/examples/__tests__/SmartDialogExample.unit.test.tsx +1 -5
  203. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +1 -8
  204. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +34 -38
  205. package/src/components/Footer/Footer.test.tsx +1 -5
  206. package/src/components/Form/Form.test.tsx +22 -35
  207. package/src/components/Header/Header.test.tsx +1 -9
  208. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +1 -5
  209. package/src/components/Input/Input.test.tsx +2 -10
  210. package/src/components/LoginForm/LoginForm.test.tsx +1 -5
  211. package/src/components/NavigationMenu/NavigationMenu.test.tsx +24 -24
  212. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.accessibility.test.tsx +1 -6
  213. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +6 -16
  214. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +1 -5
  215. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.rbac.test.tsx +1 -5
  216. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +1 -7
  217. package/src/components/PasswordReset/PasswordChangeForm.test.tsx +1 -9
  218. package/src/components/PasswordReset/PasswordResetForm.test.tsx +1 -9
  219. package/src/components/PublicLayout/PublicErrorBoundary.tsx +4 -5
  220. package/src/components/PublicLayout/PublicPageHeader.tsx +13 -9
  221. package/src/components/PublicLayout/__tests__/EventLogo.test.tsx +666 -0
  222. package/src/components/PublicLayout/__tests__/PublicErrorBoundary.test.tsx +457 -0
  223. package/src/components/PublicLayout/__tests__/PublicLoadingSpinner.test.tsx +393 -0
  224. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +351 -0
  225. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +374 -0
  226. package/src/components/PublicLayout/__tests__/PublicPageLayout.test.tsx +388 -0
  227. package/src/components/Select/Select.bug-test.tsx +69 -0
  228. package/src/components/Select/Select.refactored.tsx +497 -0
  229. package/src/components/Select/Select.test.tsx +42 -49
  230. package/src/components/Select/Select.tsx +5 -2
  231. package/src/components/Select/hooks.ts +254 -0
  232. package/src/components/Switch/Switch.test.tsx +1 -5
  233. package/src/components/Table/__tests__/Table.test.tsx +775 -0
  234. package/src/components/Toast/Toast.test.tsx +15 -8
  235. package/src/components/Tooltip/Tooltip.test.tsx +1 -5
  236. package/src/components/UserMenu/UserMenu.test.tsx +3 -15
  237. package/src/components/__tests__/FileDisplay.test.tsx +575 -0
  238. package/src/components/__tests__/FileUpload.test.tsx +446 -0
  239. package/src/components/__tests__/SuperAdminGuard.test.tsx +422 -354
  240. package/src/hooks/__tests__/ServiceHooks.test.tsx +613 -0
  241. package/src/hooks/__tests__/hooks.integration.test.tsx +1 -10
  242. package/src/hooks/__tests__/useApiFetch.unit.test.ts +10 -14
  243. package/src/hooks/__tests__/useAppConfig.unit.test.ts +307 -0
  244. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +1 -6
  245. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +1 -5
  246. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +6 -9
  247. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +321 -0
  248. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +583 -0
  249. package/src/hooks/__tests__/usePublicEventLogo.unit.test.ts +640 -0
  250. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +435 -0
  251. package/src/hooks/__tests__/useRBAC.unit.test.ts +10 -10
  252. package/src/hooks/__tests__/useStorage.unit.test.ts +751 -0
  253. package/src/hooks/index.ts +3 -0
  254. package/src/hooks/public/usePublicEvent.ts +30 -9
  255. package/src/hooks/public/usePublicRouteParams.ts +13 -3
  256. package/src/hooks/services/useAuth.ts +50 -0
  257. package/src/hooks/services/useAuthService.ts +30 -0
  258. package/src/hooks/services/useCurrentEvent.ts +36 -0
  259. package/src/hooks/services/useCurrentOrganisation.ts +52 -0
  260. package/src/hooks/services/useEventService.ts +30 -0
  261. package/src/hooks/services/useInactivityService.ts +30 -0
  262. package/src/hooks/services/useOrganisationService.ts +30 -0
  263. package/src/hooks/services/usePermissions.ts +70 -0
  264. package/src/hooks/services/useRBACService.ts +30 -0
  265. package/src/hooks/useCounter.test.ts +1 -5
  266. package/src/hooks/useEventTheme.ts +86 -0
  267. package/src/hooks/useOrganisationPermissions.test.ts +2 -5
  268. package/src/hooks/useOrganisationSecurity.test.ts +1 -5
  269. package/src/hooks/usePermissionCache.test.ts +1 -5
  270. package/src/hooks/usePermissionCheck.ts +150 -0
  271. package/src/hooks/useSecureDataAccess.test.ts +1 -5
  272. package/src/index.ts +1 -0
  273. package/src/providers/OrganisationProvider.test.tsx +1 -5
  274. package/src/providers/OrganisationProvider.tsx +56 -4
  275. package/src/providers/UnifiedAuthProvider.test.tsx +1 -5
  276. package/src/providers/__tests__/AuthProvider.test.tsx +105 -439
  277. package/src/providers/__tests__/AuthProvider.test.tsx.backup +771 -0
  278. package/src/providers/__tests__/EventProvider.test.tsx +211 -110
  279. package/src/providers/__tests__/EventProvider.test.tsx.backup +824 -0
  280. package/src/providers/__tests__/InactivityProvider.test.tsx +1 -5
  281. package/src/providers/__tests__/OrganisationProvider.test.tsx +97 -261
  282. package/src/providers/__tests__/OrganisationProvider.test.tsx.backup +820 -0
  283. package/src/providers/__tests__/ServiceProviders.test.tsx +477 -0
  284. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +72 -504
  285. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup +911 -0
  286. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx.backup2 +166 -0
  287. package/src/providers/services/AuthServiceProvider.tsx +65 -0
  288. package/src/providers/services/EventServiceProvider.tsx +83 -0
  289. package/src/providers/services/InactivityServiceProvider.tsx +83 -0
  290. package/src/providers/services/OrganisationServiceProvider.tsx +77 -0
  291. package/src/providers/services/RBACServiceProvider.tsx +79 -0
  292. package/src/providers/services/UnifiedAuthProvider.tsx +368 -0
  293. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +210 -0
  294. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +269 -0
  295. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +892 -0
  296. package/src/rbac/__tests__/engine.comprehensive.test.ts +954 -0
  297. package/src/rbac/__tests__/integration.authflow.test.tsx +1 -5
  298. package/src/rbac/__tests__/integration.navigation.test.tsx +1 -4
  299. package/src/rbac/__tests__/rbac-core.test.tsx +2 -7
  300. package/src/rbac/__tests__/rbac-functions.test.ts +1 -9
  301. package/src/rbac/__tests__/rbac-integration.test.ts +1 -9
  302. package/src/rbac/api.test.ts +1 -9
  303. package/src/rbac/cache.test.ts +10 -8
  304. package/src/rbac/cli/__tests__/policy-manager.test.ts +339 -0
  305. package/src/rbac/components/EnhancedNavigationMenu.test.tsx +1 -5
  306. package/src/rbac/components/NavigationProvider.test.tsx +1 -5
  307. package/src/rbac/components/PagePermissionProvider.test.tsx +1 -5
  308. package/src/rbac/components/SecureDataProvider.test.tsx +1 -5
  309. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +25 -29
  310. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +27 -30
  311. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +23 -27
  312. package/src/rbac/components/__tests__/RoleBasedRouter.test.tsx +18 -22
  313. package/src/rbac/config.test.ts +1 -5
  314. package/src/rbac/hooks/useCan.test.ts +262 -9
  315. package/src/rbac/hooks/usePermissions.test.ts +246 -6
  316. package/src/rbac/hooks/useRBAC.simple.test.ts +1 -5
  317. package/src/rbac/hooks/useRBAC.test.ts +472 -198
  318. package/src/rbac/providers/__tests__/RBACProvider.test.tsx +1 -9
  319. package/src/services/AuthService.ts +416 -0
  320. package/src/services/EventService.ts +366 -0
  321. package/src/services/InactivityService.ts +388 -0
  322. package/src/services/OrganisationService.ts +592 -0
  323. package/src/services/RBACService.ts +522 -0
  324. package/src/services/__tests__/AuthService.test.ts +356 -0
  325. package/src/services/__tests__/BaseService.test.ts +314 -0
  326. package/src/services/__tests__/EventService.test.ts +489 -0
  327. package/src/services/__tests__/InactivityService.test.ts +403 -0
  328. package/src/services/__tests__/OrganisationService.test.ts +660 -0
  329. package/src/services/__tests__/RBACService.test.ts +492 -0
  330. package/src/services/base/BaseService.ts +87 -0
  331. package/src/services/interfaces/IAuthService.ts +39 -0
  332. package/src/services/interfaces/IEventService.ts +30 -0
  333. package/src/services/interfaces/IInactivityService.ts +31 -0
  334. package/src/services/interfaces/IOrganisationService.ts +41 -0
  335. package/src/services/interfaces/IRBACService.ts +62 -0
  336. package/src/theming/__tests__/runtime.test.ts +540 -0
  337. package/src/types/__tests__/file-reference.test.ts +447 -0
  338. package/src/types/__tests__/organisation.test.ts +1133 -0
  339. package/src/types/__tests__/theme.test.ts +830 -0
  340. package/src/types/__tests__/type-validation.test.ts +527 -0
  341. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +1 -5
  342. package/src/utils/__tests__/debugLogger.test.ts +417 -0
  343. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -6
  344. package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -5
  345. package/src/utils/__tests__/lazyLoad.unit.test.tsx +35 -35
  346. package/src/utils/__tests__/organisationContext.unit.test.ts +1 -5
  347. package/src/utils/__tests__/performanceBudgets.unit.test.ts +5 -11
  348. package/src/utils/__tests__/secureErrors.unit.test.ts +1 -6
  349. package/src/utils/__tests__/secureStorage.unit.test.ts +1 -5
  350. package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -5
  351. package/src/utils/__tests__/sessionTracking.unit.test.ts +1 -5
  352. package/src/utils/appIdResolver.test.ts +6 -10
  353. package/src/utils/appNameResolver.simple.test.ts +142 -0
  354. package/src/utils/appNameResolver.test.ts +31 -458
  355. package/src/utils/appNameResolver.test.ts.backup +494 -0
  356. package/src/utils/debugLogger.ts +26 -5
  357. package/src/utils/formatDate.test.ts +1 -5
  358. package/src/utils/organisationContext.test.ts +1 -5
  359. package/src/utils/performanceBudgets.ts +3 -4
  360. package/src/utils/secureDataAccess.test.ts +1 -5
  361. package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -5
  362. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +1 -5
  363. package/dist/chunk-D7ARGIA3.js.map +0 -1
  364. package/dist/chunk-IPCH4YPT.js +0 -315
  365. package/dist/chunk-IPCH4YPT.js.map +0 -1
  366. package/dist/chunk-KRCRNXPD.js.map +0 -1
  367. package/dist/chunk-MOJXHWDE.js.map +0 -1
  368. package/dist/chunk-OPCWH3A4.js.map +0 -1
  369. package/dist/chunk-ZPG4XPV5.js.map +0 -1
  370. package/dist/chunk-ZPK5656W.js.map +0 -1
  371. package/docs/getting-started/installation.md +0 -269
  372. package/src/__tests__/REBUILD_PLAN.md +0 -223
  373. /package/dist/{DataTable-4IUY7BXB.js.map → DataTable-MPBSXUC6.js.map} +0 -0
  374. /package/dist/{chunk-PXWEDX7Y.js.map → chunk-2ARQW6VX.js.map} +0 -0
  375. /package/dist/{chunk-UYA6U6H7.js.map → chunk-Q2UP3ZWQ.js.map} +0 -0
@@ -0,0 +1,494 @@
1
+ /**
2
+ * @file App Name Resolver Tests
3
+ * @package @jmruthers/pace-core
4
+ * @module Utils/AppNameResolver
5
+ * @since 1.0.0
6
+ *
7
+ * Comprehensive tests for app name resolution utility functions covering all critical functionality.
8
+ */
9
+
10
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
11
+ import {
12
+ getAppNameFromPackageJson,
13
+ getAppNameFromBuildTime,
14
+ getAppNameFromGlobal,
15
+ getAppNameFromEnvironment,
16
+ getCurrentAppName,
17
+ setRBACAppName
18
+ } from './appNameResolver';
19
+
20
+ // Mock Node.js modules
21
+ const mockFs = {
22
+ existsSync: vi.fn(),
23
+ readFileSync: vi.fn()
24
+ };
25
+
26
+ const mockPath = {
27
+ join: vi.fn()
28
+ };
29
+
30
+ vi.mock('fs', () => mockFs);
31
+ vi.mock('path', () => mockPath);
32
+
33
+ describe('App Name Resolver', () => {
34
+ beforeEach(() => {
35
+ vi.clearAllMocks();
36
+ // Reset global variables
37
+ delete (globalThis as any).__RBAC_APP_NAME__;
38
+ delete (globalThis as any).RBAC_APP_NAME;
39
+ delete (globalThis as any).process;
40
+ });
41
+
42
+ afterEach(() => {
43
+ vi.restoreAllMocks();
44
+ });
45
+
46
+ describe('getAppNameFromPackageJson', () => {
47
+ it('reads app name from package.json in Node.js environment', () => {
48
+ // Mock Node.js environment
49
+ Object.defineProperty(global, 'window', { value: undefined, writable: true });
50
+ Object.defineProperty(global, 'require', { value: vi.fn(), writable: true });
51
+
52
+ mockPath.join.mockReturnValue('/path/to/package.json');
53
+ mockFs.existsSync.mockReturnValue(true);
54
+ mockFs.readFileSync.mockReturnValue(JSON.stringify({ name: '@org/my-app' }));
55
+
56
+ const result = getAppNameFromPackageJson();
57
+
58
+ expect(result).toBe('my-app');
59
+ expect(mockPath.join).toHaveBeenCalledWith(expect.any(String), 'package.json');
60
+ expect(mockFs.existsSync).toHaveBeenCalledWith('/path/to/package.json');
61
+ expect(mockFs.readFileSync).toHaveBeenCalledWith('/path/to/package.json', 'utf8');
62
+ });
63
+
64
+ it('handles scoped packages correctly', () => {
65
+ Object.defineProperty(global, 'window', { value: undefined, writable: true });
66
+ Object.defineProperty(global, 'require', { value: vi.fn(), writable: true });
67
+
68
+ mockPath.join.mockReturnValue('/path/to/package.json');
69
+ mockFs.existsSync.mockReturnValue(true);
70
+ mockFs.readFileSync.mockReturnValue(JSON.stringify({ name: '@myorg/super-app' }));
71
+
72
+ const result = getAppNameFromPackageJson();
73
+
74
+ expect(result).toBe('super-app');
75
+ });
76
+
77
+ it('handles non-scoped packages correctly', () => {
78
+ Object.defineProperty(global, 'window', { value: undefined, writable: true });
79
+ Object.defineProperty(global, 'require', { value: vi.fn(), writable: true });
80
+
81
+ mockPath.join.mockReturnValue('/path/to/package.json');
82
+ mockFs.existsSync.mockReturnValue(true);
83
+ mockFs.readFileSync.mockReturnValue(JSON.stringify({ name: 'my-app' }));
84
+
85
+ const result = getAppNameFromPackageJson();
86
+
87
+ expect(result).toBe('my-app');
88
+ });
89
+
90
+ it('tries multiple package.json paths', () => {
91
+ Object.defineProperty(global, 'window', { value: undefined, writable: true });
92
+ Object.defineProperty(global, 'require', { value: vi.fn(), writable: true });
93
+
94
+ mockPath.join
95
+ .mockReturnValueOnce('/path/to/package.json')
96
+ .mockReturnValueOnce('/path/to/../../package.json')
97
+ .mockReturnValueOnce('/path/to/../../../package.json');
98
+
99
+ mockFs.existsSync
100
+ .mockReturnValueOnce(false)
101
+ .mockReturnValueOnce(false)
102
+ .mockReturnValueOnce(true);
103
+
104
+ mockFs.readFileSync.mockReturnValue(JSON.stringify({ name: 'my-app' }));
105
+
106
+ const result = getAppNameFromPackageJson();
107
+
108
+ expect(result).toBe('my-app');
109
+ expect(mockPath.join).toHaveBeenCalledTimes(3);
110
+ expect(mockFs.existsSync).toHaveBeenCalledTimes(3);
111
+ });
112
+
113
+ it('returns null in browser environment', () => {
114
+ Object.defineProperty(global, 'window', { value: {}, writable: true });
115
+
116
+ const result = getAppNameFromPackageJson();
117
+
118
+ expect(result).toBeNull();
119
+ });
120
+
121
+ it('handles missing package.json gracefully', () => {
122
+ Object.defineProperty(global, 'window', { value: undefined, writable: true });
123
+ Object.defineProperty(global, 'require', { value: vi.fn(), writable: true });
124
+
125
+ mockPath.join.mockReturnValue('/path/to/package.json');
126
+ mockFs.existsSync.mockReturnValue(false);
127
+
128
+ const result = getAppNameFromPackageJson();
129
+
130
+ expect(result).toBeNull();
131
+ });
132
+
133
+ it('handles invalid JSON gracefully', () => {
134
+ Object.defineProperty(global, 'window', { value: undefined, writable: true });
135
+ Object.defineProperty(global, 'require', { value: vi.fn(), writable: true });
136
+
137
+ mockPath.join.mockReturnValue('/path/to/package.json');
138
+ mockFs.existsSync.mockReturnValue(true);
139
+ mockFs.readFileSync.mockReturnValue('invalid json');
140
+
141
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
142
+
143
+ const result = getAppNameFromPackageJson();
144
+
145
+ expect(result).toBeNull();
146
+ expect(consoleSpy).toHaveBeenCalledWith(
147
+ '[RBAC] Could not read app name from package.json:',
148
+ expect.any(Error)
149
+ );
150
+
151
+ consoleSpy.mockRestore();
152
+ });
153
+
154
+ it('handles missing name field in package.json', () => {
155
+ Object.defineProperty(global, 'window', { value: undefined, writable: true });
156
+ Object.defineProperty(global, 'require', { value: vi.fn(), writable: true });
157
+
158
+ mockPath.join.mockReturnValue('/path/to/package.json');
159
+ mockFs.existsSync.mockReturnValue(true);
160
+ mockFs.readFileSync.mockReturnValue(JSON.stringify({ version: '1.0.0' }));
161
+
162
+ const result = getAppNameFromPackageJson();
163
+
164
+ expect(result).toBeNull();
165
+ });
166
+ });
167
+
168
+ describe('getAppNameFromBuildTime', () => {
169
+ it('reads app name from build-time injected variable', () => {
170
+ (globalThis as any).__RBAC_APP_NAME__ = 'my-app';
171
+
172
+ const result = getAppNameFromBuildTime();
173
+
174
+ expect(result).toBe('my-app');
175
+ });
176
+
177
+ it('trims whitespace from build-time variable', () => {
178
+ (globalThis as any).__RBAC_APP_NAME__ = ' my-app ';
179
+
180
+ const result = getAppNameFromBuildTime();
181
+
182
+ expect(result).toBe('my-app');
183
+ });
184
+
185
+ it('returns null when build-time variable is not set', () => {
186
+ const result = getAppNameFromBuildTime();
187
+
188
+ expect(result).toBeNull();
189
+ });
190
+
191
+ it('returns null when build-time variable is empty', () => {
192
+ (globalThis as any).__RBAC_APP_NAME__ = '';
193
+
194
+ const result = getAppNameFromBuildTime();
195
+
196
+ expect(result).toBeNull();
197
+ });
198
+
199
+ it('handles errors gracefully', () => {
200
+ // Mock globalThis access to throw error
201
+ Object.defineProperty(globalThis, '__RBAC_APP_NAME__', {
202
+ get: () => { throw new Error('Access denied'); }
203
+ });
204
+
205
+ const result = getAppNameFromBuildTime();
206
+
207
+ expect(result).toBeNull();
208
+ });
209
+ });
210
+
211
+ describe('getAppNameFromGlobal', () => {
212
+ it('reads app name from global variable', () => {
213
+ (globalThis as any).RBAC_APP_NAME = 'my-app';
214
+
215
+ const result = getAppNameFromGlobal();
216
+
217
+ expect(result).toBe('my-app');
218
+ });
219
+
220
+ it('trims whitespace from global variable', () => {
221
+ (globalThis as any).RBAC_APP_NAME = ' my-app ';
222
+
223
+ const result = getAppNameFromGlobal();
224
+
225
+ expect(result).toBe('my-app');
226
+ });
227
+
228
+ it('returns null when global variable is not set', () => {
229
+ const result = getAppNameFromGlobal();
230
+
231
+ expect(result).toBeNull();
232
+ });
233
+
234
+ it('returns null when global variable is empty', () => {
235
+ (globalThis as any).RBAC_APP_NAME = '';
236
+
237
+ const result = getAppNameFromGlobal();
238
+
239
+ expect(result).toBeNull();
240
+ });
241
+
242
+ it('handles errors gracefully', () => {
243
+ // Mock globalThis access to throw error
244
+ Object.defineProperty(globalThis, 'RBAC_APP_NAME', {
245
+ get: () => { throw new Error('Access denied'); }
246
+ });
247
+
248
+ const result = getAppNameFromGlobal();
249
+
250
+ expect(result).toBeNull();
251
+ });
252
+ });
253
+
254
+ describe('getAppNameFromEnvironment', () => {
255
+ it('reads app name from environment variable', () => {
256
+ const originalEnv = process.env;
257
+ process.env = { ...originalEnv, RBAC_APP_NAME: 'my-app' };
258
+
259
+ const result = getAppNameFromEnvironment();
260
+
261
+ expect(result).toBe('my-app');
262
+
263
+ process.env = originalEnv;
264
+ });
265
+
266
+ it('trims whitespace from environment variable', () => {
267
+ const originalEnv = process.env;
268
+ process.env = { ...originalEnv, RBAC_APP_NAME: ' my-app ' };
269
+
270
+ const result = getAppNameFromEnvironment();
271
+
272
+ expect(result).toBe('my-app');
273
+
274
+ process.env = originalEnv;
275
+ });
276
+
277
+ it('returns null when environment variable is not set', () => {
278
+ const originalEnv = process.env;
279
+ process.env = { ...originalEnv };
280
+ delete process.env.RBAC_APP_NAME;
281
+
282
+ const result = getAppNameFromEnvironment();
283
+
284
+ expect(result).toBeNull();
285
+
286
+ process.env = originalEnv;
287
+ });
288
+
289
+ it('returns null when environment variable is empty', () => {
290
+ const originalEnv = process.env;
291
+ process.env = { ...originalEnv, RBAC_APP_NAME: '' };
292
+
293
+ const result = getAppNameFromEnvironment();
294
+
295
+ expect(result).toBeNull();
296
+
297
+ process.env = originalEnv;
298
+ });
299
+ });
300
+
301
+ describe('getCurrentAppName', () => {
302
+ it('returns app name from build-time variable (highest priority)', () => {
303
+ (globalThis as any).__RBAC_APP_NAME__ = 'build-time-app';
304
+ (globalThis as any).RBAC_APP_NAME = 'global-app';
305
+
306
+ const originalEnv = process.env;
307
+ process.env = { ...originalEnv, RBAC_APP_NAME: 'env-app' };
308
+
309
+ const result = getCurrentAppName();
310
+
311
+ expect(result).toBe('build-time-app');
312
+
313
+ process.env = originalEnv;
314
+ });
315
+
316
+ it('falls back to global variable when build-time is not available', () => {
317
+ (globalThis as any).RBAC_APP_NAME = 'global-app';
318
+
319
+ const originalEnv = process.env;
320
+ process.env = { ...originalEnv, RBAC_APP_NAME: 'env-app' };
321
+
322
+ const result = getCurrentAppName();
323
+
324
+ expect(result).toBe('global-app');
325
+
326
+ process.env = originalEnv;
327
+ });
328
+
329
+ it('falls back to environment variable when others are not available', () => {
330
+ const originalEnv = process.env;
331
+ process.env = { ...originalEnv, RBAC_APP_NAME: 'env-app' };
332
+
333
+ const result = getCurrentAppName();
334
+
335
+ expect(result).toBe('env-app');
336
+
337
+ process.env = originalEnv;
338
+ });
339
+
340
+ it('falls back to package.json when others are not available', () => {
341
+ Object.defineProperty(global, 'window', { value: undefined, writable: true });
342
+ Object.defineProperty(global, 'require', { value: vi.fn(), writable: true });
343
+
344
+ mockPath.join.mockReturnValue('/path/to/package.json');
345
+ mockFs.existsSync.mockReturnValue(true);
346
+ mockFs.readFileSync.mockReturnValue(JSON.stringify({ name: 'package-app' }));
347
+
348
+ const result = getCurrentAppName();
349
+
350
+ expect(result).toBe('package-app');
351
+ });
352
+
353
+ it('returns fallback when all methods fail', () => {
354
+ const result = getCurrentAppName();
355
+
356
+ expect(result).toBe('pace-core');
357
+ });
358
+ });
359
+
360
+ describe('setRBACAppName', () => {
361
+ it('sets global app name variable', () => {
362
+ setRBACAppName('my-app');
363
+
364
+ expect((globalThis as any).RBAC_APP_NAME).toBe('my-app');
365
+ });
366
+
367
+ it('trims whitespace when setting app name', () => {
368
+ setRBACAppName(' my-app ');
369
+
370
+ expect((globalThis as any).RBAC_APP_NAME).toBe('my-app');
371
+ });
372
+
373
+ it('handles null/undefined app name', () => {
374
+ setRBACAppName(null as any);
375
+ setRBACAppName(undefined as any);
376
+
377
+ expect((globalThis as any).RBAC_APP_NAME).toBeUndefined();
378
+ });
379
+
380
+ it('handles empty app name', () => {
381
+ setRBACAppName('');
382
+
383
+ expect((globalThis as any).RBAC_APP_NAME).toBe('');
384
+ });
385
+ });
386
+
387
+ describe('Integration Tests', () => {
388
+ it('works with real-world scenarios', () => {
389
+ // Test build-time injection
390
+ (globalThis as any).__RBAC_APP_NAME__ = 'production-app';
391
+ expect(getCurrentAppName()).toBe('production-app');
392
+
393
+ // Test global variable fallback
394
+ delete (globalThis as any).__RBAC_APP_NAME__;
395
+ (globalThis as any).RBAC_APP_NAME = 'development-app';
396
+ expect(getCurrentAppName()).toBe('development-app');
397
+
398
+ // Test environment variable fallback
399
+ delete (globalThis as any).RBAC_APP_NAME__;
400
+ const originalEnv = process.env;
401
+ process.env = { ...originalEnv, RBAC_APP_NAME: 'test-app' };
402
+ expect(getCurrentAppName()).toBe('test-app');
403
+
404
+ process.env = originalEnv;
405
+ });
406
+
407
+ it('handles complex app name patterns', () => {
408
+ const appNames = [
409
+ 'my-app',
410
+ 'my_app',
411
+ 'MyApp',
412
+ 'myapp',
413
+ '@org/my-app',
414
+ 'my-app-v2',
415
+ 'my-app@1.0.0'
416
+ ];
417
+
418
+ appNames.forEach(appName => {
419
+ setRBACAppName(appName);
420
+ expect(getCurrentAppName()).toBe(appName);
421
+ });
422
+ });
423
+ });
424
+
425
+ describe('Error Handling', () => {
426
+ it('handles file system errors gracefully', () => {
427
+ Object.defineProperty(global, 'window', { value: undefined, writable: true });
428
+ Object.defineProperty(global, 'require', { value: vi.fn(), writable: true });
429
+
430
+ mockPath.join.mockReturnValue('/path/to/package.json');
431
+ mockFs.existsSync.mockReturnValue(true);
432
+ mockFs.readFileSync.mockImplementation(() => {
433
+ throw new Error('Permission denied');
434
+ });
435
+
436
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
437
+
438
+ const result = getAppNameFromPackageJson();
439
+
440
+ expect(result).toBeNull();
441
+ expect(consoleSpy).toHaveBeenCalledWith(
442
+ '[RBAC] Could not read app name from package.json:',
443
+ expect.any(Error)
444
+ );
445
+
446
+ consoleSpy.mockRestore();
447
+ });
448
+
449
+ it('handles JSON parsing errors gracefully', () => {
450
+ Object.defineProperty(global, 'window', { value: undefined, writable: true });
451
+ Object.defineProperty(global, 'require', { value: vi.fn(), writable: true });
452
+
453
+ mockPath.join.mockReturnValue('/path/to/package.json');
454
+ mockFs.existsSync.mockReturnValue(true);
455
+ mockFs.readFileSync.mockReturnValue('{ "name": "my-app" }'); // Valid JSON but missing closing brace
456
+
457
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
458
+
459
+ const result = getAppNameFromPackageJson();
460
+
461
+ expect(result).toBeNull();
462
+ expect(consoleSpy).toHaveBeenCalledWith(
463
+ '[RBAC] Could not read app name from package.json:',
464
+ expect.any(Error)
465
+ );
466
+
467
+ consoleSpy.mockRestore();
468
+ });
469
+ });
470
+
471
+ describe('Performance', () => {
472
+ it('caches results efficiently', () => {
473
+ const startTime = Date.now();
474
+
475
+ // Call multiple times
476
+ for (let i = 0; i < 1000; i++) {
477
+ getCurrentAppName();
478
+ }
479
+
480
+ const endTime = Date.now();
481
+
482
+ expect(endTime - startTime).toBeLessThan(100); // Should be very fast
483
+ });
484
+
485
+ it('handles large app names efficiently', () => {
486
+ const largeAppName = 'a'.repeat(1000);
487
+ setRBACAppName(largeAppName);
488
+
489
+ const result = getCurrentAppName();
490
+
491
+ expect(result).toBe(largeAppName);
492
+ });
493
+ });
494
+ });
@@ -10,14 +10,23 @@
10
10
  * Only logs in development mode to prevent production console spam
11
11
  */
12
12
  export class DebugLogger {
13
- private static isDevelopment = import.meta.env.MODE === 'development';
13
+ /**
14
+ * Check if we're in development mode
15
+ */
16
+ private static get isDevelopment(): boolean {
17
+ return import.meta.env.MODE === 'development';
18
+ }
14
19
 
15
20
  /**
16
21
  * Log debug information only in development mode
17
22
  */
18
23
  static log(component: string, message: string, ...args: any[]): void {
19
24
  if (this.isDevelopment) {
20
- console.log(`[${component}] ${message}`, ...args);
25
+ try {
26
+ console.log(`[${component}] ${message}`, ...args);
27
+ } catch (e) {
28
+ // Gracefully handle console method errors
29
+ }
21
30
  }
22
31
  }
23
32
 
@@ -25,14 +34,22 @@ export class DebugLogger {
25
34
  * Log error information (always logged)
26
35
  */
27
36
  static error(component: string, message: string, ...args: any[]): void {
28
- console.error(`[${component}] ${message}`, ...args);
37
+ try {
38
+ console.error(`[${component}] ${message}`, ...args);
39
+ } catch (e) {
40
+ // Gracefully handle console method errors
41
+ }
29
42
  }
30
43
 
31
44
  /**
32
45
  * Log warning information (always logged)
33
46
  */
34
47
  static warn(component: string, message: string, ...args: any[]): void {
35
- console.warn(`[${component}] ${message}`, ...args);
48
+ try {
49
+ console.warn(`[${component}] ${message}`, ...args);
50
+ } catch (e) {
51
+ // Gracefully handle console method errors
52
+ }
36
53
  }
37
54
 
38
55
  /**
@@ -40,7 +57,11 @@ export class DebugLogger {
40
57
  */
41
58
  static info(component: string, message: string, ...args: any[]): void {
42
59
  if (this.isDevelopment) {
43
- console.info(`[${component}] ${message}`, ...args);
60
+ try {
61
+ console.info(`[${component}] ${message}`, ...args);
62
+ } catch (e) {
63
+ // Gracefully handle console method errors
64
+ }
44
65
  }
45
66
  }
46
67
  }
@@ -16,11 +16,7 @@ describe('formatDate Utility', () => {
16
16
  originalTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
17
17
  });
18
18
 
19
- afterEach(() => {
20
- vi.restoreAllMocks();
21
- });
22
-
23
- describe('Date Object Input', () => {
19
+ describe('Date Object Input', () => {
24
20
  it('formats a Date object correctly', () => {
25
21
  const date = new Date('2024-01-15T10:30:00.000Z');
26
22
  const result = formatDate(date);
@@ -28,11 +28,7 @@ describe('Organisation Context', () => {
28
28
  mockSupabase = createMockSupabaseClient();
29
29
  });
30
30
 
31
- afterEach(() => {
32
- vi.restoreAllMocks();
33
- });
34
-
35
- describe('setOrganisationContext', () => {
31
+ describe('setOrganisationContext', () => {
36
32
  it('sets organisation context successfully', async () => {
37
33
  mockSupabase.rpc.mockResolvedValue({
38
34
  data: null,
@@ -39,7 +39,7 @@ class PerformanceBudgetMonitor {
39
39
 
40
40
  // In production, this would send to a proper logging service
41
41
  // For now, we'll log to console for testing purposes
42
- if (import.meta.env.MODE === 'development' || import.meta.env.MODE === 'test') {
42
+ if (import.meta.env.MODE === 'development' || import.meta.env.MODE === 'test' || process.env.NODE_ENV === 'test') {
43
43
  console.log('📊 Performance Metric: ' + metric + ' = ' + value, metadata);
44
44
  }
45
45
 
@@ -56,8 +56,7 @@ class PerformanceBudgetMonitor {
56
56
  }
57
57
 
58
58
  setBudget(metric: string, budget: number, threshold: 'error' | 'warning' | 'info' = 'warning'): void {
59
- const actual = this.metrics.get(metric) || 0;
60
- this.budgets.push({ metric, budget, actual, threshold });
59
+ this.budgets.push({ metric, budget, actual: 0, threshold });
61
60
  }
62
61
 
63
62
  checkBudgets(): PerformanceBudget[] {
@@ -72,7 +71,7 @@ class PerformanceBudgetMonitor {
72
71
 
73
72
  // In production, this would send to a proper logging service
74
73
  // For now, we'll log to console for testing purposes
75
- if (import.meta.env.MODE === 'development' || import.meta.env.MODE === 'test') {
74
+ if (import.meta.env.MODE === 'development' || import.meta.env.MODE === 'test' || process.env.NODE_ENV === 'test') {
76
75
  if (budget.threshold === 'error') {
77
76
  console.error('❌ Performance budget exceeded: ' + budget.metric + ' (' + actual + ' > ' + budget.budget + ')');
78
77
  } else if (budget.threshold === 'warning') {
@@ -66,11 +66,7 @@ describe('secureDataAccess', () => {
66
66
  mockSupabaseClient.from = vi.fn().mockReturnValue(mockQueryBuilder);
67
67
  });
68
68
 
69
- afterEach(() => {
70
- vi.restoreAllMocks();
71
- });
72
-
73
- describe('createSecureDataAccess', () => {
69
+ describe('createSecureDataAccess', () => {
74
70
  describe('Regular User (Non-Super Admin)', () => {
75
71
  beforeEach(() => {
76
72
  secureDataAccess = createSecureDataAccess(mockSupabaseClient, mockOrganisationId, false);
@@ -156,11 +156,7 @@ describe('Storage Helpers', () => {
156
156
  });
157
157
 
158
158
  describe('uploadFile', () => {
159
- beforeEach(() => {
160
- vi.clearAllMocks();
161
- });
162
-
163
- it('should upload file successfully', async () => {
159
+ it('should upload file successfully', async () => {
164
160
  const file = createMockFile('test.jpg', 'image/jpeg', 1024);
165
161
  const mockUpload = vi.fn().mockResolvedValue({ data: { path: 'org-123/documents/test.jpg' }, error: null });
166
162
  const mockGetPublicUrl = vi.fn().mockReturnValue({ data: { publicUrl: 'https://example.com/file.jpg' } });
@@ -19,11 +19,7 @@ import {
19
19
  } from '../sqlInjectionProtection';
20
20
 
21
21
  describe('SQL Injection Protection', () => {
22
- beforeEach(() => {
23
- vi.clearAllMocks();
24
- });
25
-
26
- describe('detectSQLInjection', () => {
22
+ describe('detectSQLInjection', () => {
27
23
  it('should detect basic SQL injection patterns', () => {
28
24
  const maliciousInputs = [
29
25
  "'; DROP TABLE users; --",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/debugLogger.ts","../src/utils/cn.ts","../src/utils/organisationContext.ts"],"sourcesContent":["/**\n * @file Debug Logger Utility\n * @package @jmruthers/pace-core\n * @module Utils/DebugLogger\n * @since 0.4.76\n */\n\n/**\n * Debug logger that respects environment settings\n * Only logs in development mode to prevent production console spam\n */\nexport class DebugLogger {\n private static isDevelopment = import.meta.env.MODE === 'development';\n\n /**\n * Log debug information only in development mode\n */\n static log(component: string, message: string, ...args: any[]): void {\n if (this.isDevelopment) {\n console.log(`[${component}] ${message}`, ...args);\n }\n }\n\n /**\n * Log error information (always logged)\n */\n static error(component: string, message: string, ...args: any[]): void {\n console.error(`[${component}] ${message}`, ...args);\n }\n\n /**\n * Log warning information (always logged)\n */\n static warn(component: string, message: string, ...args: any[]): void {\n console.warn(`[${component}] ${message}`, ...args);\n }\n\n /**\n * Log info information only in development mode\n */\n static info(component: string, message: string, ...args: any[]): void {\n if (this.isDevelopment) {\n console.info(`[${component}] ${message}`, ...args);\n }\n }\n}\n","\nimport { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}","/**\n * @file Organisation Context Utility\n * @package @jmruthers/pace-core\n * @module Utils/OrganisationContext\n * @since 0.4.0\n *\n * Utility functions for managing organisation context in database sessions.\n * Provides fallback mechanisms for when database functions are not available.\n */\n\nimport type { SupabaseClient } from '@supabase/supabase-js';\n\n/**\n * Set organisation context in the database session\n * \n * This function attempts to set the organisation context using a database function.\n * If the function is not available, it falls back gracefully without throwing errors.\n * \n * @param supabase - Supabase client instance\n * @param organisationId - The organisation ID to set as context\n * @returns Promise that resolves when context is set (or falls back gracefully)\n */\nexport async function setOrganisationContext(\n supabase: SupabaseClient,\n organisationId: string\n): Promise<void> {\n if (!supabase || !organisationId) {\n // TODO: Replace with proper logging service integration\n return;\n }\n\n try {\n // Try to call the database function to set organisation context\n const { error } = await supabase.rpc('rbac_audit_log', {\n p_event_type: 'organisation_switched',\n p_organisation_id: organisationId,\n p_metadata: { action: 'set_context' }\n });\n\n if (error) {\n // Function might not exist yet - this is expected during migration\n // Silent fail - will fall back to client-side filtering\n // TODO: Replace with proper logging service integration\n } else {\n // TODO: Replace with proper logging service integration\n }\n } catch (error) {\n // Handle any other errors gracefully\n // Silent fail - will fall back to client-side filtering\n // TODO: Replace with proper logging service integration\n }\n}\n\n/**\n * Clear organisation context from the database session\n * \n * @param supabase - Supabase client instance\n * @returns Promise that resolves when context is cleared\n */\nexport async function clearOrganisationContext(\n supabase: SupabaseClient\n): Promise<void> {\n if (!supabase) {\n // TODO: Replace with proper logging service integration\n return;\n }\n\n try {\n const { error } = await supabase.rpc('rbac_audit_log', {\n p_event_type: 'organisation_switched',\n p_metadata: { action: 'clear_context' }\n });\n \n if (error) {\n // Silent fail - function not available\n // TODO: Replace with proper logging service integration\n } else {\n // TODO: Replace with proper logging service integration\n }\n } catch (error) {\n // Silent fail - error occurred\n // TODO: Replace with proper logging service integration\n }\n}\n\n/**\n * Get current organisation context from the database session\n * \n * @param supabase - Supabase client instance\n * @returns Promise that resolves to the current organisation ID or null\n */\nexport async function getOrganisationContext(\n supabase: SupabaseClient\n): Promise<string | null> {\n if (!supabase) {\n // TODO: Replace with proper logging service integration\n return null;\n }\n\n try {\n // For now, return null since we're not using database context\n // This will be replaced with proper context management\n const data = null;\n const error = null;\n \n if (error) {\n // TODO: Replace with proper logging service integration\n return null;\n }\n \n // Validate that data is a string (allow empty strings)\n if (typeof data === 'string') {\n return data;\n }\n \n // Return null for invalid data formats\n return null;\n } catch (error) {\n // TODO: Replace with proper logging service integration\n return null;\n }\n}\n\n/**\n * Check if organisation context functions are available in the database\n * \n * @param supabase - Supabase client instance\n * @returns Promise that resolves to true if functions are available\n */\nexport async function isOrganisationContextAvailable(\n supabase: SupabaseClient\n): Promise<boolean> {\n if (!supabase) {\n return false;\n }\n\n try {\n const { error } = await supabase.rpc('get_organisation_context');\n \n if (error) {\n return false;\n }\n \n return true;\n } catch (error) {\n return false;\n }\n} "],"mappings":";;;;;AAAA,IAWa;AAXb;AAAA;AAAA;AAWO,IAAM,cAAN,MAAkB;AAAA;AAAA;AAAA;AAAA,MAMvB,OAAO,IAAI,WAAmB,YAAoB,MAAmB;AACnE,YAAI,KAAK,eAAe;AACtB,kBAAQ,IAAI,IAAI,SAAS,KAAK,OAAO,IAAI,GAAG,IAAI;AAAA,QAClD;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,OAAO,MAAM,WAAmB,YAAoB,MAAmB;AACrE,gBAAQ,MAAM,IAAI,SAAS,KAAK,OAAO,IAAI,GAAG,IAAI;AAAA,MACpD;AAAA;AAAA;AAAA;AAAA,MAKA,OAAO,KAAK,WAAmB,YAAoB,MAAmB;AACpE,gBAAQ,KAAK,IAAI,SAAS,KAAK,OAAO,IAAI,GAAG,IAAI;AAAA,MACnD;AAAA;AAAA;AAAA;AAAA,MAKA,OAAO,KAAK,WAAmB,YAAoB,MAAmB;AACpE,YAAI,KAAK,eAAe;AACtB,kBAAQ,KAAK,IAAI,SAAS,KAAK,OAAO,IAAI,GAAG,IAAI;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAjCE,IADW,YACI,gBAAgB,YAAY,IAAI,SAAS;AAAA;AAAA;;;ACX1D,SAA0B,YAAY;AACtC,SAAS,eAAe;AAEjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;AANA;AAAA;AAAA;AAAA;AAAA;;;ACsBA,eAAsB,uBACpB,UACA,gBACe;AACf,MAAI,CAAC,YAAY,CAAC,gBAAgB;AAEhC;AAAA,EACF;AAEA,MAAI;AAEF,UAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,kBAAkB;AAAA,MACrD,cAAc;AAAA,MACd,mBAAmB;AAAA,MACnB,YAAY,EAAE,QAAQ,cAAc;AAAA,IACtC,CAAC;AAED,QAAI,OAAO;AAAA,IAIX,OAAO;AAAA,IAEP;AAAA,EACF,SAAS,OAAO;AAAA,EAIhB;AACF;AAQA,eAAsB,yBACpB,UACe;AACf,MAAI,CAAC,UAAU;AAEb;AAAA,EACF;AAEA,MAAI;AACF,UAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,kBAAkB;AAAA,MACrD,cAAc;AAAA,MACd,YAAY,EAAE,QAAQ,gBAAgB;AAAA,IACxC,CAAC;AAED,QAAI,OAAO;AAAA,IAGX,OAAO;AAAA,IAEP;AAAA,EACF,SAAS,OAAO;AAAA,EAGhB;AACF;AAQA,eAAsB,uBACpB,UACwB;AACxB,MAAI,CAAC,UAAU;AAEb,WAAO;AAAA,EACT;AAEA,MAAI;AAGF,UAAM,OAAO;AACb,UAAM,QAAQ;AAEd,QAAI,OAAO;AAET,aAAO;AAAA,IACT;AAGA,QAAI,OAAO,SAAS,UAAU;AAC5B,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,EACT,SAAS,OAAO;AAEd,WAAO;AAAA,EACT;AACF;AAQA,eAAsB,+BACpB,UACkB;AAClB,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,0BAA0B;AAE/D,QAAI,OAAO;AACT,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,WAAO;AAAA,EACT;AACF;AAnJA;AAAA;AAAA;AAAA;AAAA;","names":[]}