@jmruthers/pace-core 0.5.136 → 0.5.139

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 (292) hide show
  1. package/dist/{DataTable-CYOHOX3O.js → DataTable-JXFCA2BJ.js} +10 -9
  2. package/dist/{EventLogo-801uofbR.d.ts → EventLogo-rFL_kRjk.d.ts} +73 -1
  3. package/dist/{UnifiedAuthProvider-5E5TUNMS.js → UnifiedAuthProvider-XIQQ7LVU.js} +4 -5
  4. package/dist/{chunk-YLKIDTUK.js → chunk-22WKWKRX.js} +4 -4
  5. package/dist/{chunk-TVYPTYOY.js → chunk-4C7EXCAR.js} +60 -24
  6. package/dist/chunk-4C7EXCAR.js.map +1 -0
  7. package/dist/{chunk-NOHEVYVX.js → chunk-5JMOHWDI.js} +417 -319
  8. package/dist/chunk-5JMOHWDI.js.map +1 -0
  9. package/dist/{chunk-FHWWBIHA.js → chunk-6DXZ6V5Q.js} +5 -5
  10. package/dist/{chunk-2TWNJ46Y.js → chunk-6LAAY47Q.js} +2 -2
  11. package/dist/{chunk-444EZN6N.js → chunk-7QCC6MCP.js} +88 -1
  12. package/dist/chunk-7QCC6MCP.js.map +1 -0
  13. package/dist/chunk-BJPBT3CU.js +21 -0
  14. package/dist/chunk-BJPBT3CU.js.map +1 -0
  15. package/dist/{chunk-L6PGMCMD.js → chunk-BOOI7GK2.js} +38 -12
  16. package/dist/chunk-BOOI7GK2.js.map +1 -0
  17. package/dist/{chunk-XARJS7CD.js → chunk-INQLMHPF.js} +2 -2
  18. package/dist/chunk-JISYG63F.js +70 -0
  19. package/dist/chunk-JISYG63F.js.map +1 -0
  20. package/dist/{chunk-SL2YQDR6.js → chunk-MA6EPSGZ.js} +2 -2
  21. package/dist/{chunk-5DPZ5EAT.js → chunk-OWAG3GSU.js} +1 -3
  22. package/dist/{chunk-LTV3XIJJ.js → chunk-T6JN6LH6.js} +4 -4
  23. package/dist/{chunk-HJGGOMQ6.js → chunk-TLT2ZR3L.js} +147 -103
  24. package/dist/chunk-TLT2ZR3L.js.map +1 -0
  25. package/dist/{chunk-4MT5BGGL.js → chunk-YCWDTTUK.js} +4 -6
  26. package/dist/{chunk-4MT5BGGL.js.map → chunk-YCWDTTUK.js.map} +1 -1
  27. package/dist/components.d.ts +1 -1
  28. package/dist/components.js +12 -11
  29. package/dist/components.js.map +1 -1
  30. package/dist/hooks.js +8 -9
  31. package/dist/hooks.js.map +1 -1
  32. package/dist/index.d.ts +2 -2
  33. package/dist/index.js +15 -14
  34. package/dist/index.js.map +1 -1
  35. package/dist/providers.js +3 -4
  36. package/dist/rbac/index.js +8 -9
  37. package/dist/schema-DTDZQe2u.d.ts +28 -0
  38. package/dist/types.d.ts +152 -3
  39. package/dist/types.js +51 -16
  40. package/dist/types.js.map +1 -1
  41. package/dist/utils.d.ts +89 -4
  42. package/dist/utils.js +214 -96
  43. package/dist/utils.js.map +1 -1
  44. package/dist/validation.d.ts +1 -343
  45. package/dist/validation.js +3 -100
  46. package/docs/api/classes/ColumnFactory.md +1 -1
  47. package/docs/api/classes/ErrorBoundary.md +1 -1
  48. package/docs/api/classes/InvalidScopeError.md +1 -1
  49. package/docs/api/classes/MissingUserContextError.md +1 -1
  50. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  51. package/docs/api/classes/PermissionDeniedError.md +1 -1
  52. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  53. package/docs/api/classes/RBACAuditManager.md +1 -1
  54. package/docs/api/classes/RBACCache.md +1 -1
  55. package/docs/api/classes/RBACEngine.md +1 -1
  56. package/docs/api/classes/RBACError.md +1 -1
  57. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  58. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  59. package/docs/api/classes/StorageUtils.md +1 -1
  60. package/docs/api/enums/FileCategory.md +1 -1
  61. package/docs/api/interfaces/AggregateConfig.md +1 -1
  62. package/docs/api/interfaces/BadgeProps.md +27 -0
  63. package/docs/api/interfaces/ButtonProps.md +1 -1
  64. package/docs/api/interfaces/CardProps.md +1 -1
  65. package/docs/api/interfaces/ColorPalette.md +1 -1
  66. package/docs/api/interfaces/ColorShade.md +1 -1
  67. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  68. package/docs/api/interfaces/DataRecord.md +1 -1
  69. package/docs/api/interfaces/DataTableAction.md +1 -1
  70. package/docs/api/interfaces/DataTableColumn.md +1 -1
  71. package/docs/api/interfaces/DataTableProps.md +1 -1
  72. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  73. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  74. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  75. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  76. package/docs/api/interfaces/EventLogoProps.md +1 -1
  77. package/docs/api/interfaces/ExportColumn.md +1 -1
  78. package/docs/api/interfaces/ExportOptions.md +1 -1
  79. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  80. package/docs/api/interfaces/FileMetadata.md +1 -1
  81. package/docs/api/interfaces/FileReference.md +1 -1
  82. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  83. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  84. package/docs/api/interfaces/FileUploadProps.md +1 -1
  85. package/docs/api/interfaces/FooterProps.md +1 -1
  86. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  87. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  88. package/docs/api/interfaces/InputProps.md +1 -1
  89. package/docs/api/interfaces/LabelProps.md +1 -1
  90. package/docs/api/interfaces/LoginFormProps.md +1 -1
  91. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  92. package/docs/api/interfaces/NavigationContextType.md +1 -1
  93. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  94. package/docs/api/interfaces/NavigationItem.md +1 -1
  95. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  96. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  97. package/docs/api/interfaces/Organisation.md +1 -1
  98. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  99. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  100. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  101. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  102. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  103. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  104. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  105. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  106. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  107. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  108. package/docs/api/interfaces/PaletteData.md +1 -1
  109. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  110. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  111. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  112. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  113. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  114. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  115. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  116. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  117. package/docs/api/interfaces/RBACConfig.md +1 -1
  118. package/docs/api/interfaces/RBACLogger.md +1 -1
  119. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  120. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  121. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  122. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  123. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  124. package/docs/api/interfaces/RouteConfig.md +1 -1
  125. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  126. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  127. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  128. package/docs/api/interfaces/StorageConfig.md +1 -1
  129. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  130. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  131. package/docs/api/interfaces/StorageListOptions.md +1 -1
  132. package/docs/api/interfaces/StorageListResult.md +1 -1
  133. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  134. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  135. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  136. package/docs/api/interfaces/StyleImport.md +1 -1
  137. package/docs/api/interfaces/SwitchProps.md +1 -1
  138. package/docs/api/interfaces/ToastActionElement.md +1 -1
  139. package/docs/api/interfaces/ToastProps.md +1 -1
  140. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  141. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  142. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  143. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  144. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  145. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  146. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  147. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  148. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  149. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  150. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  151. package/docs/api/interfaces/UserEventAccess.md +1 -1
  152. package/docs/api/interfaces/UserMenuProps.md +1 -1
  153. package/docs/api/interfaces/UserProfile.md +1 -1
  154. package/docs/api/modules.md +84 -15
  155. package/docs/architecture/README.md +0 -1
  156. package/docs/styles/README.md +0 -2
  157. package/examples/RBAC/CompleteRBACExample.tsx +324 -0
  158. package/examples/RBAC/EventBasedApp.tsx +239 -0
  159. package/examples/RBAC/PermissionExample.tsx +151 -0
  160. package/examples/RBAC/index.ts +13 -0
  161. package/examples/public-pages/CorrectPublicPageImplementation.tsx +301 -0
  162. package/examples/public-pages/PublicEventPage.tsx +274 -0
  163. package/examples/public-pages/PublicPageApp.tsx +308 -0
  164. package/examples/public-pages/PublicPageUsageExample.tsx +216 -0
  165. package/examples/public-pages/index.ts +14 -0
  166. package/package.json +1 -10
  167. package/src/__tests__/TEST_STANDARD.md +92 -0
  168. package/src/components/Badge/Badge.test.tsx +314 -0
  169. package/src/components/Badge/Badge.tsx +304 -0
  170. package/src/components/Badge/index.ts +3 -0
  171. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +217 -0
  172. package/src/components/DataTable/__tests__/styles.test.ts +1 -1
  173. package/src/components/DataTable/components/ColumnFilter.tsx +8 -4
  174. package/src/components/DataTable/components/DataTableBody.tsx +461 -0
  175. package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
  176. package/src/components/DataTable/components/FilterRow.tsx +9 -3
  177. package/src/components/DataTable/components/PaginationControls.tsx +1 -0
  178. package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
  179. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +14 -68
  180. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +62 -0
  181. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +43 -0
  182. package/src/components/DataTable/core/ActionManager.ts +235 -0
  183. package/src/components/DataTable/core/ColumnManager.ts +205 -0
  184. package/src/components/DataTable/core/DataManager.ts +188 -0
  185. package/src/components/DataTable/core/DataTableContext.tsx +181 -0
  186. package/src/components/DataTable/core/LocalDataAdapter.ts +273 -0
  187. package/src/components/DataTable/core/PluginRegistry.ts +229 -0
  188. package/src/components/DataTable/core/StateManager.ts +311 -0
  189. package/src/components/DataTable/core/interfaces.ts +338 -0
  190. package/src/components/DataTable/styles.ts +27 -6
  191. package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +94 -0
  192. package/src/components/DataTable/utils/columnUtils.ts +40 -0
  193. package/src/components/DataTable/utils/debugTools.ts +609 -0
  194. package/src/components/DataTable/utils/index.ts +1 -0
  195. package/src/components/Dialog/README.md +804 -0
  196. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +611 -0
  197. package/src/components/Dialog/utils/safeHtml.ts +185 -0
  198. package/src/components/Footer/Footer.test.tsx +1 -1
  199. package/src/components/Form/Form.test.tsx +1 -1
  200. package/src/components/Form/FormErrorSummary.tsx +113 -0
  201. package/src/components/Form/FormFieldset.tsx +127 -0
  202. package/src/components/Form/FormLiveRegion.tsx +198 -0
  203. package/src/components/LoginForm/LoginForm.test.tsx +1 -1
  204. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +76 -10
  205. package/src/components/PaceLoginPage/PaceLoginPage.tsx +1 -1
  206. package/src/components/PasswordReset/PasswordResetForm.test.tsx +597 -0
  207. package/src/components/PasswordReset/PasswordResetForm.tsx +201 -0
  208. package/src/components/PublicLayout/PublicPageDebugger.tsx +104 -0
  209. package/src/components/PublicLayout/PublicPageDiagnostic.tsx +162 -0
  210. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +1 -1
  211. package/src/components/Select/Select.test.tsx +1 -1
  212. package/src/components/Select/Select.tsx +20 -8
  213. package/src/components/Table/__tests__/Table.test.tsx +1 -1
  214. package/src/components/index.ts +3 -0
  215. package/src/hooks/__tests__/useFileUrl.unit.test.ts +83 -85
  216. package/src/index.ts +4 -0
  217. package/src/rbac/hooks/useCan.test.ts +24 -0
  218. package/src/rbac/hooks/usePermissions.ts +49 -12
  219. package/src/styles/core.css +3 -0
  220. package/src/utils/appConfig.ts +47 -0
  221. package/src/utils/appIdResolver.test.ts +499 -0
  222. package/src/utils/appIdResolver.ts +130 -0
  223. package/src/utils/appNameResolver.simple.test.ts +212 -0
  224. package/src/utils/appNameResolver.test.ts +121 -0
  225. package/src/utils/appNameResolver.ts +191 -0
  226. package/src/utils/audit.ts +127 -0
  227. package/src/utils/auth-utils.ts +96 -0
  228. package/src/utils/bundleAnalysis.ts +129 -0
  229. package/src/utils/cn.ts +7 -0
  230. package/src/utils/debugLogger.ts +67 -0
  231. package/src/utils/deviceFingerprint.ts +215 -0
  232. package/src/utils/dynamicUtils.ts +105 -0
  233. package/src/utils/file-reference.test.ts +788 -0
  234. package/src/utils/file-reference.ts +519 -0
  235. package/src/utils/formatDate.test.ts +237 -0
  236. package/src/utils/formatting.ts +133 -0
  237. package/src/utils/index.ts +7 -0
  238. package/src/utils/lazyLoad.tsx +44 -0
  239. package/src/utils/logger.ts +179 -0
  240. package/src/utils/organisationContext.test.ts +322 -0
  241. package/src/utils/organisationContext.ts +153 -0
  242. package/src/utils/performanceBenchmark.ts +64 -0
  243. package/src/utils/performanceBudgets.ts +110 -0
  244. package/src/utils/permissionTypes.ts +37 -0
  245. package/src/utils/permissionUtils.test.ts +393 -0
  246. package/src/utils/permissionUtils.ts +34 -0
  247. package/src/utils/sanitization.ts +264 -0
  248. package/src/utils/schemaUtils.ts +37 -0
  249. package/src/utils/secureDataAccess.test.ts +711 -0
  250. package/src/utils/secureDataAccess.ts +377 -0
  251. package/src/utils/secureErrors.ts +79 -0
  252. package/src/utils/secureStorage.ts +244 -0
  253. package/src/utils/security.ts +156 -0
  254. package/src/utils/securityMonitor.ts +45 -0
  255. package/src/utils/sessionTracking.ts +126 -0
  256. package/src/utils/validation.ts +111 -0
  257. package/src/utils/validationUtils.ts +120 -0
  258. package/src/validation/index.ts +2 -2
  259. package/dist/chunk-444EZN6N.js.map +0 -1
  260. package/dist/chunk-APIBCTL2.js +0 -670
  261. package/dist/chunk-APIBCTL2.js.map +0 -1
  262. package/dist/chunk-HJGGOMQ6.js.map +0 -1
  263. package/dist/chunk-K2WWTH7O.js +0 -94
  264. package/dist/chunk-K2WWTH7O.js.map +0 -1
  265. package/dist/chunk-L6PGMCMD.js.map +0 -1
  266. package/dist/chunk-LMC26NLJ.js +0 -84
  267. package/dist/chunk-LMC26NLJ.js.map +0 -1
  268. package/dist/chunk-NOHEVYVX.js.map +0 -1
  269. package/dist/chunk-TVYPTYOY.js.map +0 -1
  270. package/dist/validation-8npbysjg.d.ts +0 -177
  271. /package/dist/{DataTable-CYOHOX3O.js.map → DataTable-JXFCA2BJ.js.map} +0 -0
  272. /package/dist/{UnifiedAuthProvider-5E5TUNMS.js.map → UnifiedAuthProvider-XIQQ7LVU.js.map} +0 -0
  273. /package/dist/{chunk-YLKIDTUK.js.map → chunk-22WKWKRX.js.map} +0 -0
  274. /package/dist/{chunk-FHWWBIHA.js.map → chunk-6DXZ6V5Q.js.map} +0 -0
  275. /package/dist/{chunk-2TWNJ46Y.js.map → chunk-6LAAY47Q.js.map} +0 -0
  276. /package/dist/{chunk-XARJS7CD.js.map → chunk-INQLMHPF.js.map} +0 -0
  277. /package/dist/{chunk-SL2YQDR6.js.map → chunk-MA6EPSGZ.js.map} +0 -0
  278. /package/dist/{chunk-5DPZ5EAT.js.map → chunk-OWAG3GSU.js.map} +0 -0
  279. /package/dist/{chunk-LTV3XIJJ.js.map → chunk-T6JN6LH6.js.map} +0 -0
  280. /package/examples/{components → components 2}/DataTable/HierarchicalActionsExample.tsx +0 -0
  281. /package/examples/{components → components 2}/DataTable/HierarchicalExample.tsx +0 -0
  282. /package/examples/{components → components 2}/DataTable/InitialPageSizeExample.tsx +0 -0
  283. /package/examples/{components → components 2}/DataTable/PerformanceExample.tsx +0 -0
  284. /package/examples/{components → components 2}/DataTable/index.ts +0 -0
  285. /package/examples/{components → components 2}/Dialog/BasicHtmlTest.tsx +0 -0
  286. /package/examples/{components → components 2}/Dialog/DebugHtmlExample.tsx +0 -0
  287. /package/examples/{components → components 2}/Dialog/HtmlDialogExample.tsx +0 -0
  288. /package/examples/{components → components 2}/Dialog/ScrollableDialogExample.tsx +0 -0
  289. /package/examples/{components → components 2}/Dialog/SimpleHtmlTest.tsx +0 -0
  290. /package/examples/{components → components 2}/Dialog/SmartDialogExample.tsx +0 -0
  291. /package/examples/{components → components 2}/Dialog/index.ts +0 -0
  292. /package/examples/{components → components 2}/index.ts +0 -0
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @file Authentication utilities
3
+ */
4
+
5
+ import type { User, SupabaseClient } from '@supabase/supabase-js';
6
+
7
+ export interface LoginCredentials {
8
+ email: string;
9
+ password: string;
10
+ }
11
+
12
+ export interface SignUpData {
13
+ email: string;
14
+ password: string;
15
+ }
16
+
17
+ export interface AuthResponse {
18
+ user?: User;
19
+ error?: Error;
20
+ }
21
+
22
+ export async function signInWithEmail(credentials: LoginCredentials): Promise<AuthResponse> {
23
+ try {
24
+ // TODO: Implement actual authentication logic
25
+ // For now, return a proper error response indicating this needs implementation
26
+ return {
27
+ error: new Error('Authentication not yet implemented - placeholder function')
28
+ };
29
+ } catch (error) {
30
+ return { error: error instanceof Error ? error : new Error('Unknown authentication error') };
31
+ }
32
+ }
33
+
34
+ export async function signUpWithEmail(data: SignUpData): Promise<AuthResponse> {
35
+ try {
36
+ // TODO: Implement actual registration logic
37
+ // For now, return a proper error response indicating this needs implementation
38
+ return {
39
+ error: new Error('Registration not yet implemented - placeholder function')
40
+ };
41
+ } catch (error) {
42
+ return { error: error instanceof Error ? error : new Error('Unknown registration error') };
43
+ }
44
+ }
45
+
46
+ export async function resetPassword(email: string): Promise<{ error?: Error }> {
47
+ try {
48
+ // TODO: Implement actual password reset logic
49
+ // For now, return a proper error response indicating this needs implementation
50
+ return {
51
+ error: new Error('Password reset not yet implemented - placeholder function')
52
+ };
53
+ } catch (error) {
54
+ return { error: error instanceof Error ? error : new Error('Unknown password reset error') };
55
+ }
56
+ }
57
+
58
+ export async function updatePassword(supabaseClient: SupabaseClient, newPassword: string): Promise<{ error?: Error }> {
59
+ try {
60
+ const { error } = await supabaseClient.auth.updateUser({
61
+ password: newPassword
62
+ });
63
+ return { error: error || undefined };
64
+ } catch (err) {
65
+ return { error: err as Error };
66
+ }
67
+ }
68
+
69
+ // Audit logger implementation - using proper types instead of any
70
+ export interface AuditEventDetails {
71
+ [key: string]: unknown;
72
+ }
73
+
74
+ export interface AuditEventData {
75
+ action: string;
76
+ details?: AuditEventDetails;
77
+ }
78
+
79
+ export const auditLogger = {
80
+ log: (event: string, details?: AuditEventDetails) => {
81
+ // TODO: Implement proper audit logging service integration
82
+ // Console logging removed for production
83
+ },
84
+ logAuthEvent: (userId: string, action: string, details?: AuditEventDetails) => {
85
+ // TODO: Implement proper auth event logging
86
+ // Console logging removed for production
87
+ },
88
+ logPermissionEvent: (userId: string, permission: string, granted: boolean) => {
89
+ // TODO: Implement proper permission event logging
90
+ // Console logging removed for production
91
+ },
92
+ logEvent: (eventData: AuditEventData) => {
93
+ // TODO: Implement proper event logging
94
+ // Console logging removed for production
95
+ }
96
+ };
@@ -0,0 +1,129 @@
1
+
2
+ interface BundleStats {
3
+ totalSize: number;
4
+ gzippedSize: number;
5
+ chunks: ChunkInfo[];
6
+ treeshakingEffectiveness: number;
7
+ }
8
+
9
+ interface ChunkInfo {
10
+ name: string;
11
+ size: number;
12
+ modules: string[];
13
+ dynamicallyImported: boolean;
14
+ }
15
+
16
+ class BundleAnalyzer {
17
+ private enabled = import.meta.env.MODE === 'development';
18
+
19
+ analyzeBundle(): BundleStats | null {
20
+ if (!this.enabled) return null;
21
+
22
+ // In a real implementation, this would integrate with webpack-bundle-analyzer
23
+ // or similar tools. For now, we'll simulate analysis
24
+
25
+ // TODO: Replace with proper logging service integration
26
+ // For now, we'll log to console for testing purposes
27
+ console.log('Bundle analysis would run here in development');
28
+ console.log('To enable real bundle analysis:');
29
+ console.log('1. Install webpack-bundle-analyzer');
30
+ console.log('2. Add bundle analysis to build scripts');
31
+ console.log('3. Integrate with performance budgets');
32
+
33
+ return {
34
+ totalSize: 0,
35
+ gzippedSize: 0,
36
+ chunks: [],
37
+ treeshakingEffectiveness: 0
38
+ };
39
+ }
40
+
41
+ checkTreeshaking(): void {
42
+ if (!this.enabled) return;
43
+
44
+ const potentialIssues = [
45
+ 'Check for unused exports in index files',
46
+ 'Verify side-effect free modules in package.json',
47
+ 'Ensure proper ES module syntax',
48
+ 'Check for circular dependencies'
49
+ ];
50
+
51
+ // TODO: Replace with proper logging service integration
52
+ // For now, we'll log to console for testing purposes
53
+ console.group('Tree-shaking Analysis');
54
+ potentialIssues.forEach(issue => console.log('- ' + issue));
55
+ console.groupEnd();
56
+ }
57
+
58
+ validateExports(): void {
59
+ if (!this.enabled) return;
60
+
61
+ // TODO: Replace with proper logging service integration
62
+ // For now, we'll log to console for testing purposes
63
+ console.group('Export Validation');
64
+ console.log('Checking for optimal export patterns...');
65
+ console.log('- Prefer named exports over default exports');
66
+ console.log('- Avoid barrel exports for large modules');
67
+ console.log('- Use dynamic imports for large dependencies');
68
+ console.groupEnd();
69
+ }
70
+
71
+ generateReport(): string {
72
+ const report = `
73
+ # Bundle Analysis Report
74
+
75
+ ## Recommendations for @jmruthers/pace-core
76
+
77
+ ### 1. Code Splitting Opportunities
78
+ - ✅ DataTable virtualization is lazy-loaded
79
+ - ⚠️ Consider splitting auth providers by use case
80
+ - ⚠️ Lazy load heavy UI components (charts, complex forms)
81
+
82
+ ### 2. Tree-shaking Optimization
83
+ - ✅ Using ES modules throughout
84
+ - ✅ Proper sideEffects configuration
85
+ - ⚠️ Check for unused utility functions
86
+
87
+ ### 3. Bundle Size Targets
88
+ - Core components: < 50KB gzipped
89
+ - Auth module: < 30KB gzipped
90
+ - Utilities: < 20KB gzipped
91
+ - Total package: < 150KB gzipped
92
+
93
+ ### 4. Performance Monitoring
94
+ - Monitor component render times
95
+ - Track bundle size changes
96
+ - Validate tree-shaking effectiveness
97
+ `;
98
+
99
+ return report.trim();
100
+ }
101
+ }
102
+
103
+ export const bundleAnalyzer = new BundleAnalyzer();
104
+
105
+ // Helper to check if imports are optimized
106
+ export function validateImportPattern(moduleId: string, importedItems: string[]): void {
107
+ if (import.meta.env.MODE !== 'development') return;
108
+
109
+ const largeModules = ['lodash', 'moment', 'rxjs'];
110
+ const isLargeModule = largeModules.some(mod => moduleId.includes(mod));
111
+
112
+ if (isLargeModule && importedItems.length > 5) {
113
+ // TODO: Replace with proper logging service integration
114
+ // For now, we'll log to console for testing purposes
115
+ console.warn(
116
+ 'Large import detected: importing ' + importedItems.length + ' items from ' + moduleId + '. ' +
117
+ 'Consider splitting imports or using more specific imports.'
118
+ );
119
+ }
120
+ }
121
+
122
+ // Monitor dynamic imports
123
+ export function trackDynamicImport(moduleName: string): void {
124
+ if (import.meta.env.MODE !== 'development') return;
125
+
126
+ // TODO: Replace with proper logging service integration
127
+ // For now, we'll log to console for testing purposes
128
+ console.log('Dynamic import: ' + moduleName + ' - Good for code splitting!');
129
+ }
@@ -0,0 +1,7 @@
1
+
2
+ import { type ClassValue, clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+
5
+ export function cn(...inputs: ClassValue[]) {
6
+ return twMerge(clsx(inputs));
7
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @file Debug Logger Utility
3
+ * @package @jmruthers/pace-core
4
+ * @module Utils/DebugLogger
5
+ * @since 0.4.76
6
+ */
7
+
8
+ /**
9
+ * Debug logger that respects environment settings
10
+ * Only logs in development mode to prevent production console spam
11
+ */
12
+ export class DebugLogger {
13
+ /**
14
+ * Check if we're in development mode
15
+ */
16
+ private static get isDevelopment(): boolean {
17
+ return import.meta.env.MODE === 'development';
18
+ }
19
+
20
+ /**
21
+ * Log debug information only in development mode
22
+ */
23
+ static log(component: string, message: string, ...args: any[]): void {
24
+ if (this.isDevelopment) {
25
+ try {
26
+ console.log(`[${component}] ${message}`, ...args);
27
+ } catch (e) {
28
+ // Gracefully handle console method errors
29
+ }
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Log error information (always logged)
35
+ */
36
+ static error(component: string, message: string, ...args: any[]): void {
37
+ try {
38
+ console.error(`[${component}] ${message}`, ...args);
39
+ } catch (e) {
40
+ // Gracefully handle console method errors
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Log warning information (always logged)
46
+ */
47
+ static warn(component: string, message: string, ...args: any[]): void {
48
+ try {
49
+ console.warn(`[${component}] ${message}`, ...args);
50
+ } catch (e) {
51
+ // Gracefully handle console method errors
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Log info information only in development mode
57
+ */
58
+ static info(component: string, message: string, ...args: any[]): void {
59
+ if (this.isDevelopment) {
60
+ try {
61
+ console.info(`[${component}] ${message}`, ...args);
62
+ } catch (e) {
63
+ // Gracefully handle console method errors
64
+ }
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,215 @@
1
+ /**
2
+ * @file Secure Device Fingerprinting
3
+ * @description Enhanced device fingerprinting with encryption and security measures
4
+ */
5
+
6
+ import { secureStorage } from './secureStorage';
7
+
8
+ export interface DeviceFingerprint {
9
+ hash: string;
10
+ timestamp: number;
11
+ components: {
12
+ userAgent: string;
13
+ language: string;
14
+ platform: string;
15
+ screen: string;
16
+ timezone: string;
17
+ canvas?: string;
18
+ webgl?: string;
19
+ };
20
+ entropy: number;
21
+ }
22
+
23
+ /**
24
+ * Generate a secure device fingerprint (synchronous)
25
+ */
26
+ export function generateDeviceFingerprint(): DeviceFingerprint {
27
+ try {
28
+ const components = {
29
+ userAgent: getHashedUserAgent(),
30
+ language: navigator.language || 'unknown',
31
+ platform: navigator.platform || 'unknown',
32
+ screen: `${screen.width}x${screen.height}x${screen.colorDepth}`,
33
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'unknown',
34
+ canvas: getCanvasFingerprint(),
35
+ webgl: getWebGLFingerprint(),
36
+ };
37
+
38
+ // Calculate entropy (uniqueness score)
39
+ const entropy = calculateEntropy(components);
40
+
41
+ // Create a hash from all components
42
+ const fingerprintData = JSON.stringify(components);
43
+ const hash = hashStringSync(fingerprintData);
44
+
45
+ const fingerprint: DeviceFingerprint = {
46
+ hash,
47
+ timestamp: Date.now(),
48
+ components,
49
+ entropy,
50
+ };
51
+
52
+ // Store fingerprint asynchronously
53
+ secureStorage.setItem('device_fingerprint', JSON.stringify(fingerprint));
54
+
55
+ return fingerprint;
56
+ } catch (error) {
57
+ return generateFallbackFingerprint();
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Validate device fingerprint with security checks
63
+ */
64
+ export function validateDeviceFingerprint(
65
+ storedFingerprint: DeviceFingerprint,
66
+ currentFingerprint: DeviceFingerprint
67
+ ): {
68
+ isValid: boolean;
69
+ confidence: number;
70
+ reasons: string[];
71
+ } {
72
+ const reasons: string[] = [];
73
+ let matchingComponents = 0;
74
+ const totalComponents = Object.keys(storedFingerprint.components).length;
75
+
76
+ // Check each component
77
+ Object.entries(storedFingerprint.components).forEach(([key, value]) => {
78
+ if (currentFingerprint.components[key as keyof typeof currentFingerprint.components] === value) {
79
+ matchingComponents++;
80
+ } else {
81
+ reasons.push(`Component mismatch: ${key}`);
82
+ }
83
+ });
84
+
85
+ // Calculate confidence score
86
+ const confidence = (matchingComponents / totalComponents) * 100;
87
+
88
+ // Security thresholds
89
+ const isValid = confidence >= 80; // Require 80% match
90
+
91
+ // Additional security checks
92
+ const timeDiff = currentFingerprint.timestamp - storedFingerprint.timestamp;
93
+ const maxAge = 30 * 24 * 60 * 60 * 1000; // 30 days
94
+
95
+ if (timeDiff > maxAge) {
96
+ reasons.push('Fingerprint too old');
97
+ return { isValid: false, confidence, reasons };
98
+ }
99
+
100
+ if (confidence < 60) {
101
+ reasons.push('Device signature changed significantly');
102
+ }
103
+
104
+ return { isValid, confidence, reasons };
105
+ }
106
+
107
+ /**
108
+ * Generate canvas fingerprint for enhanced uniqueness
109
+ */
110
+ function getCanvasFingerprint(): string {
111
+ try {
112
+ const canvas = document.createElement('canvas');
113
+ const ctx = canvas.getContext('2d');
114
+
115
+ if (!ctx) return 'canvas-unavailable';
116
+
117
+ // Draw complex pattern for fingerprinting
118
+ ctx.textBaseline = 'top';
119
+ ctx.font = '14px Arial';
120
+ ctx.fillStyle = '#f60';
121
+ ctx.fillRect(125, 1, 62, 20);
122
+ ctx.fillStyle = '#069';
123
+ ctx.fillText('Device fingerprint 🔒', 2, 15);
124
+ ctx.fillStyle = 'rgba(102, 204, 0, 0.2)';
125
+ ctx.fillText('Device fingerprint 🔒', 4, 17);
126
+
127
+ const dataURL = canvas.toDataURL();
128
+ return hashStringSync(dataURL);
129
+ } catch (error) {
130
+ return 'canvas-error';
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Get WebGL fingerprint
136
+ */
137
+ function getWebGLFingerprint(): string {
138
+ try {
139
+ const canvas = document.createElement('canvas');
140
+ const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl') as WebGLRenderingContext | null;
141
+
142
+ if (!gl) return 'webgl-unavailable';
143
+
144
+ const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
145
+ if (!debugInfo) return 'webgl-no-debug';
146
+
147
+ const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
148
+ const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
149
+
150
+ return `${vendor}|${renderer}`;
151
+ } catch (error) {
152
+ return 'webgl-error';
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Hash user agent to prevent direct exposure
158
+ */
159
+ function getHashedUserAgent(): string {
160
+ const ua = navigator.userAgent;
161
+ return hashStringSync(ua).substring(0, 16); // Shorter hash for storage
162
+ }
163
+
164
+ /**
165
+ * Calculate entropy of fingerprint components
166
+ */
167
+ function calculateEntropy(components: Record<string, string>): number {
168
+ const values = Object.values(components).join('');
169
+ const charCounts = new Map<string, number>();
170
+
171
+ for (const char of values) {
172
+ charCounts.set(char, (charCounts.get(char) || 0) + 1);
173
+ }
174
+
175
+ let entropy = 0;
176
+ for (const count of charCounts.values()) {
177
+ const probability = count / values.length;
178
+ entropy -= probability * Math.log2(probability);
179
+ }
180
+
181
+ return entropy;
182
+ }
183
+
184
+ /**
185
+ * Synchronous hash function for device fingerprinting
186
+ */
187
+ function hashStringSync(str: string): string {
188
+ let hash = 0;
189
+ for (let i = 0; i < str.length; i++) {
190
+ const char = str.charCodeAt(i);
191
+ hash = ((hash << 5) - hash) + char;
192
+ hash = hash & hash;
193
+ }
194
+ return Math.abs(hash).toString(36);
195
+ }
196
+
197
+ /**
198
+ * Generate fallback fingerprint for error cases
199
+ */
200
+ function generateFallbackFingerprint(): DeviceFingerprint {
201
+ const components = {
202
+ userAgent: 'fallback',
203
+ language: 'unknown',
204
+ platform: 'unknown',
205
+ screen: 'unknown',
206
+ timezone: 'unknown',
207
+ };
208
+
209
+ return {
210
+ hash: `fallback_${Date.now()}_${Math.random().toString(36)}`,
211
+ timestamp: Date.now(),
212
+ components,
213
+ entropy: 1, // Low entropy for fallback
214
+ };
215
+ }
@@ -0,0 +1,105 @@
1
+
2
+ /**
3
+ * Dynamic utility loader to reduce initial bundle size
4
+ * Heavy utilities are loaded on-demand
5
+ */
6
+
7
+ // Type definitions for dynamic imports
8
+ type DebounceFunction = <T extends (...args: unknown[]) => unknown>(
9
+ func: T,
10
+ wait?: number,
11
+ options?: { leading?: boolean; maxWait?: number; trailing?: boolean }
12
+ ) => T & { cancel(): void; flush(): void };
13
+
14
+ type ThrottleFunction = <T extends (...args: unknown[]) => unknown>(
15
+ func: T,
16
+ wait?: number,
17
+ options?: { leading?: boolean; trailing?: boolean }
18
+ ) => T & { cancel(): void; flush(): void };
19
+
20
+ // Dynamic lodash utilities
21
+ export const loadLodash = async (): Promise<{
22
+ debounce: DebounceFunction;
23
+ throttle: ThrottleFunction;
24
+ }> => {
25
+ const [debounceModule, throttleModule] = await Promise.all([
26
+ import('lodash.debounce' as any),
27
+ import('lodash.throttle' as any)
28
+ ]);
29
+
30
+ return {
31
+ debounce: (debounceModule.default || debounceModule) as DebounceFunction,
32
+ throttle: (throttleModule.default || throttleModule) as ThrottleFunction
33
+ };
34
+ };
35
+
36
+ // Dynamic date utilities
37
+ export const loadDateUtils = async (): Promise<typeof import('date-fns')> => {
38
+ const dateFns = await import('date-fns');
39
+ return dateFns;
40
+ };
41
+
42
+ // Dynamic chart utilities - using unknown type to avoid Recharts type issues
43
+ export const loadChartUtils = async (): Promise<unknown> => {
44
+ const recharts = await import('recharts');
45
+ return recharts;
46
+ };
47
+
48
+ // Dynamic form utilities
49
+ export const loadFormUtils = async (): Promise<{
50
+ useForm: unknown;
51
+ useController: unknown;
52
+ Controller: unknown;
53
+ FormProvider: unknown;
54
+ useFormContext: unknown;
55
+ useWatch: unknown;
56
+ useFormState: unknown;
57
+ useFieldArray: unknown;
58
+ zodResolver: unknown;
59
+ }> => {
60
+ const [reactHookForm, zodResolvers] = await Promise.all([
61
+ import('react-hook-form'),
62
+ import('@hookform/resolvers/zod')
63
+ ]);
64
+
65
+ return {
66
+ ...reactHookForm,
67
+ zodResolver: zodResolvers.zodResolver
68
+ };
69
+ };
70
+
71
+ // Dynamic CSV utilities
72
+ export const loadCSVUtils = async (): Promise<unknown> => {
73
+ const papaparse = await import('papaparse');
74
+ return papaparse.default;
75
+ };
76
+
77
+ // Utility function to create lazy utility hooks
78
+ export function createLazyUtility<T>(loader: () => Promise<T>) {
79
+ let cached: T | null = null;
80
+ let loading: Promise<T> | null = null;
81
+
82
+ return {
83
+ load: async (): Promise<T> => {
84
+ if (cached) return cached;
85
+ if (loading) return loading;
86
+
87
+ loading = loader().then(result => {
88
+ cached = result;
89
+ loading = null;
90
+ return result;
91
+ });
92
+
93
+ return loading;
94
+ },
95
+ getCached: (): T | null => cached,
96
+ isLoaded: (): boolean => cached !== null
97
+ };
98
+ }
99
+
100
+ // Pre-configured lazy utilities with explicit types
101
+ export const lazyLodash: ReturnType<typeof createLazyUtility<Awaited<ReturnType<typeof loadLodash>>>> = createLazyUtility(loadLodash);
102
+ export const lazyDateUtils: ReturnType<typeof createLazyUtility<Awaited<ReturnType<typeof loadDateUtils>>>> = createLazyUtility(loadDateUtils);
103
+ export const lazyChartUtils: ReturnType<typeof createLazyUtility<unknown>> = createLazyUtility(loadChartUtils);
104
+ export const lazyFormUtils: ReturnType<typeof createLazyUtility<Awaited<ReturnType<typeof loadFormUtils>>>> = createLazyUtility(loadFormUtils);
105
+ export const lazyCSVUtils: ReturnType<typeof createLazyUtility<unknown>> = createLazyUtility(loadCSVUtils);