@jmruthers/pace-core 0.5.135 → 0.5.137
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.
- package/dist/{DataTable-A36PJG6N.js → DataTable-6M4L6BI2.js} +26 -13
- package/dist/{DataTable-C7GaRZye.d.ts → DataTable-CWAZZcXC.d.ts} +1 -1
- package/dist/{PublicLoadingSpinner-CUAnTvcg.d.ts → EventLogo-rFL_kRjk.d.ts} +123 -135
- package/dist/{UnifiedAuthProvider-BVKmQd9u.d.ts → UnifiedAuthProvider-DJxGTftH.d.ts} +1 -1
- package/dist/{UnifiedAuthProvider-CQDZRJIS.js → UnifiedAuthProvider-XIQQ7LVU.js} +5 -5
- package/dist/{api-TNIBJWLM.js → api-45XYYO2A.js} +4 -3
- package/dist/{audit-T36HM7IM.js → audit-64X3VJXB.js} +3 -2
- package/dist/{chunk-F64FFPOZ.js → chunk-22WKWKRX.js} +26 -20
- package/dist/chunk-22WKWKRX.js.map +1 -0
- package/dist/{chunk-VZ5OR6HD.js → chunk-4C7EXCAR.js} +62 -150
- package/dist/chunk-4C7EXCAR.js.map +1 -0
- package/dist/{chunk-PYUXFQJ3.js → chunk-56XJ3TU6.js} +2 -2
- package/dist/chunk-56XJ3TU6.js.map +1 -0
- package/dist/{chunk-CTJRBUX2.js → chunk-6LAAY47Q.js} +2 -2
- package/dist/{chunk-UJI6WSMD.js → chunk-7QCC6MCP.js} +90 -3
- package/dist/chunk-7QCC6MCP.js.map +1 -0
- package/dist/{chunk-66C4BSAY.js → chunk-ANBQRTPX.js} +9 -2
- package/dist/chunk-ANBQRTPX.js.map +1 -0
- package/dist/{chunk-CQZU6TFE.js → chunk-BCIBECNB.js} +100 -62
- package/dist/chunk-BCIBECNB.js.map +1 -0
- package/dist/{chunk-GKHF54DI.js → chunk-BESYRHQM.js} +10 -4
- package/dist/chunk-BESYRHQM.js.map +1 -0
- package/dist/chunk-BJPBT3CU.js +21 -0
- package/dist/chunk-BJPBT3CU.js.map +1 -0
- package/dist/{chunk-BYXRHAIF.js → chunk-BLCXZEYF.js} +23 -14
- package/dist/chunk-BLCXZEYF.js.map +1 -0
- package/dist/{chunk-WP5I5GLN.js → chunk-BVYWGZVV.js} +112 -97
- package/dist/chunk-BVYWGZVV.js.map +1 -0
- package/dist/{chunk-GEVIB2UB.js → chunk-ERISIBYU.js} +14 -5
- package/dist/chunk-ERISIBYU.js.map +1 -0
- package/dist/{chunk-O3NWNXDY.js → chunk-FMUCXFII.js} +2 -2
- package/dist/chunk-FMUCXFII.js.map +1 -0
- package/dist/{chunk-GVDR7WNV.js → chunk-HAWZXGR2.js} +334 -614
- package/dist/chunk-HAWZXGR2.js.map +1 -0
- package/dist/{chunk-ZV77RZMU.js → chunk-INQLMHPF.js} +2 -2
- package/dist/chunk-JISYG63F.js +70 -0
- package/dist/chunk-JISYG63F.js.map +1 -0
- package/dist/{chunk-HMNOSGVA.js → chunk-KYRHUBIU.js} +576 -767
- package/dist/chunk-KYRHUBIU.js.map +1 -0
- package/dist/{chunk-M6DDYFUD.js → chunk-LS353YLY.js} +19 -16
- package/dist/chunk-LS353YLY.js.map +1 -0
- package/dist/{chunk-TGIY2AR2.js → chunk-MA6EPSGZ.js} +4 -3
- package/dist/{chunk-TGIY2AR2.js.map → chunk-MA6EPSGZ.js.map} +1 -1
- package/dist/chunk-OWAG3GSU.js +58 -0
- package/dist/chunk-OWAG3GSU.js.map +1 -0
- package/dist/{chunk-JCQZ6LA7.js → chunk-Q5QRDWKI.js} +9 -3
- package/dist/chunk-Q5QRDWKI.js.map +1 -0
- package/dist/chunk-S5OFRT4M.js +94 -0
- package/dist/chunk-S5OFRT4M.js.map +1 -0
- package/dist/{chunk-3DBFLLLU.js → chunk-SBVILCCA.js} +14 -9
- package/dist/chunk-SBVILCCA.js.map +1 -0
- package/dist/{chunk-ZYZCRSBD.js → chunk-T6JN6LH6.js} +16 -11
- package/dist/chunk-T6JN6LH6.js.map +1 -0
- package/dist/chunk-XDNLUEXI.js +138 -0
- package/dist/chunk-XDNLUEXI.js.map +1 -0
- package/dist/{chunk-3CG5L6RN.js → chunk-YCWDTTUK.js} +90 -75
- package/dist/chunk-YCWDTTUK.js.map +1 -0
- package/dist/{chunk-5F3NDPJV.js → chunk-ZZ2SS7NI.js} +10 -5
- package/dist/chunk-ZZ2SS7NI.js.map +1 -0
- package/dist/components.d.ts +7 -287
- package/dist/components.js +27 -157
- package/dist/components.js.map +1 -1
- package/dist/{file-reference-C9isKNPn.d.ts → file-reference-C6Gkn77H.d.ts} +1 -1
- package/dist/{formatting-DFcCxUEk.d.ts → formatting-CvUXy2mF.d.ts} +1 -1
- package/dist/hooks.d.ts +3 -3
- package/dist/hooks.js +21 -16
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +101 -9
- package/dist/index.js +44 -31
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +4 -4
- package/dist/rbac/index.js +12 -12
- package/dist/schema-DTDZQe2u.d.ts +28 -0
- package/dist/styles/index.js +2 -1
- package/dist/theming/runtime.d.ts +2 -19
- package/dist/theming/runtime.js +2 -1
- package/dist/{types-D5rqZQXk.d.ts → types-Dfz9dmVH.d.ts} +12 -1
- package/dist/types.d.ts +153 -4
- package/dist/types.js +51 -16
- package/dist/types.js.map +1 -1
- package/dist/{useInactivityTracker-MRUU55XI.js → useInactivityTracker-TO6ZOF35.js} +3 -2
- package/dist/{usePublicRouteParams-Dyt1tzI9.d.ts → usePublicRouteParams-B7PabvuH.d.ts} +1 -1
- package/dist/utils.d.ts +221 -173
- package/dist/utils.js +185 -225
- package/dist/utils.js.map +1 -1
- package/dist/validation.d.ts +24 -115
- package/dist/validation.js +19 -474
- package/dist/validation.js.map +1 -1
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +6 -6
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +6 -6
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +7 -7
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +4 -4
- package/docs/api/interfaces/BadgeProps.md +27 -0
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +29 -4
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +18 -18
- package/docs/api/interfaces/DataTableColumn.md +61 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +14 -14
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +152 -0
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +8 -8
- package/docs/api/interfaces/FileDisplayProps.md +15 -15
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
- package/docs/api/interfaces/NavigationContextType.md +9 -9
- package/docs/api/interfaces/NavigationGuardProps.md +10 -10
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +7 -7
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +27 -27
- package/docs/api/interfaces/PaceLoginPageProps.md +4 -4
- package/docs/api/interfaces/PageAccessRecord.md +8 -8
- package/docs/api/interfaces/PagePermissionContextType.md +8 -8
- package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
- package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
- package/docs/api/interfaces/PaletteData.md +4 -4
- package/docs/api/interfaces/PermissionEnforcerProps.md +11 -11
- package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
- package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +10 -10
- package/docs/api/interfaces/RouteConfig.md +10 -10
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +21 -0
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +9 -9
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +9 -9
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
- package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
- package/docs/api/interfaces/UserEventAccess.md +11 -11
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +591 -220
- package/docs/api-reference/components.md +106 -26
- package/docs/architecture/README.md +0 -3
- package/docs/implementation-guides/data-tables.md +277 -13
- package/docs/implementation-guides/forms.md +1 -16
- package/docs/implementation-guides/permission-enforcement.md +8 -2
- package/docs/styles/README.md +0 -2
- package/examples/README.md +30 -14
- package/examples/STRUCTURE.md +125 -0
- package/examples/components 2/DataTable/HierarchicalActionsExample.tsx +421 -0
- package/examples/components 2/DataTable/HierarchicalExample.tsx +475 -0
- package/examples/components 2/DataTable/InitialPageSizeExample.tsx +177 -0
- package/examples/components 2/DataTable/PerformanceExample.tsx +506 -0
- package/examples/components 2/DataTable/index.ts +13 -0
- package/examples/components 2/Dialog/BasicHtmlTest.tsx +55 -0
- package/examples/components 2/Dialog/DebugHtmlExample.tsx +68 -0
- package/examples/components 2/Dialog/HtmlDialogExample.tsx +202 -0
- package/examples/components 2/Dialog/ScrollableDialogExample.tsx +290 -0
- package/examples/components 2/Dialog/SimpleHtmlTest.tsx +61 -0
- package/examples/components 2/Dialog/SmartDialogExample.tsx +322 -0
- package/examples/components 2/Dialog/index.ts +15 -0
- package/examples/components 2/index.ts +11 -0
- package/examples/features/index.ts +12 -0
- package/{src/examples → examples/features/public-pages}/CorrectPublicPageImplementation.tsx +14 -17
- package/{src/examples → examples/features/public-pages}/PublicEventPage.tsx +14 -27
- package/{src/examples → examples/features/public-pages}/PublicPageApp.tsx +15 -28
- package/{src/examples → examples/features/public-pages}/PublicPageUsageExample.tsx +8 -10
- package/examples/features/public-pages/index.ts +14 -0
- package/examples/features/rbac/CompleteRBACExample.tsx +324 -0
- package/examples/features/rbac/EventBasedApp.tsx +239 -0
- package/examples/features/rbac/PermissionExample.tsx +151 -0
- package/examples/features/rbac/index.ts +13 -0
- package/examples/index.ts +11 -3
- package/package.json +30 -19
- package/src/__tests__/TEST_STANDARD.md +92 -0
- package/src/components/Alert/Alert.tsx +1 -1
- package/src/components/Avatar/Avatar.tsx +1 -1
- package/src/components/Badge/Badge.test.tsx +314 -0
- package/src/components/Badge/Badge.tsx +304 -0
- package/src/components/Badge/index.ts +3 -0
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/Card/Card.tsx +1 -1
- package/src/components/Checkbox/Checkbox.tsx +1 -1
- package/src/components/DataTable/DataTable.test.tsx +1 -1
- package/src/components/DataTable/DataTable.tsx +1 -30
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +562 -0
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +217 -0
- package/src/components/DataTable/__tests__/styles.test.ts +3 -3
- package/src/components/DataTable/components/ActionButtons.tsx +0 -15
- package/src/components/DataTable/components/ColumnFilter.tsx +8 -4
- package/src/components/DataTable/components/DataTableBody.tsx +461 -0
- package/src/components/DataTable/components/DataTableCore.tsx +4 -185
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +1 -1
- package/src/components/DataTable/components/DataTableModals.tsx +1 -27
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
- package/src/components/DataTable/components/EditableRow.tsx +1 -1
- package/src/components/DataTable/components/FilterRow.tsx +9 -3
- package/src/components/DataTable/components/ImportModal.tsx +2 -14
- package/src/components/DataTable/components/PaginationControls.tsx +2 -1
- package/src/components/DataTable/components/UnifiedTableBody.tsx +109 -82
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +14 -68
- package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +1 -1
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +62 -0
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +1 -1
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +1 -1
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +43 -0
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +1 -1
- package/src/components/DataTable/core/ActionManager.ts +235 -0
- package/src/components/DataTable/core/ColumnManager.ts +205 -0
- package/src/components/DataTable/core/DataManager.ts +188 -0
- package/src/components/DataTable/core/DataTableContext.tsx +181 -0
- package/src/components/DataTable/core/LocalDataAdapter.ts +273 -0
- package/src/components/DataTable/core/PluginRegistry.ts +229 -0
- package/src/components/DataTable/core/StateManager.ts +311 -0
- package/src/components/DataTable/core/interfaces.ts +338 -0
- package/src/components/DataTable/examples/GroupingAggregationExample.tsx +273 -0
- package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +1 -1
- package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +1 -1
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +1 -1
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +1 -1
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +2 -23
- package/src/components/DataTable/index.ts +4 -0
- package/src/components/DataTable/styles.ts +28 -7
- package/src/components/DataTable/types.ts +13 -0
- package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +94 -0
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +1 -1
- package/src/components/DataTable/utils/aggregationUtils.ts +161 -0
- package/src/components/DataTable/utils/columnUtils.ts +40 -0
- package/src/components/DataTable/utils/debugTools.ts +609 -0
- package/src/components/DataTable/utils/exportUtils.ts +1 -1
- package/src/components/DataTable/utils/flexibleImport.ts +1 -11
- package/src/components/DataTable/utils/index.ts +2 -0
- package/src/components/DataTable/utils/paginationUtils.ts +1 -1
- package/src/components/Dialog/Dialog.tsx +2 -2
- package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +8 -1
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +35 -7
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +5 -4
- package/src/components/EventSelector/EventSelector.tsx +3 -2
- package/src/components/FileDisplay/FileDisplay.tsx +2 -36
- package/src/components/FileUpload/FileUpload.test.tsx +2 -2
- package/src/components/FileUpload/FileUpload.tsx +2 -2
- package/src/components/Footer/Footer.test.tsx +1 -1
- package/src/components/Footer/Footer.tsx +1 -1
- package/src/components/Form/Form.test.tsx +5 -510
- package/src/components/Form/Form.tsx +1 -1
- package/src/components/Form/FormField.tsx +1 -1
- package/src/components/Form/index.ts +0 -12
- package/src/components/Header/Header.tsx +1 -1
- package/src/components/Input/Input.tsx +1 -1
- package/src/components/Label/Label.tsx +1 -1
- package/src/components/LoginForm/LoginForm.test.tsx +1 -1
- package/src/components/LoginForm/LoginForm.tsx +1 -1
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -3
- package/src/components/NavigationMenu/NavigationMenu.tsx +9 -8
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +4 -3
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -12
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +0 -16
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +76 -10
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +0 -1
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -9
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +35 -3
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +14 -13
- package/src/components/PasswordReset/PasswordChangeForm.tsx +1 -1
- package/src/components/PasswordReset/index.ts +0 -2
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +35 -8
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -2
- package/src/components/PublicLayout/PublicErrorBoundary.tsx +1 -1
- package/src/components/PublicLayout/PublicLoadingSpinner.tsx +1 -1
- package/src/components/PublicLayout/PublicPageContextChecker.tsx +44 -43
- package/src/components/PublicLayout/PublicPageFooter.tsx +1 -1
- package/src/components/PublicLayout/PublicPageHeader.tsx +1 -15
- package/src/components/PublicLayout/PublicPageProvider.tsx +3 -2
- package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +2 -0
- package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +1 -1
- package/src/components/PublicLayout/index.ts +4 -2
- package/src/components/Select/Select.test.tsx +1 -1
- package/src/components/Select/Select.tsx +21 -9
- package/src/components/{SessionRestorationLoader.tsx → SessionRestorationLoader/SessionRestorationLoader.tsx} +3 -2
- package/src/components/SessionRestorationLoader/index.ts +3 -0
- package/src/components/Switch/Switch.tsx +1 -1
- package/src/components/Table/Table.tsx +1 -1
- package/src/components/Table/__tests__/Table.test.tsx +1 -1
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/Tooltip/Tooltip.tsx +1 -1
- package/src/components/index.ts +7 -10
- package/src/hooks/__tests__/hooks.integration.test.tsx +37 -22
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +33 -17
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +28 -3
- package/src/hooks/__tests__/useFileDisplay.unit.test.ts +36 -9
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +83 -85
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +26 -2
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +19 -6
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -4
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +17 -4
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +26 -6
- package/src/hooks/__tests__/usePublicFileDisplay.test.ts +16 -6
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +3 -3
- package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +17 -3
- package/src/hooks/public/usePublicEvent.ts +7 -6
- package/src/hooks/public/usePublicEventLogo.ts +7 -4
- package/src/hooks/public/usePublicFileDisplay.ts +6 -150
- package/src/hooks/useComponentPerformance.ts +4 -1
- package/src/hooks/useDataTablePerformance.ts +4 -3
- package/src/hooks/useEventTheme.test.ts +18 -5
- package/src/hooks/useEventTheme.ts +4 -1
- package/src/hooks/useEvents.ts +2 -0
- package/src/hooks/useFileDisplay.ts +9 -8
- package/src/hooks/useFileReference.ts +4 -1
- package/src/hooks/useFileUrl.ts +4 -1
- package/src/hooks/useInactivityTracker.ts +5 -4
- package/src/hooks/useOrganisationSecurity.test.ts +33 -12
- package/src/hooks/useOrganisationSecurity.ts +8 -7
- package/src/hooks/usePerformanceMonitor.ts +6 -3
- package/src/hooks/usePermissionCache.ts +13 -6
- package/src/hooks/useSecureDataAccess.test.ts +2 -2
- package/src/hooks/useSecureDataAccess.ts +9 -8
- package/src/hooks/useSessionRestoration.ts +4 -1
- package/src/hooks/useStorage.ts +4 -1
- package/src/index.ts +20 -7
- package/src/providers/services/AuthServiceProvider.tsx +3 -2
- package/src/providers/services/EventServiceProvider.tsx +2 -1
- package/src/providers/services/InactivityServiceProvider.tsx +2 -1
- package/src/providers/services/OrganisationServiceProvider.tsx +2 -1
- package/src/providers/services/UnifiedAuthProvider.tsx +4 -3
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +22 -2
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +24 -2
- package/src/rbac/__tests__/cache-invalidation.test.ts +20 -6
- package/src/rbac/api.ts +5 -2
- package/src/rbac/audit-enhanced.ts +6 -6
- package/src/rbac/audit.test.ts +60 -38
- package/src/rbac/audit.ts +8 -8
- package/src/rbac/cache-invalidation.ts +7 -4
- package/src/rbac/components/EnhancedNavigationMenu.tsx +11 -5
- package/src/rbac/components/NavigationGuard.tsx +7 -3
- package/src/rbac/components/NavigationProvider.tsx +6 -3
- package/src/rbac/components/PagePermissionGuard.tsx +28 -16
- package/src/rbac/components/PagePermissionProvider.tsx +4 -1
- package/src/rbac/components/PermissionEnforcer.tsx +9 -3
- package/src/rbac/components/RoleBasedRouter.tsx +3 -1
- package/src/rbac/components/SecureDataProvider.tsx +7 -3
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +87 -61
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +83 -33
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +36 -13
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +2 -2
- package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +22 -8
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +19 -6
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +43 -17
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +42 -17
- package/src/rbac/engine.ts +15 -7
- package/src/rbac/hooks/usePermissions.ts +7 -3
- package/src/rbac/hooks/useResolvedScope.test.ts +2 -2
- package/src/rbac/hooks/useResolvedScope.ts +10 -7
- package/src/rbac/permissions.ts +5 -2
- package/src/rbac/security.test.ts +27 -16
- package/src/rbac/security.ts +5 -4
- package/src/services/AuthService.ts +22 -21
- package/src/services/EventService.ts +12 -12
- package/src/services/InactivityService.ts +5 -4
- package/src/services/OrganisationService.ts +26 -25
- package/src/services/__tests__/AuthService.test.ts +51 -19
- package/src/services/__tests__/EventService.test.ts +37 -5
- package/src/services/__tests__/InactivityService.test.ts +38 -4
- package/src/services/__tests__/OrganisationService.test.ts +3 -8
- package/src/services/base/BaseService.ts +3 -1
- package/src/styles/core.css +3 -0
- package/src/theming/__tests__/runtime.test.ts +21 -12
- package/src/theming/parseEventColours.ts +5 -19
- package/src/theming/runtime.ts +8 -4
- package/src/types/validation.ts +2 -29
- package/src/utils/__tests__/appConfig.unit.test.ts +1 -1
- package/src/utils/__tests__/audit.unit.test.ts +1 -1
- package/src/utils/__tests__/auth-utils.unit.test.ts +1 -1
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +19 -19
- package/src/utils/__tests__/cn.unit.test.ts +1 -1
- package/src/utils/__tests__/debugLogger.test.ts +1 -1
- package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -1
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -1
- package/src/utils/__tests__/formatting.unit.test.ts +1 -1
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +1 -1
- package/src/utils/__tests__/logger.unit.test.ts +1 -1
- package/src/utils/__tests__/organisationContext.unit.test.ts +1 -1
- package/src/utils/__tests__/performanceBenchmark.test.ts +1 -1
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +1 -1
- package/src/utils/__tests__/permissionTypes.unit.test.ts +1 -1
- package/src/utils/__tests__/permissionUtils.unit.test.ts +1 -1
- package/src/utils/__tests__/sanitization.unit.test.ts +1 -1
- package/src/utils/__tests__/schemaUtils.unit.test.ts +1 -1
- package/src/utils/__tests__/secureDataAccess.unit.test.ts +1 -1
- package/src/utils/__tests__/secureErrors.unit.test.ts +33 -15
- package/src/utils/__tests__/secureStorage.unit.test.ts +1 -1
- package/src/utils/__tests__/security.unit.test.ts +40 -18
- package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -1
- package/src/utils/__tests__/sessionTracking.unit.test.ts +40 -29
- package/src/utils/__tests__/validationUtils.unit.test.ts +19 -6
- package/src/utils/app/appConfig.ts +47 -0
- package/src/utils/app/appIdResolver.test.ts +497 -0
- package/src/utils/app/appIdResolver.ts +133 -0
- package/src/utils/app/appNameResolver.simple.test.ts +212 -0
- package/src/utils/app/appNameResolver.test.ts +121 -0
- package/src/utils/app/appNameResolver.ts +195 -0
- package/src/utils/audit/audit.ts +127 -0
- package/src/utils/context/organisationContext.test.ts +322 -0
- package/src/utils/context/organisationContext.ts +156 -0
- package/src/utils/context/sessionTracking.ts +125 -0
- package/src/utils/core/cn.ts +7 -0
- package/src/utils/core/debugLogger.ts +67 -0
- package/src/utils/core/logger.ts +181 -0
- package/src/utils/device/deviceFingerprint.ts +215 -0
- package/src/utils/dynamic/dynamicUtils.ts +105 -0
- package/src/utils/dynamic/lazyLoad.tsx +44 -0
- package/src/utils/file-reference/__tests__/file-reference.test.ts +788 -0
- package/src/utils/file-reference/index.ts +501 -0
- package/src/utils/formatting/formatDate.test.ts +237 -0
- package/src/utils/formatting/formatting.ts +133 -0
- package/src/utils/index.ts +39 -54
- package/src/utils/performance/bundleAnalysis.ts +129 -0
- package/src/utils/performance/performanceBenchmark.ts +64 -0
- package/src/utils/performance/performanceBudgets.ts +110 -0
- package/src/utils/permissions/permissionTypes.ts +37 -0
- package/src/utils/permissions/permissionUtils.test.ts +393 -0
- package/src/utils/permissions/permissionUtils.ts +34 -0
- package/src/utils/security/auth-utils.ts +96 -0
- package/src/utils/security/secureDataAccess.test.ts +711 -0
- package/src/utils/security/secureDataAccess.ts +377 -0
- package/src/utils/security/secureErrors.ts +82 -0
- package/src/utils/security/secureStorage.ts +244 -0
- package/src/utils/security/security.ts +159 -0
- package/src/utils/security/securityMonitor.ts +45 -0
- package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -4
- package/src/utils/storage/helpers.ts +15 -8
- package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +598 -0
- package/src/{validation → utils/validation}/csrf.ts +1 -1
- package/src/utils/validation/htmlSanitization.ts +184 -0
- package/src/utils/validation/index.ts +79 -0
- package/src/utils/validation/sanitization.ts +333 -0
- package/src/{validation/schemaUtils.ts → utils/validation/schema.ts} +11 -6
- package/src/{validation → utils/validation}/sqlInjectionProtection.ts +2 -0
- package/src/utils/validation/validation.ts +111 -0
- package/src/utils/validation/validationUtils.ts +123 -0
- package/src/validation/index.ts +3 -34
- package/dist/chunk-24MKLB7U.js +0 -81
- package/dist/chunk-24MKLB7U.js.map +0 -1
- package/dist/chunk-3CG5L6RN.js.map +0 -1
- package/dist/chunk-3DBFLLLU.js.map +0 -1
- package/dist/chunk-5F3NDPJV.js.map +0 -1
- package/dist/chunk-66C4BSAY.js.map +0 -1
- package/dist/chunk-BDZUMRBD.js +0 -87
- package/dist/chunk-BDZUMRBD.js.map +0 -1
- package/dist/chunk-BYXRHAIF.js.map +0 -1
- package/dist/chunk-CDQ3PX7L.js +0 -18
- package/dist/chunk-CDQ3PX7L.js.map +0 -1
- package/dist/chunk-CQZU6TFE.js.map +0 -1
- package/dist/chunk-F64FFPOZ.js.map +0 -1
- package/dist/chunk-GEVIB2UB.js.map +0 -1
- package/dist/chunk-GKHF54DI.js.map +0 -1
- package/dist/chunk-GVDR7WNV.js.map +0 -1
- package/dist/chunk-HMNOSGVA.js.map +0 -1
- package/dist/chunk-JCQZ6LA7.js.map +0 -1
- package/dist/chunk-M6DDYFUD.js.map +0 -1
- package/dist/chunk-O3NWNXDY.js.map +0 -1
- package/dist/chunk-PYUXFQJ3.js.map +0 -1
- package/dist/chunk-UJI6WSMD.js.map +0 -1
- package/dist/chunk-VZ5OR6HD.js.map +0 -1
- package/dist/chunk-WP5I5GLN.js.map +0 -1
- package/dist/chunk-ZYZCRSBD.js.map +0 -1
- package/dist/validation-DnhrNMju.d.ts +0 -159
- package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +0 -185
- package/src/validation/__tests__/common.unit.test.ts +0 -101
- package/src/validation/__tests__/csrf.unit.test.ts +0 -365
- package/src/validation/__tests__/passwordSchema.unit.test.ts +0 -203
- package/src/validation/__tests__/sanitization.unit.test.ts +0 -250
- package/src/validation/__tests__/schemaUtils.unit.test.ts +0 -451
- package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +0 -462
- package/src/validation/__tests__/user.unit.test.ts +0 -440
- package/src/validation/sanitization.ts +0 -96
- /package/dist/{DataTable-A36PJG6N.js.map → DataTable-6M4L6BI2.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-CQDZRJIS.js.map → UnifiedAuthProvider-XIQQ7LVU.js.map} +0 -0
- /package/dist/{api-TNIBJWLM.js.map → api-45XYYO2A.js.map} +0 -0
- /package/dist/{audit-T36HM7IM.js.map → audit-64X3VJXB.js.map} +0 -0
- /package/dist/{chunk-CTJRBUX2.js.map → chunk-6LAAY47Q.js.map} +0 -0
- /package/dist/{chunk-ZV77RZMU.js.map → chunk-INQLMHPF.js.map} +0 -0
- /package/dist/{useInactivityTracker-MRUU55XI.js.map → useInactivityTracker-TO6ZOF35.js.map} +0 -0
- /package/src/{validation → utils/validation}/common.ts +0 -0
- /package/src/{validation → utils/validation}/passwordSchema.ts +0 -0
- /package/src/{validation → utils/validation}/user.ts +0 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file formatDate Utility Tests
|
|
3
|
+
* @description Comprehensive tests for the formatDate utility function
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import { formatDate } from './formatting';
|
|
8
|
+
|
|
9
|
+
describe('formatDate Utility', () => {
|
|
10
|
+
let originalLocale: string;
|
|
11
|
+
let originalTimezone: string;
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
// Store original values
|
|
15
|
+
originalLocale = Intl.DateTimeFormat().resolvedOptions().locale;
|
|
16
|
+
originalTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('Date Object Input', () => {
|
|
20
|
+
it('formats a Date object correctly', () => {
|
|
21
|
+
const date = new Date('2024-01-15T10:30:00.000Z');
|
|
22
|
+
const result = formatDate(date);
|
|
23
|
+
|
|
24
|
+
expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('formats different Date objects', () => {
|
|
28
|
+
const dates = [
|
|
29
|
+
new Date('2023-12-25T00:00:00.000Z'),
|
|
30
|
+
new Date('2024-06-15T12:00:00.000Z'),
|
|
31
|
+
new Date('2024-12-31T23:59:59.999Z')
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
dates.forEach(date => {
|
|
35
|
+
const result = formatDate(date);
|
|
36
|
+
expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('String Input', () => {
|
|
42
|
+
it('formats ISO date strings correctly', () => {
|
|
43
|
+
const result = formatDate('2024-01-15T10:30:00.000Z');
|
|
44
|
+
expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('formats date-only strings correctly', () => {
|
|
48
|
+
const result = formatDate('2024-01-15');
|
|
49
|
+
expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('formats various date string formats', () => {
|
|
53
|
+
const dateStrings = [
|
|
54
|
+
'2024-01-15',
|
|
55
|
+
'2024-01-15T10:30:00Z',
|
|
56
|
+
'2024-01-15T10:30:00.000Z',
|
|
57
|
+
'2024-01-15T10:30:00+00:00'
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
dateStrings.forEach(dateString => {
|
|
61
|
+
const result = formatDate(dateString);
|
|
62
|
+
expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('Number Input', () => {
|
|
68
|
+
it('formats timestamp numbers correctly', () => {
|
|
69
|
+
const timestamp = new Date('2024-01-15T10:30:00.000Z').getTime();
|
|
70
|
+
const result = formatDate(timestamp);
|
|
71
|
+
expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('formats Unix timestamps correctly', () => {
|
|
75
|
+
const unixTimestamp = Math.floor(new Date('2024-01-15T10:30:00.000Z').getTime() / 1000);
|
|
76
|
+
const result = formatDate(unixTimestamp * 1000); // Convert back to milliseconds
|
|
77
|
+
expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('Edge Cases', () => {
|
|
82
|
+
it('handles invalid date strings gracefully', () => {
|
|
83
|
+
const invalidDates = [
|
|
84
|
+
'invalid-date',
|
|
85
|
+
'not-a-date',
|
|
86
|
+
'2024-13-45', // Invalid month and day
|
|
87
|
+
'2024-02-30' // Invalid day for February
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
invalidDates.forEach(invalidDate => {
|
|
91
|
+
const result = formatDate(invalidDate);
|
|
92
|
+
// Should return a string even for invalid dates (may be "Invalid Date")
|
|
93
|
+
expect(typeof result).toBe('string');
|
|
94
|
+
expect(result.length).toBeGreaterThan(0);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('handles empty string input', () => {
|
|
99
|
+
const result = formatDate('');
|
|
100
|
+
expect(typeof result).toBe('string');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('handles null and undefined input', () => {
|
|
104
|
+
// @ts-expect-error - Testing runtime behavior with invalid types
|
|
105
|
+
expect(() => formatDate(null)).toThrow();
|
|
106
|
+
// @ts-expect-error - Testing runtime behavior with invalid types
|
|
107
|
+
expect(() => formatDate(undefined)).toThrow();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('handles very large numbers', () => {
|
|
111
|
+
const largeNumber = Number.MAX_SAFE_INTEGER;
|
|
112
|
+
const result = formatDate(largeNumber);
|
|
113
|
+
expect(typeof result).toBe('string');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('handles negative numbers', () => {
|
|
117
|
+
const negativeNumber = -1000000;
|
|
118
|
+
const result = formatDate(negativeNumber);
|
|
119
|
+
expect(typeof result).toBe('string');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('handles zero', () => {
|
|
123
|
+
const result = formatDate(0);
|
|
124
|
+
expect(typeof result).toBe('string');
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('Format Consistency', () => {
|
|
129
|
+
it('returns consistent format for same date', () => {
|
|
130
|
+
const date = new Date('2024-01-15T10:30:00.000Z');
|
|
131
|
+
const result1 = formatDate(date);
|
|
132
|
+
const result2 = formatDate(date);
|
|
133
|
+
|
|
134
|
+
expect(result1).toBe(result2);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('returns consistent format across different input types for same date', () => {
|
|
138
|
+
const date = new Date('2024-01-15T10:30:00.000Z');
|
|
139
|
+
const dateString = '2024-01-15T10:30:00.000Z';
|
|
140
|
+
const timestamp = date.getTime();
|
|
141
|
+
|
|
142
|
+
const result1 = formatDate(date);
|
|
143
|
+
const result2 = formatDate(dateString);
|
|
144
|
+
const result3 = formatDate(timestamp);
|
|
145
|
+
|
|
146
|
+
expect(result1).toBe(result2);
|
|
147
|
+
expect(result2).toBe(result3);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('Locale Handling', () => {
|
|
152
|
+
it('uses default locale when no locale is specified', () => {
|
|
153
|
+
const date = new Date('2024-01-15T10:30:00.000Z');
|
|
154
|
+
const result = formatDate(date);
|
|
155
|
+
|
|
156
|
+
// Should use the default locale format
|
|
157
|
+
expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('handles different locales correctly', () => {
|
|
161
|
+
const date = new Date('2024-01-15T10:30:00.000Z');
|
|
162
|
+
|
|
163
|
+
const result = formatDate(date);
|
|
164
|
+
expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe('Time Zone Handling', () => {
|
|
169
|
+
it('handles different time zones correctly', () => {
|
|
170
|
+
const date = new Date('2024-01-15T10:30:00.000Z');
|
|
171
|
+
const result = formatDate(date);
|
|
172
|
+
|
|
173
|
+
// Should format consistently regardless of timezone
|
|
174
|
+
expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
describe('Performance', () => {
|
|
179
|
+
it('handles large number of calls efficiently', () => {
|
|
180
|
+
const date = new Date('2024-01-15T10:30:00.000Z');
|
|
181
|
+
const startTime = performance.now();
|
|
182
|
+
|
|
183
|
+
// Call formatDate many times
|
|
184
|
+
for (let i = 0; i < 1000; i++) {
|
|
185
|
+
formatDate(date);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const endTime = performance.now();
|
|
189
|
+
const duration = endTime - startTime;
|
|
190
|
+
|
|
191
|
+
// Should complete in reasonable time (less than 200ms for 1000 calls)
|
|
192
|
+
expect(duration).toBeLessThan(200);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe('Type Safety', () => {
|
|
197
|
+
it('accepts valid Date types', () => {
|
|
198
|
+
const date = new Date();
|
|
199
|
+
expect(() => formatDate(date)).not.toThrow();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('accepts valid string types', () => {
|
|
203
|
+
const dateString = '2024-01-15';
|
|
204
|
+
expect(() => formatDate(dateString)).not.toThrow();
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('accepts valid number types', () => {
|
|
208
|
+
const timestamp = Date.now();
|
|
209
|
+
expect(() => formatDate(timestamp)).not.toThrow();
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
describe('Return Value', () => {
|
|
214
|
+
it('returns a string', () => {
|
|
215
|
+
const date = new Date('2024-01-15T10:30:00.000Z');
|
|
216
|
+
const result = formatDate(date);
|
|
217
|
+
|
|
218
|
+
expect(typeof result).toBe('string');
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('returns non-empty string for valid dates', () => {
|
|
222
|
+
const date = new Date('2024-01-15T10:30:00.000Z');
|
|
223
|
+
const result = formatDate(date);
|
|
224
|
+
|
|
225
|
+
expect(result).toBeTruthy();
|
|
226
|
+
expect(result.length).toBeGreaterThan(0);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('returns expected format pattern', () => {
|
|
230
|
+
const date = new Date('2024-01-15T10:30:00.000Z');
|
|
231
|
+
const result = formatDate(date);
|
|
232
|
+
|
|
233
|
+
// Should match pattern: "MMM DD, YYYY"
|
|
234
|
+
expect(result).toMatch(/^\d{1,2} [A-Za-z]{3} \d{4}$/);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
});
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for formatting data in the application
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Format a date as a readable string in "dd mmm yyyy" format (e.g., "15 Jun 2024")
|
|
7
|
+
*/
|
|
8
|
+
export function formatDate(date: Date | string | number): string {
|
|
9
|
+
const dateObj = typeof date === 'string' || typeof date === 'number'
|
|
10
|
+
? new Date(date)
|
|
11
|
+
: date;
|
|
12
|
+
|
|
13
|
+
// Use 'en-GB' locale to ensure "dd mmm yyyy" format (e.g., "15 Jun 2024")
|
|
14
|
+
return dateObj.toLocaleDateString('en-GB', {
|
|
15
|
+
year: 'numeric',
|
|
16
|
+
month: 'short',
|
|
17
|
+
day: 'numeric'
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Format a number as a currency
|
|
23
|
+
*/
|
|
24
|
+
export function formatCurrency(value: number, currencyCode = 'USD', locale = 'en-US'): string {
|
|
25
|
+
return new Intl.NumberFormat(locale, {
|
|
26
|
+
style: 'currency',
|
|
27
|
+
currency: currencyCode,
|
|
28
|
+
}).format(value);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Format a number with custom options
|
|
33
|
+
*/
|
|
34
|
+
export function formatNumber(
|
|
35
|
+
value: number,
|
|
36
|
+
options: Intl.NumberFormatOptions = {},
|
|
37
|
+
locale = 'en-US'
|
|
38
|
+
): string {
|
|
39
|
+
return new Intl.NumberFormat(locale, options).format(value);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Format a number as a percentage.
|
|
44
|
+
*
|
|
45
|
+
* The third parameter can be either:
|
|
46
|
+
* - A number for fixed decimal places (backward compatible): `formatPercent(0.81, 'en-US', 2)`
|
|
47
|
+
* - An options object with:
|
|
48
|
+
* - `decimals`: Fixed number of decimal places (default: 1)
|
|
49
|
+
* - `preserveDecimals`: Auto-detect and preserve decimal places from the input value
|
|
50
|
+
* - `maxDecimals`: Maximum decimal places when preserving (default: 10)
|
|
51
|
+
*
|
|
52
|
+
* @param value - The percentage value as a decimal (e.g., 0.81 for 0.81%)
|
|
53
|
+
* @param locale - The locale string (default: 'en-US')
|
|
54
|
+
* @param decimalsOrOptions - Either a number for fixed decimals, or an options object with:
|
|
55
|
+
* - `decimals` - Fixed number of decimal places (default: 1)
|
|
56
|
+
* - `preserveDecimals` - Auto-detect and preserve decimal places from the input value
|
|
57
|
+
* - `maxDecimals` - Maximum decimal places when preserving (default: 10)
|
|
58
|
+
* @returns Formatted percentage string (e.g., "0.81%", "81%")
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* // Fixed decimals (default behavior)
|
|
63
|
+
* formatPercent(0.5) // '0.5%'
|
|
64
|
+
* formatPercent(0.81, 'en-US', 1) // '0.8%' (loses precision)
|
|
65
|
+
*
|
|
66
|
+
* // Preserve decimal places dynamically
|
|
67
|
+
* formatPercent(0.81, 'en-US', { preserveDecimals: true }) // '0.81%'
|
|
68
|
+
* formatPercent(0.8123, 'en-US', { preserveDecimals: true, maxDecimals: 2 }) // '0.81%'
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export function formatPercent(
|
|
72
|
+
value: number,
|
|
73
|
+
locale: string = 'en-US',
|
|
74
|
+
decimalsOrOptions?: number | {
|
|
75
|
+
decimals?: number;
|
|
76
|
+
preserveDecimals?: boolean;
|
|
77
|
+
maxDecimals?: number;
|
|
78
|
+
}
|
|
79
|
+
): string {
|
|
80
|
+
let decimals: number;
|
|
81
|
+
|
|
82
|
+
// Backward compatibility: if decimalsOrOptions is a number, use it directly
|
|
83
|
+
if (typeof decimalsOrOptions === 'number') {
|
|
84
|
+
decimals = decimalsOrOptions;
|
|
85
|
+
} else if (decimalsOrOptions && typeof decimalsOrOptions === 'object') {
|
|
86
|
+
// New options object: check if we should preserve decimals
|
|
87
|
+
if (decimalsOrOptions.preserveDecimals) {
|
|
88
|
+
const valueStr = value.toString();
|
|
89
|
+
const decimalIndex = valueStr.indexOf('.');
|
|
90
|
+
|
|
91
|
+
if (decimalIndex !== -1) {
|
|
92
|
+
const detectedDecimals = valueStr.length - decimalIndex - 1;
|
|
93
|
+
const maxDecimals = decimalsOrOptions.maxDecimals ?? 10;
|
|
94
|
+
decimals = Math.min(detectedDecimals, maxDecimals);
|
|
95
|
+
} else {
|
|
96
|
+
decimals = 0;
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
decimals = decimalsOrOptions.decimals ?? 1;
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
decimals = 1;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return new Intl.NumberFormat(locale, {
|
|
106
|
+
style: 'percent',
|
|
107
|
+
minimumFractionDigits: decimals,
|
|
108
|
+
maximumFractionDigits: decimals,
|
|
109
|
+
}).format(value / 100);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Format a large number with abbreviations (K, M, B)
|
|
114
|
+
*/
|
|
115
|
+
export function formatCompactNumber(value: number, locale = 'en-US'): string {
|
|
116
|
+
return new Intl.NumberFormat(locale, {
|
|
117
|
+
notation: 'compact',
|
|
118
|
+
compactDisplay: 'short'
|
|
119
|
+
}).format(value);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Format a file size in bytes to a human-readable string
|
|
124
|
+
*/
|
|
125
|
+
export function formatFileSize(bytes: number): string {
|
|
126
|
+
if (bytes === 0) return '0 Bytes';
|
|
127
|
+
|
|
128
|
+
const k = 1024;
|
|
129
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
|
130
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
131
|
+
|
|
132
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
133
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -6,39 +6,57 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
// Core utilities
|
|
9
|
-
export { cn } from './cn';
|
|
10
|
-
export { DebugLogger } from './debugLogger';
|
|
9
|
+
export { cn } from './core/cn';
|
|
10
|
+
export { DebugLogger } from './core/debugLogger';
|
|
11
|
+
export { Logger, logger, createLogger, LogLevel } from './core/logger';
|
|
12
|
+
export type { LoggerConfig } from './core/logger';
|
|
11
13
|
|
|
12
14
|
// App configuration utilities
|
|
13
|
-
export * from './appNameResolver';
|
|
14
|
-
export
|
|
15
|
+
export * from './app/appNameResolver';
|
|
16
|
+
export { setAppConfig, getAppConfig, getCurrentAppId } from './app/appConfig';
|
|
17
|
+
export * from './app/appIdResolver';
|
|
15
18
|
|
|
16
19
|
// Validation and sanitization
|
|
17
20
|
export * from './validation';
|
|
18
|
-
export
|
|
19
|
-
|
|
21
|
+
// Explicitly re-export commonly used validation utilities to ensure they're available
|
|
22
|
+
// Import from source modules to avoid re-export issues
|
|
23
|
+
export { validateUserInput, usernameSchema } from './validation/validationUtils';
|
|
24
|
+
export { sanitizeUserInput, sanitizeFormData } from './validation/sanitization';
|
|
25
|
+
export { emailSchema, nameSchema, phoneSchema, urlSchema } from './validation/common';
|
|
26
|
+
export { passwordSchema } from './validation/passwordSchema';
|
|
27
|
+
export { pickSchema, combineSchemas } from './validation/schema';
|
|
20
28
|
|
|
21
29
|
// Security utilities
|
|
22
30
|
export {
|
|
23
31
|
getSecurityHeaders,
|
|
24
32
|
validateSecurityHeaders
|
|
25
|
-
} from './security';
|
|
33
|
+
} from './security/security';
|
|
34
|
+
export type { SecurityEvent } from './security/security';
|
|
26
35
|
|
|
27
|
-
//
|
|
28
|
-
|
|
36
|
+
// Security monitoring utilities
|
|
37
|
+
export {
|
|
38
|
+
securityMonitor
|
|
39
|
+
} from './security/securityMonitor';
|
|
40
|
+
export type { SecureDataAccess } from './security/secureDataAccess';
|
|
29
41
|
|
|
30
42
|
// Performance utilities
|
|
31
43
|
export { useComponentPerformance } from '../hooks/useComponentPerformance';
|
|
32
44
|
export { PERFORMANCE_THRESHOLDS } from '../constants/performance';
|
|
33
|
-
export { createPerformanceBenchmark, measureRenderPerformance } from './performanceBenchmark';
|
|
34
|
-
export type { PerformanceMetrics } from './performanceBenchmark';
|
|
45
|
+
export { createPerformanceBenchmark, measureRenderPerformance } from './performance/performanceBenchmark';
|
|
46
|
+
export type { PerformanceMetrics } from './performance/performanceBenchmark';
|
|
35
47
|
|
|
36
48
|
// Bundle analysis utilities
|
|
37
49
|
export {
|
|
38
50
|
bundleAnalyzer,
|
|
39
51
|
validateImportPattern,
|
|
40
52
|
trackDynamicImport
|
|
41
|
-
} from './bundleAnalysis';
|
|
53
|
+
} from './performance/bundleAnalysis';
|
|
54
|
+
|
|
55
|
+
// Performance budget utilities
|
|
56
|
+
export {
|
|
57
|
+
performanceBudgetMonitor,
|
|
58
|
+
PERFORMANCE_BUDGETS
|
|
59
|
+
} from './performance/performanceBudgets';
|
|
42
60
|
|
|
43
61
|
// Dynamic utility loaders
|
|
44
62
|
export {
|
|
@@ -53,25 +71,10 @@ export {
|
|
|
53
71
|
lazyChartUtils,
|
|
54
72
|
lazyFormUtils,
|
|
55
73
|
lazyCSVUtils
|
|
56
|
-
} from './dynamicUtils';
|
|
57
|
-
|
|
58
|
-
// Performance budget utilities
|
|
59
|
-
export {
|
|
60
|
-
performanceBudgetMonitor,
|
|
61
|
-
PERFORMANCE_BUDGETS
|
|
62
|
-
} from './performanceBudgets';
|
|
74
|
+
} from './dynamic/dynamicUtils';
|
|
63
75
|
|
|
64
76
|
// Lazy loading utilities
|
|
65
|
-
export { createLazyComponent, LazyDataTable } from './lazyLoad';
|
|
66
|
-
|
|
67
|
-
// App configuration utilities
|
|
68
|
-
export {
|
|
69
|
-
setAppConfig,
|
|
70
|
-
getAppConfig,
|
|
71
|
-
getCurrentAppName,
|
|
72
|
-
getCurrentAppId
|
|
73
|
-
} from './appConfig';
|
|
74
|
-
export type { AppConfig } from './appConfig';
|
|
77
|
+
export { createLazyComponent, LazyDataTable } from './dynamic/lazyLoad';
|
|
75
78
|
|
|
76
79
|
// Permission utilities
|
|
77
80
|
export {
|
|
@@ -79,30 +82,18 @@ export {
|
|
|
79
82
|
hasPermission,
|
|
80
83
|
hasAnyPermission,
|
|
81
84
|
hasAllPermissions
|
|
82
|
-
} from './permissionUtils';
|
|
85
|
+
} from './permissions/permissionUtils';
|
|
83
86
|
|
|
84
87
|
// Permission types
|
|
85
88
|
export {
|
|
86
89
|
PermissionType,
|
|
87
90
|
parsePermission
|
|
88
|
-
} from './permissionTypes';
|
|
89
|
-
|
|
90
|
-
// Schema utilities
|
|
91
|
-
export {
|
|
92
|
-
pickSchema,
|
|
93
|
-
combineSchemas
|
|
94
|
-
} from './schemaUtils';
|
|
95
|
-
|
|
96
|
-
// Security monitoring utilities
|
|
97
|
-
export {
|
|
98
|
-
securityMonitor
|
|
99
|
-
} from './securityMonitor';
|
|
100
|
-
export type { SecureDataAccess } from './secureDataAccess';
|
|
91
|
+
} from './permissions/permissionTypes';
|
|
101
92
|
|
|
102
93
|
// Session tracking utilities
|
|
103
94
|
export {
|
|
104
95
|
useSessionTracking
|
|
105
|
-
} from './sessionTracking';
|
|
96
|
+
} from './context/sessionTracking';
|
|
106
97
|
|
|
107
98
|
// Audit utilities
|
|
108
99
|
export {
|
|
@@ -112,14 +103,13 @@ export {
|
|
|
112
103
|
logPermissionEvent,
|
|
113
104
|
logSecurityEvent,
|
|
114
105
|
logAuditEvent
|
|
115
|
-
} from './audit';
|
|
106
|
+
} from './audit/audit';
|
|
116
107
|
|
|
117
108
|
// Device fingerprinting utilities
|
|
118
109
|
export {
|
|
119
110
|
generateDeviceFingerprint,
|
|
120
111
|
validateDeviceFingerprint
|
|
121
|
-
} from './deviceFingerprint';
|
|
122
|
-
|
|
112
|
+
} from './device/deviceFingerprint';
|
|
123
113
|
|
|
124
114
|
// Formatting utilities
|
|
125
115
|
export {
|
|
@@ -129,7 +119,7 @@ export {
|
|
|
129
119
|
formatPercent,
|
|
130
120
|
formatCompactNumber,
|
|
131
121
|
formatFileSize
|
|
132
|
-
} from './formatting';
|
|
122
|
+
} from './formatting/formatting';
|
|
133
123
|
|
|
134
124
|
// Organisation context utilities
|
|
135
125
|
export {
|
|
@@ -137,9 +127,4 @@ export {
|
|
|
137
127
|
clearOrganisationContext,
|
|
138
128
|
getOrganisationContext,
|
|
139
129
|
isOrganisationContextAvailable
|
|
140
|
-
} from './organisationContext';
|
|
141
|
-
|
|
142
|
-
// Re-export types for convenience
|
|
143
|
-
export type {
|
|
144
|
-
SecurityEvent
|
|
145
|
-
} from './security';
|
|
130
|
+
} from './context/organisationContext';
|
|
@@ -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
|
+
}
|