@vlian/framework 1.2.56 → 1.2.59
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/README.md +15 -3
- package/dist/analytics/index.cjs +0 -2
- package/dist/analytics/index.js +1 -3
- package/dist/analytics.umd.js +8 -208
- package/dist/components/LocaleSwitch.cjs +0 -2
- package/dist/components/LocaleSwitch.js +1 -103
- package/dist/components/ThemeSwitch.cjs +0 -2
- package/dist/components/ThemeSwitch.js +1 -102
- package/dist/components/index.cjs +0 -2
- package/dist/components/index.js +1 -4
- package/dist/components/persistence.cjs +0 -2
- package/dist/components/persistence.js +1 -39
- package/dist/core/Test.cjs +0 -2
- package/dist/core/Test.js +1 -15
- package/dist/core/app/AppContext.cjs +0 -2
- package/dist/core/app/AppContext.js +1 -339
- package/dist/core/app/AppContext.types.cjs +0 -2
- package/dist/core/app/AppContext.types.js +1 -5
- package/dist/core/app/BasicLayout.cjs +0 -2
- package/dist/core/app/BasicLayout.js +1 -74
- package/dist/core/app/DefaultApp.cjs +0 -2
- package/dist/core/app/DefaultApp.js +1 -143
- package/dist/core/app/index.cjs +0 -2
- package/dist/core/app/index.js +1 -7
- package/dist/core/config/AppConfig.cjs +0 -2
- package/dist/core/config/AppConfig.js +1 -133
- package/dist/core/config/ConfigLoader.cjs +0 -2
- package/dist/core/config/ConfigLoader.js +1 -311
- package/dist/core/config/ConfigValidator.cjs +0 -2
- package/dist/core/config/ConfigValidator.js +2 -121
- package/dist/core/config/index.cjs +0 -2
- package/dist/core/config/index.js +1 -7
- package/dist/core/dev/DevTools.cjs +0 -2
- package/dist/core/dev/DevTools.js +1 -210
- package/dist/core/error/ErrorBoundary.cjs +0 -2
- package/dist/core/error/ErrorBoundary.js +1 -399
- package/dist/core/error/ErrorHandler.cjs +0 -2
- package/dist/core/error/ErrorHandler.js +1 -261
- package/dist/core/error/index.cjs +0 -2
- package/dist/core/error/index.js +1 -6
- package/dist/core/event/AppEventBus.cjs +0 -2
- package/dist/core/event/AppEventBus.js +1 -438
- package/dist/core/event/frameworkEvents.cjs +0 -2
- package/dist/core/event/frameworkEvents.js +1 -135
- package/dist/core/event/hooks.cjs +0 -2
- package/dist/core/event/hooks.js +1 -95
- package/dist/core/event/index.cjs +0 -2
- package/dist/core/event/index.js +1 -10
- package/dist/core/event/types.cjs +0 -2
- package/dist/core/event/types.js +1 -56
- package/dist/core/event/useEventBus.cjs +0 -2
- package/dist/core/event/useEventBus.js +1 -39
- package/dist/core/index.cjs +0 -2
- package/dist/core/index.js +1 -69
- package/dist/core/initialization/InitializationErrorThrower.cjs +0 -2
- package/dist/core/initialization/InitializationErrorThrower.js +1 -30
- package/dist/core/initialization/index.cjs +0 -2
- package/dist/core/initialization/index.js +1 -7
- package/dist/core/initialization/initialization.cjs +0 -2
- package/dist/core/initialization/initialization.js +1 -78
- package/dist/core/initialization/initializationErrorState.cjs +0 -2
- package/dist/core/initialization/initializationErrorState.js +1 -60
- package/dist/core/kernel/defaultAdapters.cjs +0 -2
- package/dist/core/kernel/defaultAdapters.js +1 -176
- package/dist/core/kernel/errors.cjs +0 -2
- package/dist/core/kernel/errors.js +1 -53
- package/dist/core/kernel/index.cjs +0 -2
- package/dist/core/kernel/index.js +1 -4
- package/dist/core/kernel/startKernel.cjs +0 -2
- package/dist/core/kernel/startKernel.js +1 -192
- package/dist/core/kernel/types.cjs +0 -2
- package/dist/core/kernel/types.js +1 -3
- package/dist/core/middleware.cjs +0 -2
- package/dist/core/middleware.js +1 -61
- package/dist/core/plugin/PluginEventBus.cjs +0 -2
- package/dist/core/plugin/PluginEventBus.js +1 -286
- package/dist/core/plugin/PluginSandbox.cjs +0 -2
- package/dist/core/plugin/PluginSandbox.js +1 -125
- package/dist/core/plugin.cjs +0 -2
- package/dist/core/plugin.js +1 -438
- package/dist/core/router/RouterManager.cjs +0 -2
- package/dist/core/router/RouterManager.js +1 -272
- package/dist/core/router/adapter/AdapterManager.cjs +0 -2
- package/dist/core/router/adapter/AdapterManager.js +1 -221
- package/dist/core/router/adapter/index.cjs +0 -2
- package/dist/core/router/adapter/index.js +1 -7
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.cjs +0 -2
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.js +1 -116
- package/dist/core/router/adapter/react-router/index.cjs +0 -2
- package/dist/core/router/adapter/react-router/index.js +1 -5
- package/dist/core/router/adapter/types.cjs +0 -2
- package/dist/core/router/adapter/types.js +1 -7
- package/dist/core/router/dev/RouterDevTools.cjs +0 -2
- package/dist/core/router/dev/RouterDevTools.js +1 -211
- package/dist/core/router/dev/index.cjs +0 -2
- package/dist/core/router/dev/index.js +1 -5
- package/dist/core/router/dynamic/DynamicRouteManager.cjs +0 -2
- package/dist/core/router/dynamic/DynamicRouteManager.js +1 -179
- package/dist/core/router/dynamic/index.cjs +0 -2
- package/dist/core/router/dynamic/index.js +1 -5
- package/dist/core/router/errors/RouterError.cjs +0 -2
- package/dist/core/router/errors/RouterError.js +1 -48
- package/dist/core/router/errors/index.cjs +0 -2
- package/dist/core/router/errors/index.js +1 -5
- package/dist/core/router/index.cjs +0 -2
- package/dist/core/router/index.js +1 -32
- package/dist/core/router/lifecycle/RouterLifecycleManager.cjs +0 -2
- package/dist/core/router/lifecycle/RouterLifecycleManager.js +1 -130
- package/dist/core/router/lifecycle/index.cjs +0 -2
- package/dist/core/router/lifecycle/index.js +1 -5
- package/dist/core/router/middleware/RouterMiddlewareManager.cjs +0 -2
- package/dist/core/router/middleware/RouterMiddlewareManager.js +1 -179
- package/dist/core/router/middleware/auth.cjs +0 -2
- package/dist/core/router/middleware/auth.js +1 -63
- package/dist/core/router/middleware/index.cjs +0 -2
- package/dist/core/router/middleware/index.js +1 -7
- package/dist/core/router/middleware/types.cjs +0 -2
- package/dist/core/router/middleware/types.js +1 -7
- package/dist/core/router/monitoring/RouterMonitoring.cjs +0 -2
- package/dist/core/router/monitoring/RouterMonitoring.js +1 -213
- package/dist/core/router/monitoring/index.cjs +0 -2
- package/dist/core/router/monitoring/index.js +1 -5
- package/dist/core/router/navigation/RouterNavigation.cjs +0 -2
- package/dist/core/router/navigation/RouterNavigation.js +1 -192
- package/dist/core/router/navigation/index.cjs +0 -2
- package/dist/core/router/navigation/index.js +1 -5
- package/dist/core/router/performance/RouteCache.cjs +0 -2
- package/dist/core/router/performance/RouteCache.js +1 -291
- package/dist/core/router/performance/RoutePreloader.cjs +0 -2
- package/dist/core/router/performance/RoutePreloader.js +1 -277
- package/dist/core/router/performance/index.cjs +0 -2
- package/dist/core/router/performance/index.js +1 -6
- package/dist/core/router/plugin/RouterPluginManager.cjs +0 -2
- package/dist/core/router/plugin/RouterPluginManager.js +1 -248
- package/dist/core/router/plugin/index.cjs +0 -2
- package/dist/core/router/plugin/index.js +1 -6
- package/dist/core/router/plugin/types.cjs +0 -2
- package/dist/core/router/plugin/types.js +1 -33
- package/dist/core/router/types.cjs +0 -2
- package/dist/core/router/types.js +1 -5
- package/dist/core/router/utils/adapters/react-router/RouteErrorBoundary.cjs +0 -2
- package/dist/core/router/utils/adapters/react-router/RouteErrorBoundary.js +1 -121
- package/dist/core/router/utils/adapters/react-router/transform.cjs +0 -2
- package/dist/core/router/utils/adapters/react-router/transform.js +1 -242
- package/dist/core/router/utils/transform.cjs +0 -2
- package/dist/core/router/utils/transform.js +1 -791
- package/dist/core/router/validation/RouterConfigValidator.cjs +0 -2
- package/dist/core/router/validation/RouterConfigValidator.js +2 -77
- package/dist/core/router/validation/index.cjs +0 -2
- package/dist/core/router/validation/index.js +1 -6
- package/dist/core/router/validation/schema.cjs +0 -2
- package/dist/core/router/validation/schema.js +1 -151
- package/dist/core/router/version/RouteVersionManager.cjs +0 -2
- package/dist/core/router/version/RouteVersionManager.js +1 -191
- package/dist/core/router/version/index.cjs +0 -2
- package/dist/core/router/version/index.js +1 -5
- package/dist/core/splash/SplashScreen.cjs +0 -2
- package/dist/core/splash/SplashScreen.js +1 -293
- package/dist/core/splash/index.cjs +0 -2
- package/dist/core/splash/index.js +1 -6
- package/dist/core/splash/splashScreenUtils.cjs +0 -2
- package/dist/core/splash/splashScreenUtils.js +1 -30
- package/dist/core/startup/AppInstance.cjs +0 -2
- package/dist/core/startup/AppInstance.js +1 -226
- package/dist/core/startup/environment.cjs +0 -2
- package/dist/core/startup/environment.js +1 -154
- package/dist/core/startup/index.cjs +0 -2
- package/dist/core/startup/index.js +1 -8
- package/dist/core/startup/initializeServices.cjs +0 -2
- package/dist/core/startup/initializeServices.js +1 -188
- package/dist/core/startup/performanceTracker.cjs +0 -2
- package/dist/core/startup/performanceTracker.js +1 -167
- package/dist/core/startup/renderApp.cjs +0 -2
- package/dist/core/startup/renderApp.js +1 -267
- package/dist/core/startup/startApp.cjs +0 -2
- package/dist/core/startup/startApp.js +1 -315
- package/dist/core/types.cjs +0 -2
- package/dist/core/types.js +1 -5
- package/dist/index.cjs +0 -2
- package/dist/index.js +1 -11
- package/dist/index.umd.cjs +0 -2
- package/dist/index.umd.js +362 -13230
- package/dist/kernel/constants.cjs +0 -2
- package/dist/kernel/constants.js +1 -43
- package/dist/kernel/index.cjs +0 -2
- package/dist/kernel/index.js +1 -4
- package/dist/kernel/kernel.cjs +1 -3
- package/dist/kernel/kernel.js +1 -273
- package/dist/kernel/manager/cacheManager.cjs +0 -2
- package/dist/kernel/manager/cacheManager.js +1 -38
- package/dist/kernel/manager/i18n/I18nManager.cjs +0 -2
- package/dist/kernel/manager/i18n/I18nManager.js +1 -83
- package/dist/kernel/manager/i18n/i18n.persistence.cjs +4 -3
- package/dist/kernel/manager/i18n/i18n.persistence.js +1 -38
- package/dist/kernel/manager/i18n/i18n.schema.cjs +0 -2
- package/dist/kernel/manager/i18n/i18n.schema.js +1 -64
- package/dist/kernel/manager/i18n/index.cjs +0 -2
- package/dist/kernel/manager/i18n/index.js +1 -3
- package/dist/kernel/manager/i18nManager.cjs +0 -2
- package/dist/kernel/manager/i18nManager.js +1 -3
- package/dist/kernel/manager/index.cjs +0 -2
- package/dist/kernel/manager/index.js +1 -6
- package/dist/kernel/manager/logger/LoggerManager.cjs +0 -2
- package/dist/kernel/manager/logger/LoggerManager.js +1 -99
- package/dist/kernel/manager/logger/index.cjs +0 -2
- package/dist/kernel/manager/logger/index.js +1 -3
- package/dist/kernel/manager/logger/logger.persistence.cjs +0 -2
- package/dist/kernel/manager/logger/logger.persistence.js +1 -43
- package/dist/kernel/manager/logger/logger.schema.cjs +0 -2
- package/dist/kernel/manager/logger/logger.schema.js +1 -55
- package/dist/kernel/manager/loggerManager.cjs +0 -2
- package/dist/kernel/manager/loggerManager.js +1 -3
- package/dist/kernel/manager/theme/ThemeManager.cjs +0 -2
- package/dist/kernel/manager/theme/ThemeManager.js +1 -76
- package/dist/kernel/manager/theme/index.cjs +0 -2
- package/dist/kernel/manager/theme/index.js +1 -3
- package/dist/kernel/manager/theme/theme.dom.cjs +0 -2
- package/dist/kernel/manager/theme/theme.dom.js +1 -45
- package/dist/kernel/manager/theme/theme.persistence.cjs +0 -2
- package/dist/kernel/manager/theme/theme.persistence.js +1 -38
- package/dist/kernel/manager/theme/theme.schema.cjs +0 -2
- package/dist/kernel/manager/theme/theme.schema.js +1 -97
- package/dist/kernel/manager/themeManager.cjs +0 -2
- package/dist/kernel/manager/themeManager.js +1 -3
- package/dist/kernel/types.cjs +0 -2
- package/dist/kernel/types.js +1 -3
- package/dist/library/index.cjs +0 -2
- package/dist/library/index.js +1 -4
- package/dist/library/locale/index.cjs +0 -2
- package/dist/library/locale/index.js +1 -12
- package/dist/library/locale/langs/en-us/index.cjs +0 -2
- package/dist/library/locale/langs/en-us/index.js +1 -24
- package/dist/library/locale/langs/zh-cn/index.cjs +0 -2
- package/dist/library/locale/langs/zh-cn/index.js +1 -24
- package/dist/library/locale/types.cjs +0 -2
- package/dist/library/locale/types.js +1 -3
- package/dist/library/storage/cache.cjs +0 -2
- package/dist/library/storage/cache.js +1 -237
- package/dist/library/storage/encryption.cjs +0 -2
- package/dist/library/storage/encryption.js +1 -141
- package/dist/library/storage/index.cjs +0 -2
- package/dist/library/storage/index.js +1 -106
- package/dist/state/StateManager.cjs +0 -2
- package/dist/state/StateManager.js +1 -160
- package/dist/state/adapters/AdapterFactory.cjs +0 -2
- package/dist/state/adapters/AdapterFactory.js +1 -85
- package/dist/state/adapters/DefaultAdapter.cjs +0 -2
- package/dist/state/adapters/DefaultAdapter.js +1 -71
- package/dist/state/adapters/ReduxAdapter.cjs +0 -2
- package/dist/state/adapters/ReduxAdapter.js +1 -439
- package/dist/state/adapters/ZustandAdapter.cjs +0 -2
- package/dist/state/adapters/ZustandAdapter.js +1 -70
- package/dist/state/adapters/index.cjs +0 -2
- package/dist/state/adapters/index.js +1 -9
- package/dist/state/adapters/types.cjs +0 -2
- package/dist/state/adapters/types.js +1 -5
- package/dist/state/core/DerivedStateInstance.cjs +0 -2
- package/dist/state/core/DerivedStateInstance.js +1 -173
- package/dist/state/core/StateInstance.cjs +0 -2
- package/dist/state/core/StateInstance.js +1 -168
- package/dist/state/core/StateRegistry.cjs +0 -2
- package/dist/state/core/StateRegistry.js +1 -106
- package/dist/state/core/StateScope.cjs +0 -2
- package/dist/state/core/StateScope.js +1 -133
- package/dist/state/core/index.cjs +0 -2
- package/dist/state/core/index.js +1 -8
- package/dist/state/index.cjs +0 -2
- package/dist/state/index.js +1 -12
- package/dist/state/types.cjs +0 -2
- package/dist/state/types.js +1 -13
- package/dist/state.umd.js +22 -1395
- package/dist/types.cjs +0 -2
- package/dist/types.js +1 -3
- package/dist/utils/analytics.cjs +0 -2
- package/dist/utils/analytics.js +1 -204
- package/dist/utils/configSecurity.cjs +0 -2
- package/dist/utils/configSecurity.js +3 -176
- package/dist/utils/csrf.cjs +0 -2
- package/dist/utils/csrf.js +1 -3
- package/dist/utils/errors/ErrorCodes.cjs +0 -2
- package/dist/utils/errors/ErrorCodes.js +1 -3
- package/dist/utils/errors.cjs +0 -2
- package/dist/utils/errors.js +1 -18
- package/dist/utils/index.cjs +0 -2
- package/dist/utils/index.js +1 -48
- package/dist/utils/logger.cjs +0 -2
- package/dist/utils/logger.js +1 -3
- package/dist/utils/logger.types.cjs +0 -2
- package/dist/utils/logger.types.js +1 -3
- package/dist/utils/monitoring.cjs +0 -2
- package/dist/utils/monitoring.js +1 -3
- package/dist/utils/performance.cjs +0 -2
- package/dist/utils/performance.js +1 -3
- package/dist/utils/resourceLoader.cjs +0 -2
- package/dist/utils/resourceLoader.js +1 -3
- package/dist/utils/runtimeSecurity.cjs +0 -2
- package/dist/utils/runtimeSecurity.js +1 -3
- package/dist/utils/security.cjs +0 -2
- package/dist/utils/security.js +1 -3
- package/dist/utils/traceId.cjs +0 -2
- package/dist/utils/traceId.js +1 -3
- package/dist/utils/validation.cjs +0 -2
- package/dist/utils/validation.js +1 -3
- package/package.json +3 -4
- package/dist/analytics/index.cjs.map +0 -1
- package/dist/analytics/index.js.map +0 -1
- package/dist/analytics.umd.js.map +0 -1
- package/dist/components/LocaleSwitch.cjs.map +0 -1
- package/dist/components/LocaleSwitch.js.map +0 -1
- package/dist/components/ThemeSwitch.cjs.map +0 -1
- package/dist/components/ThemeSwitch.js.map +0 -1
- package/dist/components/index.cjs.map +0 -1
- package/dist/components/index.js.map +0 -1
- package/dist/components/persistence.cjs.map +0 -1
- package/dist/components/persistence.js.map +0 -1
- package/dist/core/Test.cjs.map +0 -1
- package/dist/core/Test.js.map +0 -1
- package/dist/core/app/AppContext.cjs.map +0 -1
- package/dist/core/app/AppContext.js.map +0 -1
- package/dist/core/app/AppContext.types.cjs.map +0 -1
- package/dist/core/app/AppContext.types.js.map +0 -1
- package/dist/core/app/BasicLayout.cjs.map +0 -1
- package/dist/core/app/BasicLayout.js.map +0 -1
- package/dist/core/app/DefaultApp.cjs.map +0 -1
- package/dist/core/app/DefaultApp.js.map +0 -1
- package/dist/core/app/index.cjs.map +0 -1
- package/dist/core/app/index.js.map +0 -1
- package/dist/core/config/AppConfig.cjs.map +0 -1
- package/dist/core/config/AppConfig.js.map +0 -1
- package/dist/core/config/ConfigLoader.cjs.map +0 -1
- package/dist/core/config/ConfigLoader.js.map +0 -1
- package/dist/core/config/ConfigValidator.cjs.map +0 -1
- package/dist/core/config/ConfigValidator.js.map +0 -1
- package/dist/core/config/index.cjs.map +0 -1
- package/dist/core/config/index.js.map +0 -1
- package/dist/core/dev/DevTools.cjs.map +0 -1
- package/dist/core/dev/DevTools.js.map +0 -1
- package/dist/core/error/ErrorBoundary.cjs.map +0 -1
- package/dist/core/error/ErrorBoundary.js.map +0 -1
- package/dist/core/error/ErrorHandler.cjs.map +0 -1
- package/dist/core/error/ErrorHandler.js.map +0 -1
- package/dist/core/error/index.cjs.map +0 -1
- package/dist/core/error/index.js.map +0 -1
- package/dist/core/event/AppEventBus.cjs.map +0 -1
- package/dist/core/event/AppEventBus.js.map +0 -1
- package/dist/core/event/frameworkEvents.cjs.map +0 -1
- package/dist/core/event/frameworkEvents.js.map +0 -1
- package/dist/core/event/hooks.cjs.map +0 -1
- package/dist/core/event/hooks.js.map +0 -1
- package/dist/core/event/index.cjs.map +0 -1
- package/dist/core/event/index.js.map +0 -1
- package/dist/core/event/types.cjs.map +0 -1
- package/dist/core/event/types.js.map +0 -1
- package/dist/core/event/useEventBus.cjs.map +0 -1
- package/dist/core/event/useEventBus.js.map +0 -1
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.js.map +0 -1
- package/dist/core/initialization/InitializationErrorThrower.cjs.map +0 -1
- package/dist/core/initialization/InitializationErrorThrower.js.map +0 -1
- package/dist/core/initialization/index.cjs.map +0 -1
- package/dist/core/initialization/index.js.map +0 -1
- package/dist/core/initialization/initialization.cjs.map +0 -1
- package/dist/core/initialization/initialization.js.map +0 -1
- package/dist/core/initialization/initializationErrorState.cjs.map +0 -1
- package/dist/core/initialization/initializationErrorState.js.map +0 -1
- package/dist/core/kernel/defaultAdapters.cjs.map +0 -1
- package/dist/core/kernel/defaultAdapters.js.map +0 -1
- package/dist/core/kernel/errors.cjs.map +0 -1
- package/dist/core/kernel/errors.js.map +0 -1
- package/dist/core/kernel/index.cjs.map +0 -1
- package/dist/core/kernel/index.js.map +0 -1
- package/dist/core/kernel/startKernel.cjs.map +0 -1
- package/dist/core/kernel/startKernel.js.map +0 -1
- package/dist/core/kernel/types.cjs.map +0 -1
- package/dist/core/kernel/types.js.map +0 -1
- package/dist/core/middleware.cjs.map +0 -1
- package/dist/core/middleware.js.map +0 -1
- package/dist/core/plugin/PluginEventBus.cjs.map +0 -1
- package/dist/core/plugin/PluginEventBus.js.map +0 -1
- package/dist/core/plugin/PluginSandbox.cjs.map +0 -1
- package/dist/core/plugin/PluginSandbox.js.map +0 -1
- package/dist/core/plugin.cjs.map +0 -1
- package/dist/core/plugin.js.map +0 -1
- package/dist/core/router/RouterManager.cjs.map +0 -1
- package/dist/core/router/RouterManager.js.map +0 -1
- package/dist/core/router/adapter/AdapterManager.cjs.map +0 -1
- package/dist/core/router/adapter/AdapterManager.js.map +0 -1
- package/dist/core/router/adapter/index.cjs.map +0 -1
- package/dist/core/router/adapter/index.js.map +0 -1
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.cjs.map +0 -1
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.js.map +0 -1
- package/dist/core/router/adapter/react-router/index.cjs.map +0 -1
- package/dist/core/router/adapter/react-router/index.js.map +0 -1
- package/dist/core/router/adapter/types.cjs.map +0 -1
- package/dist/core/router/adapter/types.js.map +0 -1
- package/dist/core/router/dev/RouterDevTools.cjs.map +0 -1
- package/dist/core/router/dev/RouterDevTools.js.map +0 -1
- package/dist/core/router/dev/index.cjs.map +0 -1
- package/dist/core/router/dev/index.js.map +0 -1
- package/dist/core/router/dynamic/DynamicRouteManager.cjs.map +0 -1
- package/dist/core/router/dynamic/DynamicRouteManager.js.map +0 -1
- package/dist/core/router/dynamic/index.cjs.map +0 -1
- package/dist/core/router/dynamic/index.js.map +0 -1
- package/dist/core/router/errors/RouterError.cjs.map +0 -1
- package/dist/core/router/errors/RouterError.js.map +0 -1
- package/dist/core/router/errors/index.cjs.map +0 -1
- package/dist/core/router/errors/index.js.map +0 -1
- package/dist/core/router/index.cjs.map +0 -1
- package/dist/core/router/index.js.map +0 -1
- package/dist/core/router/lifecycle/RouterLifecycleManager.cjs.map +0 -1
- package/dist/core/router/lifecycle/RouterLifecycleManager.js.map +0 -1
- package/dist/core/router/lifecycle/index.cjs.map +0 -1
- package/dist/core/router/lifecycle/index.js.map +0 -1
- package/dist/core/router/middleware/RouterMiddlewareManager.cjs.map +0 -1
- package/dist/core/router/middleware/RouterMiddlewareManager.js.map +0 -1
- package/dist/core/router/middleware/auth.cjs.map +0 -1
- package/dist/core/router/middleware/auth.js.map +0 -1
- package/dist/core/router/middleware/index.cjs.map +0 -1
- package/dist/core/router/middleware/index.js.map +0 -1
- package/dist/core/router/middleware/types.cjs.map +0 -1
- package/dist/core/router/middleware/types.js.map +0 -1
- package/dist/core/router/monitoring/RouterMonitoring.cjs.map +0 -1
- package/dist/core/router/monitoring/RouterMonitoring.js.map +0 -1
- package/dist/core/router/monitoring/index.cjs.map +0 -1
- package/dist/core/router/monitoring/index.js.map +0 -1
- package/dist/core/router/navigation/RouterNavigation.cjs.map +0 -1
- package/dist/core/router/navigation/RouterNavigation.js.map +0 -1
- package/dist/core/router/navigation/index.cjs.map +0 -1
- package/dist/core/router/navigation/index.js.map +0 -1
- package/dist/core/router/performance/RouteCache.cjs.map +0 -1
- package/dist/core/router/performance/RouteCache.js.map +0 -1
- package/dist/core/router/performance/RoutePreloader.cjs.map +0 -1
- package/dist/core/router/performance/RoutePreloader.js.map +0 -1
- package/dist/core/router/performance/index.cjs.map +0 -1
- package/dist/core/router/performance/index.js.map +0 -1
- package/dist/core/router/plugin/RouterPluginManager.cjs.map +0 -1
- package/dist/core/router/plugin/RouterPluginManager.js.map +0 -1
- package/dist/core/router/plugin/index.cjs.map +0 -1
- package/dist/core/router/plugin/index.js.map +0 -1
- package/dist/core/router/plugin/types.cjs.map +0 -1
- package/dist/core/router/plugin/types.js.map +0 -1
- package/dist/core/router/types.cjs.map +0 -1
- package/dist/core/router/types.js.map +0 -1
- package/dist/core/router/utils/adapters/react-router/RouteErrorBoundary.cjs.map +0 -1
- package/dist/core/router/utils/adapters/react-router/RouteErrorBoundary.js.map +0 -1
- package/dist/core/router/utils/adapters/react-router/transform.cjs.map +0 -1
- package/dist/core/router/utils/adapters/react-router/transform.js.map +0 -1
- package/dist/core/router/utils/transform.cjs.map +0 -1
- package/dist/core/router/utils/transform.js.map +0 -1
- package/dist/core/router/validation/RouterConfigValidator.cjs.map +0 -1
- package/dist/core/router/validation/RouterConfigValidator.js.map +0 -1
- package/dist/core/router/validation/index.cjs.map +0 -1
- package/dist/core/router/validation/index.js.map +0 -1
- package/dist/core/router/validation/schema.cjs.map +0 -1
- package/dist/core/router/validation/schema.js.map +0 -1
- package/dist/core/router/version/RouteVersionManager.cjs.map +0 -1
- package/dist/core/router/version/RouteVersionManager.js.map +0 -1
- package/dist/core/router/version/index.cjs.map +0 -1
- package/dist/core/router/version/index.js.map +0 -1
- package/dist/core/splash/SplashScreen.cjs.map +0 -1
- package/dist/core/splash/SplashScreen.js.map +0 -1
- package/dist/core/splash/index.cjs.map +0 -1
- package/dist/core/splash/index.js.map +0 -1
- package/dist/core/splash/splashScreenUtils.cjs.map +0 -1
- package/dist/core/splash/splashScreenUtils.js.map +0 -1
- package/dist/core/startup/AppInstance.cjs.map +0 -1
- package/dist/core/startup/AppInstance.js.map +0 -1
- package/dist/core/startup/environment.cjs.map +0 -1
- package/dist/core/startup/environment.js.map +0 -1
- package/dist/core/startup/index.cjs.map +0 -1
- package/dist/core/startup/index.js.map +0 -1
- package/dist/core/startup/initializeServices.cjs.map +0 -1
- package/dist/core/startup/initializeServices.js.map +0 -1
- package/dist/core/startup/performanceTracker.cjs.map +0 -1
- package/dist/core/startup/performanceTracker.js.map +0 -1
- package/dist/core/startup/renderApp.cjs.map +0 -1
- package/dist/core/startup/renderApp.js.map +0 -1
- package/dist/core/startup/startApp.cjs.map +0 -1
- package/dist/core/startup/startApp.js.map +0 -1
- package/dist/core/types.cjs.map +0 -1
- package/dist/core/types.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.umd.cjs.map +0 -1
- package/dist/index.umd.js.map +0 -1
- package/dist/kernel/constants.cjs.map +0 -1
- package/dist/kernel/constants.js.map +0 -1
- package/dist/kernel/index.cjs.map +0 -1
- package/dist/kernel/index.js.map +0 -1
- package/dist/kernel/kernel.cjs.map +0 -1
- package/dist/kernel/kernel.js.map +0 -1
- package/dist/kernel/manager/cacheManager.cjs.map +0 -1
- package/dist/kernel/manager/cacheManager.js.map +0 -1
- package/dist/kernel/manager/i18n/I18nManager.cjs.map +0 -1
- package/dist/kernel/manager/i18n/I18nManager.js.map +0 -1
- package/dist/kernel/manager/i18n/i18n.persistence.cjs.map +0 -1
- package/dist/kernel/manager/i18n/i18n.persistence.js.map +0 -1
- package/dist/kernel/manager/i18n/i18n.schema.cjs.map +0 -1
- package/dist/kernel/manager/i18n/i18n.schema.js.map +0 -1
- package/dist/kernel/manager/i18n/index.cjs.map +0 -1
- package/dist/kernel/manager/i18n/index.js.map +0 -1
- package/dist/kernel/manager/i18nManager.cjs.map +0 -1
- package/dist/kernel/manager/i18nManager.js.map +0 -1
- package/dist/kernel/manager/index.cjs.map +0 -1
- package/dist/kernel/manager/index.js.map +0 -1
- package/dist/kernel/manager/logger/LoggerManager.cjs.map +0 -1
- package/dist/kernel/manager/logger/LoggerManager.js.map +0 -1
- package/dist/kernel/manager/logger/index.cjs.map +0 -1
- package/dist/kernel/manager/logger/index.js.map +0 -1
- package/dist/kernel/manager/logger/logger.persistence.cjs.map +0 -1
- package/dist/kernel/manager/logger/logger.persistence.js.map +0 -1
- package/dist/kernel/manager/logger/logger.schema.cjs.map +0 -1
- package/dist/kernel/manager/logger/logger.schema.js.map +0 -1
- package/dist/kernel/manager/loggerManager.cjs.map +0 -1
- package/dist/kernel/manager/loggerManager.js.map +0 -1
- package/dist/kernel/manager/persistence.cjs +0 -78
- package/dist/kernel/manager/persistence.cjs.map +0 -1
- package/dist/kernel/manager/persistence.d.ts +0 -3
- package/dist/kernel/manager/persistence.js +0 -60
- package/dist/kernel/manager/persistence.js.map +0 -1
- package/dist/kernel/manager/theme/ThemeManager.cjs.map +0 -1
- package/dist/kernel/manager/theme/ThemeManager.js.map +0 -1
- package/dist/kernel/manager/theme/index.cjs.map +0 -1
- package/dist/kernel/manager/theme/index.js.map +0 -1
- package/dist/kernel/manager/theme/theme.dom.cjs.map +0 -1
- package/dist/kernel/manager/theme/theme.dom.js.map +0 -1
- package/dist/kernel/manager/theme/theme.persistence.cjs.map +0 -1
- package/dist/kernel/manager/theme/theme.persistence.js.map +0 -1
- package/dist/kernel/manager/theme/theme.schema.cjs.map +0 -1
- package/dist/kernel/manager/theme/theme.schema.js.map +0 -1
- package/dist/kernel/manager/themeManager.cjs.map +0 -1
- package/dist/kernel/manager/themeManager.js.map +0 -1
- package/dist/kernel/types.cjs.map +0 -1
- package/dist/kernel/types.js.map +0 -1
- package/dist/library/index.cjs.map +0 -1
- package/dist/library/index.js.map +0 -1
- package/dist/library/locale/index.cjs.map +0 -1
- package/dist/library/locale/index.js.map +0 -1
- package/dist/library/locale/langs/en-us/index.cjs.map +0 -1
- package/dist/library/locale/langs/en-us/index.js.map +0 -1
- package/dist/library/locale/langs/zh-cn/index.cjs.map +0 -1
- package/dist/library/locale/langs/zh-cn/index.js.map +0 -1
- package/dist/library/locale/types.cjs.map +0 -1
- package/dist/library/locale/types.js.map +0 -1
- package/dist/library/storage/cache.cjs.map +0 -1
- package/dist/library/storage/cache.js.map +0 -1
- package/dist/library/storage/encryption.cjs.map +0 -1
- package/dist/library/storage/encryption.js.map +0 -1
- package/dist/library/storage/index.cjs.map +0 -1
- package/dist/library/storage/index.js.map +0 -1
- package/dist/request/adapter/RequestAdapter.d.ts +0 -85
- package/dist/request/adapter/RequestAdapter.js +0 -70
- package/dist/request/adapter/RequestAdapter.js.map +0 -1
- package/dist/request/adapter/axiosAdapter.d.ts +0 -10
- package/dist/request/adapter/axiosAdapter.js +0 -115
- package/dist/request/adapter/axiosAdapter.js.map +0 -1
- package/dist/request/adapter/fetchAdapter.d.ts +0 -10
- package/dist/request/adapter/fetchAdapter.js +0 -126
- package/dist/request/adapter/fetchAdapter.js.map +0 -1
- package/dist/request/adapter/index.d.ts +0 -9
- package/dist/request/adapter/index.js +0 -14
- package/dist/request/adapter/index.js.map +0 -1
- package/dist/request/adapter/kyAdapter.d.ts +0 -10
- package/dist/request/adapter/kyAdapter.js +0 -142
- package/dist/request/adapter/kyAdapter.js.map +0 -1
- package/dist/request/adapter/undiciAdapter.d.ts +0 -10
- package/dist/request/adapter/undiciAdapter.js +0 -164
- package/dist/request/adapter/undiciAdapter.js.map +0 -1
- package/dist/request/adapter.d.ts +0 -1
- package/dist/request/core/RequestClient.d.ts +0 -134
- package/dist/request/core/RequestClient.js +0 -509
- package/dist/request/core/RequestClient.js.map +0 -1
- package/dist/request/core/index.d.ts +0 -5
- package/dist/request/core/index.js +0 -5
- package/dist/request/core/index.js.map +0 -1
- package/dist/request/core.d.ts +0 -1
- package/dist/request/index.d.ts +0 -1
- package/dist/request/index.js +0 -50
- package/dist/request/index.js.map +0 -1
- package/dist/request/plugin/RequestPlugin.d.ts +0 -170
- package/dist/request/plugin/RequestPlugin.js +0 -203
- package/dist/request/plugin/RequestPlugin.js.map +0 -1
- package/dist/request/plugin/cache.d.ts +0 -33
- package/dist/request/plugin/cache.js +0 -264
- package/dist/request/plugin/cache.js.map +0 -1
- package/dist/request/plugin/csrfPlugin.d.ts +0 -21
- package/dist/request/plugin/csrfPlugin.js +0 -44
- package/dist/request/plugin/csrfPlugin.js.map +0 -1
- package/dist/request/plugin/index.d.ts +0 -11
- package/dist/request/plugin/index.js +0 -12
- package/dist/request/plugin/index.js.map +0 -1
- package/dist/request/plugin/monitoring.d.ts +0 -112
- package/dist/request/plugin/monitoring.js +0 -205
- package/dist/request/plugin/monitoring.js.map +0 -1
- package/dist/request/plugin/queue.d.ts +0 -91
- package/dist/request/plugin/queue.js +0 -156
- package/dist/request/plugin/queue.js.map +0 -1
- package/dist/request/plugin/retry.d.ts +0 -34
- package/dist/request/plugin/retry.js +0 -93
- package/dist/request/plugin/retry.js.map +0 -1
- package/dist/request/plugin/validation.d.ts +0 -26
- package/dist/request/plugin/validation.js +0 -116
- package/dist/request/plugin/validation.js.map +0 -1
- package/dist/request/plugin.d.ts +0 -1
- package/dist/request/runtime/RequestContext.d.ts +0 -50
- package/dist/request/runtime/RequestContext.js +0 -86
- package/dist/request/runtime/RequestContext.js.map +0 -1
- package/dist/request/runtime/index.d.ts +0 -4
- package/dist/request/runtime/index.js +0 -5
- package/dist/request/runtime/index.js.map +0 -1
- package/dist/request/runtime.d.ts +0 -1
- package/dist/request/types.d.ts +0 -1
- package/dist/request/types.js +0 -97
- package/dist/request/types.js.map +0 -1
- package/dist/request/utils/RequestQueueManager.d.ts +0 -74
- package/dist/request/utils/RequestQueueManager.js +0 -160
- package/dist/request/utils/RequestQueueManager.js.map +0 -1
- package/dist/request/utils/dependencyCheck.d.ts +0 -63
- package/dist/request/utils/dependencyCheck.js +0 -192
- package/dist/request/utils/dependencyCheck.js.map +0 -1
- package/dist/request/utils/index.d.ts +0 -5
- package/dist/request/utils/index.js +0 -6
- package/dist/request/utils/index.js.map +0 -1
- package/dist/request/utils.d.ts +0 -1
- package/dist/state/StateManager.cjs.map +0 -1
- package/dist/state/StateManager.js.map +0 -1
- package/dist/state/adapters/AdapterFactory.cjs.map +0 -1
- package/dist/state/adapters/AdapterFactory.js.map +0 -1
- package/dist/state/adapters/DefaultAdapter.cjs.map +0 -1
- package/dist/state/adapters/DefaultAdapter.js.map +0 -1
- package/dist/state/adapters/ReduxAdapter.cjs.map +0 -1
- package/dist/state/adapters/ReduxAdapter.js.map +0 -1
- package/dist/state/adapters/ZustandAdapter.cjs.map +0 -1
- package/dist/state/adapters/ZustandAdapter.js.map +0 -1
- package/dist/state/adapters/index.cjs.map +0 -1
- package/dist/state/adapters/index.js.map +0 -1
- package/dist/state/adapters/types.cjs.map +0 -1
- package/dist/state/adapters/types.js.map +0 -1
- package/dist/state/core/DerivedStateInstance.cjs.map +0 -1
- package/dist/state/core/DerivedStateInstance.js.map +0 -1
- package/dist/state/core/StateInstance.cjs.map +0 -1
- package/dist/state/core/StateInstance.js.map +0 -1
- package/dist/state/core/StateRegistry.cjs.map +0 -1
- package/dist/state/core/StateRegistry.js.map +0 -1
- package/dist/state/core/StateScope.cjs.map +0 -1
- package/dist/state/core/StateScope.js.map +0 -1
- package/dist/state/core/index.cjs.map +0 -1
- package/dist/state/core/index.js.map +0 -1
- package/dist/state/index.cjs.map +0 -1
- package/dist/state/index.js.map +0 -1
- package/dist/state/types.cjs.map +0 -1
- package/dist/state/types.js.map +0 -1
- package/dist/state.umd.js.map +0 -1
- package/dist/types.cjs.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils/analytics.cjs.map +0 -1
- package/dist/utils/analytics.js.map +0 -1
- package/dist/utils/configSecurity.cjs.map +0 -1
- package/dist/utils/configSecurity.js.map +0 -1
- package/dist/utils/csrf.cjs.map +0 -1
- package/dist/utils/csrf.js.map +0 -1
- package/dist/utils/errors/ErrorCodes.cjs.map +0 -1
- package/dist/utils/errors/ErrorCodes.js.map +0 -1
- package/dist/utils/errors.cjs.map +0 -1
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/index.cjs.map +0 -1
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/logger.cjs.map +0 -1
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/logger.types.cjs.map +0 -1
- package/dist/utils/logger.types.js.map +0 -1
- package/dist/utils/monitoring.cjs.map +0 -1
- package/dist/utils/monitoring.js.map +0 -1
- package/dist/utils/performance.cjs.map +0 -1
- package/dist/utils/performance.js.map +0 -1
- package/dist/utils/resourceLoader.cjs.map +0 -1
- package/dist/utils/resourceLoader.js.map +0 -1
- package/dist/utils/runtimeSecurity.cjs.map +0 -1
- package/dist/utils/runtimeSecurity.js.map +0 -1
- package/dist/utils/security.cjs.map +0 -1
- package/dist/utils/security.js.map +0 -1
- package/dist/utils/traceId.cjs.map +0 -1
- package/dist/utils/traceId.js.map +0 -1
- package/dist/utils/validation.cjs.map +0 -1
- package/dist/utils/validation.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/monitoring/RouterMonitoring.ts"],"sourcesContent":["/**\n * 路由监控服务\n * 提供路由访问统计、性能监控、错误监控等功能\n */\n\nimport { getMonitoring } from '@vlian/monitoring';\nimport { logger } from '@vlian/logger';\nimport type { RouteLocation } from '../types';\nimport type { RouterError } from '../errors';\n\n/**\n * 路由访问记录\n */\ninterface RouteAccessRecord {\n /**\n * 路由路径\n */\n path: string;\n\n /**\n * 路由名称\n */\n name?: string;\n\n /**\n * 访问时间\n */\n timestamp: number;\n\n /**\n * 访问持续时间(毫秒)\n */\n duration?: number;\n\n /**\n * 来源路由\n */\n from?: string;\n\n /**\n * 是否成功\n */\n success: boolean;\n\n /**\n * 错误信息(如果有)\n */\n error?: string;\n}\n\n/**\n * 路由性能指标\n */\ninterface RoutePerformanceMetrics {\n /**\n * 路由匹配时间(毫秒)\n */\n matchTime?: number;\n\n /**\n * 组件加载时间(毫秒)\n */\n loadTime?: number;\n\n /**\n * 路由渲染时间(毫秒)\n */\n renderTime?: number;\n\n /**\n * 总时间(毫秒)\n */\n totalTime?: number;\n}\n\n/**\n * 路由监控配置\n */\nexport interface RouterMonitoringConfig {\n /**\n * 是否启用路由监控\n * @default true\n */\n enabled?: boolean;\n\n /**\n * 是否记录路由访问\n * @default true\n */\n trackAccess?: boolean;\n\n /**\n * 是否记录性能指标\n * @default true\n */\n trackPerformance?: boolean;\n\n /**\n * 是否记录错误\n * @default true\n */\n trackErrors?: boolean;\n\n /**\n * 最大记录数量\n * @default 1000\n */\n maxRecords?: number;\n\n /**\n * 采样率 (0-1)\n * @default 1.0\n */\n sampleRate?: number;\n}\n\n/**\n * 路由监控服务\n */\nexport class RouterMonitoring {\n private accessRecords: RouteAccessRecord[] = [];\n private performanceMetrics: Map<string, RoutePerformanceMetrics[]> = new Map();\n private config: Required<RouterMonitoringConfig>;\n private monitoringService = getMonitoring();\n private currentRouteStartTime: number = 0;\n private currentRoute?: RouteLocation;\n\n constructor(config: RouterMonitoringConfig = {}) {\n this.config = {\n enabled: config.enabled ?? true,\n trackAccess: config.trackAccess ?? true,\n trackPerformance: config.trackPerformance ?? true,\n trackErrors: config.trackErrors ?? true,\n maxRecords: config.maxRecords ?? 1000,\n sampleRate: config.sampleRate ?? 1.0,\n };\n }\n\n /**\n * 记录路由访问\n */\n trackRouteAccess(\n to: RouteLocation,\n from?: RouteLocation,\n success: boolean = true,\n error?: Error\n ): void {\n if (!this.config.enabled || !this.config.trackAccess) {\n return;\n }\n\n // 采样检查\n if (Math.random() > this.config.sampleRate) {\n return;\n }\n\n const record: RouteAccessRecord = {\n path: to.path,\n name: to.meta?.name as string | undefined,\n timestamp: Date.now(),\n from: from?.path,\n success,\n error: error?.message,\n };\n\n // 如果有当前路由,计算持续时间\n if (this.currentRoute && this.currentRouteStartTime > 0) {\n record.duration = Date.now() - this.currentRouteStartTime;\n }\n\n this.accessRecords.push(record);\n\n // 限制记录数量\n if (this.accessRecords.length > this.config.maxRecords) {\n this.accessRecords.shift();\n }\n\n // 上报到监控服务\n this.monitoringService.trackEvent('route_access', {\n path: to.path,\n name: to.meta?.name,\n success,\n error: error?.message,\n });\n\n // 更新当前路由\n this.currentRoute = to;\n this.currentRouteStartTime = Date.now();\n\n logger.debug('路由访问已记录', record);\n }\n\n /**\n * 记录路由性能指标\n */\n trackRoutePerformance(\n routeName: string,\n metrics: RoutePerformanceMetrics\n ): void {\n if (!this.config.enabled || !this.config.trackPerformance) {\n return;\n }\n\n // 采样检查\n if (Math.random() > this.config.sampleRate) {\n return;\n }\n\n const routeMetrics = this.performanceMetrics.get(routeName) || [];\n routeMetrics.push(metrics);\n\n // 限制记录数量\n if (routeMetrics.length > 100) {\n routeMetrics.shift();\n }\n\n this.performanceMetrics.set(routeName, routeMetrics);\n\n // 上报到监控服务\n this.monitoringService.reportPerformance({\n [`route_${routeName}_match`]: metrics.matchTime || 0,\n [`route_${routeName}_load`]: metrics.loadTime || 0,\n [`route_${routeName}_render`]: metrics.renderTime || 0,\n [`route_${routeName}_total`]: metrics.totalTime || 0,\n });\n\n logger.debug(`路由性能指标已记录: ${routeName}`, metrics);\n }\n\n /**\n * 记录路由错误\n */\n trackRouteError(error: RouterError | Error, context?: Record<string, unknown>): void {\n if (!this.config.enabled || !this.config.trackErrors) {\n return;\n }\n\n // 采样检查\n if (Math.random() > this.config.sampleRate) {\n return;\n }\n\n // 上报到监控服务\n this.monitoringService.captureError(error, {\n type: 'router',\n ...context,\n });\n\n logger.error('路由错误已记录', error, context);\n }\n\n /**\n * 获取路由访问统计\n */\n getAccessStats(): {\n total: number;\n success: number;\n failed: number;\n byPath: Record<string, number>;\n byName: Record<string, number>;\n averageDuration: number;\n } {\n const stats = {\n total: this.accessRecords.length,\n success: 0,\n failed: 0,\n byPath: {} as Record<string, number>,\n byName: {} as Record<string, number>,\n averageDuration: 0,\n };\n\n let totalDuration = 0;\n let durationCount = 0;\n\n for (const record of this.accessRecords) {\n if (record.success) {\n stats.success++;\n } else {\n stats.failed++;\n }\n\n stats.byPath[record.path] = (stats.byPath[record.path] || 0) + 1;\n\n if (record.name) {\n stats.byName[record.name] = (stats.byName[record.name] || 0) + 1;\n }\n\n if (record.duration) {\n totalDuration += record.duration;\n durationCount++;\n }\n }\n\n stats.averageDuration = durationCount > 0 ? totalDuration / durationCount : 0;\n\n return stats;\n }\n\n /**\n * 获取路由性能统计\n */\n getPerformanceStats(): Record<\n string,\n {\n count: number;\n averageMatchTime: number;\n averageLoadTime: number;\n averageRenderTime: number;\n averageTotalTime: number;\n }\n > {\n const stats: Record<\n string,\n {\n count: number;\n averageMatchTime: number;\n averageLoadTime: number;\n averageRenderTime: number;\n averageTotalTime: number;\n }\n > = {};\n\n for (const [routeName, metrics] of this.performanceMetrics.entries()) {\n let totalMatchTime = 0;\n let totalLoadTime = 0;\n let totalRenderTime = 0;\n let totalTotalTime = 0;\n let count = 0;\n\n for (const metric of metrics) {\n if (metric.matchTime) {\n totalMatchTime += metric.matchTime;\n }\n if (metric.loadTime) {\n totalLoadTime += metric.loadTime;\n }\n if (metric.renderTime) {\n totalRenderTime += metric.renderTime;\n }\n if (metric.totalTime) {\n totalTotalTime += metric.totalTime;\n }\n count++;\n }\n\n stats[routeName] = {\n count,\n averageMatchTime: count > 0 ? totalMatchTime / count : 0,\n averageLoadTime: count > 0 ? totalLoadTime / count : 0,\n averageRenderTime: count > 0 ? totalRenderTime / count : 0,\n averageTotalTime: count > 0 ? totalTotalTime / count : 0,\n };\n }\n\n return stats;\n }\n\n /**\n * 清空所有记录\n */\n clear(): void {\n this.accessRecords = [];\n this.performanceMetrics.clear();\n logger.debug('路由监控记录已清空');\n }\n\n /**\n * 获取监控报告\n */\n getReport() {\n return {\n access: this.getAccessStats(),\n performance: this.getPerformanceStats(),\n timestamp: Date.now(),\n };\n }\n}\n\n/**\n * 获取路由监控服务单例\n */\nlet routerMonitoringInstance: RouterMonitoring | null = null;\n\nexport function getRouterMonitoring(\n config?: RouterMonitoringConfig\n): RouterMonitoring {\n if (!routerMonitoringInstance) {\n routerMonitoringInstance = new RouterMonitoring(config);\n }\n return routerMonitoringInstance;\n}\n"],"names":["getMonitoring","logger","RouterMonitoring","trackRouteAccess","to","from","success","error","config","enabled","trackAccess","Math","random","sampleRate","record","path","name","meta","timestamp","Date","now","message","currentRoute","currentRouteStartTime","duration","accessRecords","push","length","maxRecords","shift","monitoringService","trackEvent","debug","trackRoutePerformance","routeName","metrics","trackPerformance","routeMetrics","performanceMetrics","get","set","reportPerformance","matchTime","loadTime","renderTime","totalTime","trackRouteError","context","trackErrors","captureError","type","getAccessStats","stats","total","failed","byPath","byName","averageDuration","totalDuration","durationCount","getPerformanceStats","entries","totalMatchTime","totalLoadTime","totalRenderTime","totalTotalTime","count","metric","averageMatchTime","averageLoadTime","averageRenderTime","averageTotalTime","clear","getReport","access","performance","Map","routerMonitoringInstance","getRouterMonitoring"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/monitoring/index.ts"],"sourcesContent":["/**\n * 路由监控模块入口\n */\n\nexport * from './RouterMonitoring';\n"],"names":[],"mappings":"AAAA;;CAEC;;;;qBAEa"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/monitoring/index.ts"],"sourcesContent":["/**\n * 路由监控模块入口\n */\n\nexport * from './RouterMonitoring';\n"],"names":[],"mappings":"AAAA;;CAEC,GAED,cAAc,qBAAqB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/navigation/RouterNavigation.ts"],"sourcesContent":["/**\n * 路由导航 API\n * 提供框架级别的路由导航能力,封装 react-router-dom 的导航功能\n */\n\nimport { logger } from '@vlian/logger';\nimport type { RouteLocation, NavigateOptions } from '../types';\nimport { getRouterLifecycleManager } from '../lifecycle';\nimport { getRouterMiddlewareManager } from '../middleware';\nimport type { RouterMiddlewareContext } from '../middleware/types';\n\n/**\n * 路由导航器\n */\nexport class RouterNavigation {\n private static readonly MAX_REDIRECTS = 10;\n\n private static buildTargetPath(\n to: string,\n query?: Record<string, unknown>\n ): string {\n const base =\n typeof window !== 'undefined' && window.location?.origin\n ? window.location.origin\n : 'http://localhost';\n\n const url = new URL(to, base);\n\n if (query && Object.keys(query).length > 0) {\n const params = new URLSearchParams(url.search);\n Object.entries(query).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n params.delete(key);\n return;\n }\n params.set(key, String(value));\n });\n url.search = params.toString();\n }\n\n return `${url.pathname}${url.search}${url.hash}`;\n }\n\n private static async navigateInternal(\n to: string,\n options: NavigateOptions | undefined,\n depth: number,\n visited: Set<string>\n ): Promise<void> {\n const startTime = performance.now();\n\n if (depth > this.MAX_REDIRECTS) {\n throw new Error(`路由重定向次数超过上限(${this.MAX_REDIRECTS}),可能存在循环重定向`);\n }\n\n const targetPath = this.buildTargetPath(to, options?.query);\n if (visited.has(targetPath)) {\n throw new Error(`检测到循环重定向: ${targetPath}`);\n }\n visited.add(targetPath);\n\n const routerManager = await import('../RouterManager').then((m) => m.getRouterManager());\n const router = routerManager.getRouter();\n\n if (!router) {\n throw new Error('路由未初始化,无法导航');\n }\n\n // 获取当前路由信息\n const currentLocation = this.getCurrentRoute();\n\n // 构建目标路由位置\n const targetLocation: RouteLocation = {\n path: targetPath,\n query: options?.query,\n };\n\n // 执行生命周期钩子\n const lifecycleManager = getRouterLifecycleManager();\n const beforeEachResult = await lifecycleManager.beforeEach(\n targetLocation,\n currentLocation\n );\n\n let finalPath = targetPath;\n\n // 如果 beforeEach 返回 false,阻止导航\n if (beforeEachResult === false) {\n logger.debug('路由导航被阻止: beforeEach 返回 false');\n return;\n }\n\n // 如果 beforeEach 返回字符串,重定向到该路径\n if (typeof beforeEachResult === 'string') {\n logger.debug(`路由导航重定向: ${beforeEachResult}`);\n finalPath = this.buildTargetPath(beforeEachResult);\n }\n\n // 执行中间件\n const middlewareManager = getRouterMiddlewareManager();\n const middlewareContext: RouterMiddlewareContext = {\n to: {\n ...targetLocation,\n path: finalPath,\n },\n from: currentLocation,\n options,\n };\n\n const middlewareResult = await middlewareManager.execute(middlewareContext);\n\n // 如果中间件阻止导航\n if (!middlewareResult.allow) {\n if (middlewareResult.redirect) {\n logger.debug(`路由导航被中间件重定向: ${middlewareResult.redirect}`);\n return this.navigateInternal(\n middlewareResult.redirect,\n { ...options, query: undefined },\n depth + 1,\n visited\n );\n }\n logger.debug(`路由导航被中间件阻止: ${middlewareResult.reason || '未知原因'}`);\n return;\n }\n\n // 执行导航\n try {\n if (options?.replace) {\n router.navigate(finalPath, { replace: true, state: options.state });\n } else {\n router.navigate(finalPath, { state: options?.state });\n }\n\n // 执行 afterEach 钩子\n await lifecycleManager.afterEach(\n {\n ...targetLocation,\n path: finalPath,\n },\n currentLocation\n );\n\n const duration = performance.now() - startTime;\n routerManager.getMonitoring().trackRoutePerformance(finalPath, {\n totalTime: duration,\n });\n } catch (error) {\n logger.error('路由导航失败', error);\n throw error;\n }\n }\n\n /**\n * 导航到指定路径\n * \n * @param to - 目标路径或路由名称\n * @param options - 导航选项\n */\n static async navigate(\n to: string,\n options?: NavigateOptions\n ): Promise<void> {\n return this.navigateInternal(to, options, 0, new Set());\n }\n\n /**\n * 获取当前路由信息\n * \n * @returns 当前路由位置信息\n */\n static getCurrentRoute(): RouteLocation {\n if (typeof window === 'undefined') {\n return {\n path: '/',\n query: {},\n };\n }\n\n // 从 window.location 获取当前路由信息\n const pathname = window.location.pathname;\n const search = window.location.search;\n const hash = window.location.hash;\n\n // 解析查询参数\n const query: Record<string, unknown> = {};\n if (search) {\n const params = new URLSearchParams(search);\n params.forEach((value, key) => {\n query[key] = value;\n });\n }\n\n return {\n path: pathname + hash,\n query,\n };\n }\n\n /**\n * 返回上一页\n * \n * @param fallback - 如果没有历史记录,跳转到该路径\n */\n static async goBack(fallback?: string): Promise<void> {\n if (window.history.length > 1) {\n window.history.back();\n } else if (fallback) {\n await this.navigate(fallback);\n } else {\n logger.warn('没有历史记录,无法返回');\n }\n }\n\n /**\n * 前进到下一页\n */\n static goForward(): void {\n window.history.forward();\n }\n\n /**\n * 替换当前路由\n * \n * @param to - 目标路径\n * @param options - 导航选项\n */\n static async replace(\n to: string,\n options?: Omit<NavigateOptions, 'replace'>\n ): Promise<void> {\n return this.navigate(to, { ...options, replace: true });\n }\n}\n"],"names":["RouterNavigation","buildTargetPath","to","query","base","window","location","origin","url","URL","Object","keys","length","params","URLSearchParams","search","entries","forEach","key","value","undefined","delete","set","String","toString","pathname","hash","navigateInternal","options","depth","visited","startTime","performance","now","MAX_REDIRECTS","Error","targetPath","has","add","routerManager","then","m","getRouterManager","router","getRouter","currentLocation","getCurrentRoute","targetLocation","path","lifecycleManager","getRouterLifecycleManager","beforeEachResult","beforeEach","finalPath","logger","debug","middlewareManager","getRouterMiddlewareManager","middlewareContext","from","middlewareResult","execute","allow","redirect","reason","replace","navigate","state","afterEach","duration","getMonitoring","trackRoutePerformance","totalTime","error","Set","goBack","fallback","history","back","warn","goForward","forward"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/navigation/RouterNavigation.ts"],"sourcesContent":["/**\n * 路由导航 API\n * 提供框架级别的路由导航能力,封装 react-router-dom 的导航功能\n */\n\nimport { logger } from '@vlian/logger';\nimport type { RouteLocation, NavigateOptions } from '../types';\nimport { getRouterLifecycleManager } from '../lifecycle';\nimport { getRouterMiddlewareManager } from '../middleware';\nimport type { RouterMiddlewareContext } from '../middleware/types';\n\n/**\n * 路由导航器\n */\nexport class RouterNavigation {\n private static readonly MAX_REDIRECTS = 10;\n\n private static buildTargetPath(\n to: string,\n query?: Record<string, unknown>\n ): string {\n const base =\n typeof window !== 'undefined' && window.location?.origin\n ? window.location.origin\n : 'http://localhost';\n\n const url = new URL(to, base);\n\n if (query && Object.keys(query).length > 0) {\n const params = new URLSearchParams(url.search);\n Object.entries(query).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n params.delete(key);\n return;\n }\n params.set(key, String(value));\n });\n url.search = params.toString();\n }\n\n return `${url.pathname}${url.search}${url.hash}`;\n }\n\n private static async navigateInternal(\n to: string,\n options: NavigateOptions | undefined,\n depth: number,\n visited: Set<string>\n ): Promise<void> {\n const startTime = performance.now();\n\n if (depth > this.MAX_REDIRECTS) {\n throw new Error(`路由重定向次数超过上限(${this.MAX_REDIRECTS}),可能存在循环重定向`);\n }\n\n const targetPath = this.buildTargetPath(to, options?.query);\n if (visited.has(targetPath)) {\n throw new Error(`检测到循环重定向: ${targetPath}`);\n }\n visited.add(targetPath);\n\n const routerManager = await import('../RouterManager').then((m) => m.getRouterManager());\n const router = routerManager.getRouter();\n\n if (!router) {\n throw new Error('路由未初始化,无法导航');\n }\n\n // 获取当前路由信息\n const currentLocation = this.getCurrentRoute();\n\n // 构建目标路由位置\n const targetLocation: RouteLocation = {\n path: targetPath,\n query: options?.query,\n };\n\n // 执行生命周期钩子\n const lifecycleManager = getRouterLifecycleManager();\n const beforeEachResult = await lifecycleManager.beforeEach(\n targetLocation,\n currentLocation\n );\n\n let finalPath = targetPath;\n\n // 如果 beforeEach 返回 false,阻止导航\n if (beforeEachResult === false) {\n logger.debug('路由导航被阻止: beforeEach 返回 false');\n return;\n }\n\n // 如果 beforeEach 返回字符串,重定向到该路径\n if (typeof beforeEachResult === 'string') {\n logger.debug(`路由导航重定向: ${beforeEachResult}`);\n finalPath = this.buildTargetPath(beforeEachResult);\n }\n\n // 执行中间件\n const middlewareManager = getRouterMiddlewareManager();\n const middlewareContext: RouterMiddlewareContext = {\n to: {\n ...targetLocation,\n path: finalPath,\n },\n from: currentLocation,\n options,\n };\n\n const middlewareResult = await middlewareManager.execute(middlewareContext);\n\n // 如果中间件阻止导航\n if (!middlewareResult.allow) {\n if (middlewareResult.redirect) {\n logger.debug(`路由导航被中间件重定向: ${middlewareResult.redirect}`);\n return this.navigateInternal(\n middlewareResult.redirect,\n { ...options, query: undefined },\n depth + 1,\n visited\n );\n }\n logger.debug(`路由导航被中间件阻止: ${middlewareResult.reason || '未知原因'}`);\n return;\n }\n\n // 执行导航\n try {\n if (options?.replace) {\n router.navigate(finalPath, { replace: true, state: options.state });\n } else {\n router.navigate(finalPath, { state: options?.state });\n }\n\n // 执行 afterEach 钩子\n await lifecycleManager.afterEach(\n {\n ...targetLocation,\n path: finalPath,\n },\n currentLocation\n );\n\n const duration = performance.now() - startTime;\n routerManager.getMonitoring().trackRoutePerformance(finalPath, {\n totalTime: duration,\n });\n } catch (error) {\n logger.error('路由导航失败', error);\n throw error;\n }\n }\n\n /**\n * 导航到指定路径\n * \n * @param to - 目标路径或路由名称\n * @param options - 导航选项\n */\n static async navigate(\n to: string,\n options?: NavigateOptions\n ): Promise<void> {\n return this.navigateInternal(to, options, 0, new Set());\n }\n\n /**\n * 获取当前路由信息\n * \n * @returns 当前路由位置信息\n */\n static getCurrentRoute(): RouteLocation {\n if (typeof window === 'undefined') {\n return {\n path: '/',\n query: {},\n };\n }\n\n // 从 window.location 获取当前路由信息\n const pathname = window.location.pathname;\n const search = window.location.search;\n const hash = window.location.hash;\n\n // 解析查询参数\n const query: Record<string, unknown> = {};\n if (search) {\n const params = new URLSearchParams(search);\n params.forEach((value, key) => {\n query[key] = value;\n });\n }\n\n return {\n path: pathname + hash,\n query,\n };\n }\n\n /**\n * 返回上一页\n * \n * @param fallback - 如果没有历史记录,跳转到该路径\n */\n static async goBack(fallback?: string): Promise<void> {\n if (window.history.length > 1) {\n window.history.back();\n } else if (fallback) {\n await this.navigate(fallback);\n } else {\n logger.warn('没有历史记录,无法返回');\n }\n }\n\n /**\n * 前进到下一页\n */\n static goForward(): void {\n window.history.forward();\n }\n\n /**\n * 替换当前路由\n * \n * @param to - 目标路径\n * @param options - 导航选项\n */\n static async replace(\n to: string,\n options?: Omit<NavigateOptions, 'replace'>\n ): Promise<void> {\n return this.navigate(to, { ...options, replace: true });\n }\n}\n"],"names":["logger","getRouterLifecycleManager","getRouterMiddlewareManager","RouterNavigation","buildTargetPath","to","query","base","window","location","origin","url","URL","Object","keys","length","params","URLSearchParams","search","entries","forEach","key","value","undefined","delete","set","String","toString","pathname","hash","navigateInternal","options","depth","visited","startTime","performance","now","MAX_REDIRECTS","Error","targetPath","has","add","routerManager","then","m","getRouterManager","router","getRouter","currentLocation","getCurrentRoute","targetLocation","path","lifecycleManager","beforeEachResult","beforeEach","finalPath","debug","middlewareManager","middlewareContext","from","middlewareResult","execute","allow","redirect","reason","replace","navigate","state","afterEach","duration","getMonitoring","trackRoutePerformance","totalTime","error","Set","goBack","fallback","history","back","warn","goForward","forward"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/navigation/index.ts"],"sourcesContent":["/**\n * 路由导航模块入口\n */\n\nexport * from './RouterNavigation';\n"],"names":[],"mappings":"AAAA;;CAEC;;;;qBAEa"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/navigation/index.ts"],"sourcesContent":["/**\n * 路由导航模块入口\n */\n\nexport * from './RouterNavigation';\n"],"names":[],"mappings":"AAAA;;CAEC,GAED,cAAc,qBAAqB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/performance/RouteCache.ts"],"sourcesContent":["/**\n * 路由缓存管理器\n * 提供路由转换结果、匹配结果的缓存功能\n */\n\nimport { logger } from '@vlian/logger';\nimport type { RouteConfig } from '../types';\nimport type { TransformRoutesResult } from '../utils/transform';\n\n/**\n * 缓存项接口\n */\ninterface CacheItem<T> {\n /**\n * 缓存值\n */\n value: T;\n /**\n * 过期时间戳\n */\n expiresAt: number;\n /**\n * 创建时间戳\n */\n createdAt: number;\n /**\n * 访问次数\n */\n accessCount: number;\n /**\n * 最后访问时间\n */\n lastAccessedAt: number;\n}\n\n/**\n * LRU 缓存配置\n */\nexport interface RouteCacheConfig {\n /**\n * 最大缓存数量\n * @default 50\n */\n maxSize?: number;\n\n /**\n * 缓存过期时间(毫秒)\n * @default 5 * 60 * 1000 (5分钟)\n */\n ttl?: number;\n\n /**\n * 是否启用持久化缓存(使用 IndexedDB)\n * @default false\n */\n enablePersistence?: boolean;\n\n /**\n * 持久化缓存键前缀\n * @default 'router_cache_'\n */\n persistenceKeyPrefix?: string;\n}\n\n/**\n * 路由缓存管理器\n */\nexport class RouteCache {\n private cache: Map<string, CacheItem<TransformRoutesResult>> = new Map();\n private matchCache: Map<string, CacheItem<RouteConfig | null>> = new Map();\n private config: Required<RouteCacheConfig>;\n private persistenceEnabled: boolean = false;\n private cleanupTimer: ReturnType<typeof setInterval> | null = null;\n private stats = {\n transformHits: 0,\n transformMisses: 0,\n matchHits: 0,\n matchMisses: 0,\n };\n\n constructor(config: RouteCacheConfig = {}) {\n this.config = {\n maxSize: config.maxSize ?? 50,\n ttl: config.ttl ?? 5 * 60 * 1000,\n enablePersistence: config.enablePersistence ?? false,\n persistenceKeyPrefix: config.persistenceKeyPrefix ?? 'router_cache_',\n };\n\n // 初始化持久化缓存\n if (this.config.enablePersistence && typeof window !== 'undefined' && 'indexedDB' in window) {\n this.initPersistence();\n }\n\n // 定期清理过期缓存\n this.startCleanupInterval();\n }\n\n /**\n * 初始化持久化缓存\n */\n private async initPersistence(): Promise<void> {\n try {\n // 检查 IndexedDB 是否可用\n if (typeof window !== 'undefined' && 'indexedDB' in window) {\n this.persistenceEnabled = true;\n await this.loadFromPersistence();\n logger.debug('路由缓存持久化已启用');\n }\n } catch (error) {\n logger.warn('路由缓存持久化初始化失败', error);\n this.persistenceEnabled = false;\n }\n }\n\n /**\n * 从持久化存储加载缓存\n */\n private async loadFromPersistence(): Promise<void> {\n try {\n // 这里可以实现从 IndexedDB 加载缓存的逻辑\n // 由于 IndexedDB 操作较复杂,这里先留空\n // 实际实现可以使用 idb 库或原生 IndexedDB API\n } catch (error) {\n logger.warn('从持久化存储加载缓存失败', error);\n }\n }\n\n /**\n * 保存到持久化存储\n */\n private async saveToPersistence(_key: string, _value: TransformRoutesResult): Promise<void> {\n if (!this.persistenceEnabled) {\n return;\n }\n\n try {\n // 这里可以实现保存到 IndexedDB 的逻辑\n // 实际实现可以使用 idb 库或原生 IndexedDB API\n } catch (error) {\n logger.warn('保存到持久化存储失败', error);\n }\n }\n\n /**\n * 生成缓存键\n */\n private generateKey(routes: RouteConfig[] | (() => RouteConfig[] | Promise<RouteConfig[]>)): string {\n if (typeof routes === 'function') {\n // 对于函数,使用函数名或随机 ID\n return `fn_${routes.name || Math.random().toString(36).substring(7)}`;\n }\n\n // 对于数组,使用 JSON.stringify 生成键(注意:这可能会很慢)\n // 实际使用中可以考虑使用路由配置的哈希值\n try {\n const routesStr = JSON.stringify(routes, (_key, value) => {\n // 过滤掉函数,避免序列化问题\n if (typeof value === 'function') {\n return '[Function]';\n }\n return value;\n });\n return `routes_${this.hashString(routesStr)}`;\n } catch (error) {\n // 如果序列化失败,使用随机键\n return `routes_${Math.random().toString(36).substring(7)}`;\n }\n }\n\n /**\n * 字符串哈希函数(简单实现)\n */\n private hashString(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // 转换为 32 位整数\n }\n return Math.abs(hash).toString(36);\n }\n\n /**\n * 检查缓存项是否过期\n */\n private isExpired(item: CacheItem<unknown>): boolean {\n return Date.now() > item.expiresAt;\n }\n\n /**\n * 清理过期缓存\n */\n private cleanup(): void {\n\n // 清理转换结果缓存\n for (const [key, item] of this.cache.entries()) {\n if (this.isExpired(item)) {\n this.cache.delete(key);\n }\n }\n\n // 清理匹配结果缓存\n for (const [key, item] of this.matchCache.entries()) {\n if (this.isExpired(item)) {\n this.matchCache.delete(key);\n }\n }\n\n // 如果缓存超过最大大小,删除最久未访问的项(LRU)\n this.evictLRU();\n }\n\n /**\n * LRU 淘汰策略\n */\n private evictLRU(): void {\n // 清理转换结果缓存\n if (this.cache.size > this.config.maxSize) {\n const sorted = Array.from(this.cache.entries()).sort(\n (a, b) => a[1].lastAccessedAt - b[1].lastAccessedAt\n );\n const toDelete = sorted.slice(0, this.cache.size - this.config.maxSize);\n toDelete.forEach(([key]) => this.cache.delete(key));\n }\n\n // 清理匹配结果缓存\n if (this.matchCache.size > this.config.maxSize) {\n const sorted = Array.from(this.matchCache.entries()).sort(\n (a, b) => a[1].lastAccessedAt - b[1].lastAccessedAt\n );\n const toDelete = sorted.slice(0, this.matchCache.size - this.config.maxSize);\n toDelete.forEach(([key]) => this.matchCache.delete(key));\n }\n }\n\n /**\n * 启动定期清理\n */\n private startCleanupInterval(): void {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n }\n\n // 每 1 分钟清理一次过期缓存\n this.cleanupTimer = setInterval(() => {\n this.cleanup();\n }, 60 * 1000);\n }\n\n /**\n * 获取转换结果缓存\n */\n get(routes: RouteConfig[] | (() => RouteConfig[] | Promise<RouteConfig[]>)): TransformRoutesResult | null {\n const key = this.generateKey(routes);\n const item = this.cache.get(key);\n\n if (!item) {\n this.stats.transformMisses++;\n return null;\n }\n\n if (this.isExpired(item)) {\n this.cache.delete(key);\n this.stats.transformMisses++;\n return null;\n }\n\n // 更新访问信息\n item.lastAccessedAt = Date.now();\n item.accessCount++;\n this.stats.transformHits++;\n\n return item.value;\n }\n\n /**\n * 设置转换结果缓存\n */\n set(\n routes: RouteConfig[] | (() => RouteConfig[] | Promise<RouteConfig[]>),\n value: TransformRoutesResult\n ): void {\n const key = this.generateKey(routes);\n const now = Date.now();\n\n const item: CacheItem<TransformRoutesResult> = {\n value,\n expiresAt: now + this.config.ttl,\n createdAt: now,\n accessCount: 0,\n lastAccessedAt: now,\n };\n\n this.cache.set(key, item);\n\n // 保存到持久化存储\n if (this.persistenceEnabled) {\n this.saveToPersistence(key, value).catch((error) => {\n logger.warn('保存缓存到持久化存储失败', error);\n });\n }\n\n // 检查是否需要淘汰\n this.evictLRU();\n }\n\n /**\n * 获取路由匹配缓存\n */\n getMatch(path: string): RouteConfig | null | undefined {\n const item = this.matchCache.get(path);\n\n if (!item) {\n this.stats.matchMisses++;\n return undefined;\n }\n\n if (this.isExpired(item)) {\n this.matchCache.delete(path);\n this.stats.matchMisses++;\n return undefined;\n }\n\n // 更新访问信息\n item.lastAccessedAt = Date.now();\n item.accessCount++;\n this.stats.matchHits++;\n\n return item.value;\n }\n\n /**\n * 设置路由匹配缓存\n */\n setMatch(path: string, route: RouteConfig | null): void {\n const now = Date.now();\n\n const item: CacheItem<RouteConfig | null> = {\n value: route,\n expiresAt: now + this.config.ttl,\n createdAt: now,\n accessCount: 0,\n lastAccessedAt: now,\n };\n\n this.matchCache.set(path, item);\n\n // 检查是否需要淘汰\n this.evictLRU();\n }\n\n /**\n * 清空所有缓存\n */\n clear(): void {\n this.cache.clear();\n this.matchCache.clear();\n this.stats = {\n transformHits: 0,\n transformMisses: 0,\n matchHits: 0,\n matchMisses: 0,\n };\n logger.debug('路由缓存已清空');\n }\n\n /**\n * 销毁缓存实例并释放资源\n */\n destroy(): void {\n this.clear();\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = null;\n }\n }\n\n /**\n * 获取缓存统计信息\n */\n getStats(): {\n transformCacheSize: number;\n matchCacheSize: number;\n totalSize: number;\n hitRate: number;\n } {\n const totalHits = this.stats.transformHits + this.stats.matchHits;\n const totalAccess =\n totalHits +\n this.stats.transformMisses +\n this.stats.matchMisses;\n\n const hitRate = totalAccess > 0 ? totalHits / totalAccess : 0;\n\n return {\n transformCacheSize: this.cache.size,\n matchCacheSize: this.matchCache.size,\n totalSize: this.cache.size + this.matchCache.size,\n hitRate,\n };\n }\n}\n\n/**\n * 获取路由缓存管理器单例\n */\nlet routeCacheInstance: RouteCache | null = null;\n\nexport function getRouteCache(config?: RouteCacheConfig): RouteCache {\n if (!routeCacheInstance) {\n routeCacheInstance = new RouteCache(config);\n }\n return routeCacheInstance;\n}\n"],"names":["RouteCache","getRouteCache","initPersistence","window","persistenceEnabled","loadFromPersistence","logger","debug","error","warn","saveToPersistence","_key","_value","generateKey","routes","name","Math","random","toString","substring","routesStr","JSON","stringify","value","hashString","str","hash","i","length","char","charCodeAt","abs","isExpired","item","Date","now","expiresAt","cleanup","key","cache","entries","delete","matchCache","evictLRU","size","config","maxSize","sorted","Array","from","sort","a","b","lastAccessedAt","toDelete","slice","forEach","startCleanupInterval","cleanupTimer","clearInterval","setInterval","get","stats","transformMisses","accessCount","transformHits","set","ttl","createdAt","catch","getMatch","path","matchMisses","undefined","matchHits","setMatch","route","clear","destroy","getStats","totalHits","totalAccess","hitRate","transformCacheSize","matchCacheSize","totalSize","Map","enablePersistence","persistenceKeyPrefix","routeCacheInstance"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/performance/RouteCache.ts"],"sourcesContent":["/**\n * 路由缓存管理器\n * 提供路由转换结果、匹配结果的缓存功能\n */\n\nimport { logger } from '@vlian/logger';\nimport type { RouteConfig } from '../types';\nimport type { TransformRoutesResult } from '../utils/transform';\n\n/**\n * 缓存项接口\n */\ninterface CacheItem<T> {\n /**\n * 缓存值\n */\n value: T;\n /**\n * 过期时间戳\n */\n expiresAt: number;\n /**\n * 创建时间戳\n */\n createdAt: number;\n /**\n * 访问次数\n */\n accessCount: number;\n /**\n * 最后访问时间\n */\n lastAccessedAt: number;\n}\n\n/**\n * LRU 缓存配置\n */\nexport interface RouteCacheConfig {\n /**\n * 最大缓存数量\n * @default 50\n */\n maxSize?: number;\n\n /**\n * 缓存过期时间(毫秒)\n * @default 5 * 60 * 1000 (5分钟)\n */\n ttl?: number;\n\n /**\n * 是否启用持久化缓存(使用 IndexedDB)\n * @default false\n */\n enablePersistence?: boolean;\n\n /**\n * 持久化缓存键前缀\n * @default 'router_cache_'\n */\n persistenceKeyPrefix?: string;\n}\n\n/**\n * 路由缓存管理器\n */\nexport class RouteCache {\n private cache: Map<string, CacheItem<TransformRoutesResult>> = new Map();\n private matchCache: Map<string, CacheItem<RouteConfig | null>> = new Map();\n private config: Required<RouteCacheConfig>;\n private persistenceEnabled: boolean = false;\n private cleanupTimer: ReturnType<typeof setInterval> | null = null;\n private stats = {\n transformHits: 0,\n transformMisses: 0,\n matchHits: 0,\n matchMisses: 0,\n };\n\n constructor(config: RouteCacheConfig = {}) {\n this.config = {\n maxSize: config.maxSize ?? 50,\n ttl: config.ttl ?? 5 * 60 * 1000,\n enablePersistence: config.enablePersistence ?? false,\n persistenceKeyPrefix: config.persistenceKeyPrefix ?? 'router_cache_',\n };\n\n // 初始化持久化缓存\n if (this.config.enablePersistence && typeof window !== 'undefined' && 'indexedDB' in window) {\n this.initPersistence();\n }\n\n // 定期清理过期缓存\n this.startCleanupInterval();\n }\n\n /**\n * 初始化持久化缓存\n */\n private async initPersistence(): Promise<void> {\n try {\n // 检查 IndexedDB 是否可用\n if (typeof window !== 'undefined' && 'indexedDB' in window) {\n this.persistenceEnabled = true;\n await this.loadFromPersistence();\n logger.debug('路由缓存持久化已启用');\n }\n } catch (error) {\n logger.warn('路由缓存持久化初始化失败', error);\n this.persistenceEnabled = false;\n }\n }\n\n /**\n * 从持久化存储加载缓存\n */\n private async loadFromPersistence(): Promise<void> {\n try {\n // 这里可以实现从 IndexedDB 加载缓存的逻辑\n // 由于 IndexedDB 操作较复杂,这里先留空\n // 实际实现可以使用 idb 库或原生 IndexedDB API\n } catch (error) {\n logger.warn('从持久化存储加载缓存失败', error);\n }\n }\n\n /**\n * 保存到持久化存储\n */\n private async saveToPersistence(_key: string, _value: TransformRoutesResult): Promise<void> {\n if (!this.persistenceEnabled) {\n return;\n }\n\n try {\n // 这里可以实现保存到 IndexedDB 的逻辑\n // 实际实现可以使用 idb 库或原生 IndexedDB API\n } catch (error) {\n logger.warn('保存到持久化存储失败', error);\n }\n }\n\n /**\n * 生成缓存键\n */\n private generateKey(routes: RouteConfig[] | (() => RouteConfig[] | Promise<RouteConfig[]>)): string {\n if (typeof routes === 'function') {\n // 对于函数,使用函数名或随机 ID\n return `fn_${routes.name || Math.random().toString(36).substring(7)}`;\n }\n\n // 对于数组,使用 JSON.stringify 生成键(注意:这可能会很慢)\n // 实际使用中可以考虑使用路由配置的哈希值\n try {\n const routesStr = JSON.stringify(routes, (_key, value) => {\n // 过滤掉函数,避免序列化问题\n if (typeof value === 'function') {\n return '[Function]';\n }\n return value;\n });\n return `routes_${this.hashString(routesStr)}`;\n } catch (error) {\n // 如果序列化失败,使用随机键\n return `routes_${Math.random().toString(36).substring(7)}`;\n }\n }\n\n /**\n * 字符串哈希函数(简单实现)\n */\n private hashString(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // 转换为 32 位整数\n }\n return Math.abs(hash).toString(36);\n }\n\n /**\n * 检查缓存项是否过期\n */\n private isExpired(item: CacheItem<unknown>): boolean {\n return Date.now() > item.expiresAt;\n }\n\n /**\n * 清理过期缓存\n */\n private cleanup(): void {\n\n // 清理转换结果缓存\n for (const [key, item] of this.cache.entries()) {\n if (this.isExpired(item)) {\n this.cache.delete(key);\n }\n }\n\n // 清理匹配结果缓存\n for (const [key, item] of this.matchCache.entries()) {\n if (this.isExpired(item)) {\n this.matchCache.delete(key);\n }\n }\n\n // 如果缓存超过最大大小,删除最久未访问的项(LRU)\n this.evictLRU();\n }\n\n /**\n * LRU 淘汰策略\n */\n private evictLRU(): void {\n // 清理转换结果缓存\n if (this.cache.size > this.config.maxSize) {\n const sorted = Array.from(this.cache.entries()).sort(\n (a, b) => a[1].lastAccessedAt - b[1].lastAccessedAt\n );\n const toDelete = sorted.slice(0, this.cache.size - this.config.maxSize);\n toDelete.forEach(([key]) => this.cache.delete(key));\n }\n\n // 清理匹配结果缓存\n if (this.matchCache.size > this.config.maxSize) {\n const sorted = Array.from(this.matchCache.entries()).sort(\n (a, b) => a[1].lastAccessedAt - b[1].lastAccessedAt\n );\n const toDelete = sorted.slice(0, this.matchCache.size - this.config.maxSize);\n toDelete.forEach(([key]) => this.matchCache.delete(key));\n }\n }\n\n /**\n * 启动定期清理\n */\n private startCleanupInterval(): void {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n }\n\n // 每 1 分钟清理一次过期缓存\n this.cleanupTimer = setInterval(() => {\n this.cleanup();\n }, 60 * 1000);\n }\n\n /**\n * 获取转换结果缓存\n */\n get(routes: RouteConfig[] | (() => RouteConfig[] | Promise<RouteConfig[]>)): TransformRoutesResult | null {\n const key = this.generateKey(routes);\n const item = this.cache.get(key);\n\n if (!item) {\n this.stats.transformMisses++;\n return null;\n }\n\n if (this.isExpired(item)) {\n this.cache.delete(key);\n this.stats.transformMisses++;\n return null;\n }\n\n // 更新访问信息\n item.lastAccessedAt = Date.now();\n item.accessCount++;\n this.stats.transformHits++;\n\n return item.value;\n }\n\n /**\n * 设置转换结果缓存\n */\n set(\n routes: RouteConfig[] | (() => RouteConfig[] | Promise<RouteConfig[]>),\n value: TransformRoutesResult\n ): void {\n const key = this.generateKey(routes);\n const now = Date.now();\n\n const item: CacheItem<TransformRoutesResult> = {\n value,\n expiresAt: now + this.config.ttl,\n createdAt: now,\n accessCount: 0,\n lastAccessedAt: now,\n };\n\n this.cache.set(key, item);\n\n // 保存到持久化存储\n if (this.persistenceEnabled) {\n this.saveToPersistence(key, value).catch((error) => {\n logger.warn('保存缓存到持久化存储失败', error);\n });\n }\n\n // 检查是否需要淘汰\n this.evictLRU();\n }\n\n /**\n * 获取路由匹配缓存\n */\n getMatch(path: string): RouteConfig | null | undefined {\n const item = this.matchCache.get(path);\n\n if (!item) {\n this.stats.matchMisses++;\n return undefined;\n }\n\n if (this.isExpired(item)) {\n this.matchCache.delete(path);\n this.stats.matchMisses++;\n return undefined;\n }\n\n // 更新访问信息\n item.lastAccessedAt = Date.now();\n item.accessCount++;\n this.stats.matchHits++;\n\n return item.value;\n }\n\n /**\n * 设置路由匹配缓存\n */\n setMatch(path: string, route: RouteConfig | null): void {\n const now = Date.now();\n\n const item: CacheItem<RouteConfig | null> = {\n value: route,\n expiresAt: now + this.config.ttl,\n createdAt: now,\n accessCount: 0,\n lastAccessedAt: now,\n };\n\n this.matchCache.set(path, item);\n\n // 检查是否需要淘汰\n this.evictLRU();\n }\n\n /**\n * 清空所有缓存\n */\n clear(): void {\n this.cache.clear();\n this.matchCache.clear();\n this.stats = {\n transformHits: 0,\n transformMisses: 0,\n matchHits: 0,\n matchMisses: 0,\n };\n logger.debug('路由缓存已清空');\n }\n\n /**\n * 销毁缓存实例并释放资源\n */\n destroy(): void {\n this.clear();\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = null;\n }\n }\n\n /**\n * 获取缓存统计信息\n */\n getStats(): {\n transformCacheSize: number;\n matchCacheSize: number;\n totalSize: number;\n hitRate: number;\n } {\n const totalHits = this.stats.transformHits + this.stats.matchHits;\n const totalAccess =\n totalHits +\n this.stats.transformMisses +\n this.stats.matchMisses;\n\n const hitRate = totalAccess > 0 ? totalHits / totalAccess : 0;\n\n return {\n transformCacheSize: this.cache.size,\n matchCacheSize: this.matchCache.size,\n totalSize: this.cache.size + this.matchCache.size,\n hitRate,\n };\n }\n}\n\n/**\n * 获取路由缓存管理器单例\n */\nlet routeCacheInstance: RouteCache | null = null;\n\nexport function getRouteCache(config?: RouteCacheConfig): RouteCache {\n if (!routeCacheInstance) {\n routeCacheInstance = new RouteCache(config);\n }\n return routeCacheInstance;\n}\n"],"names":["logger","RouteCache","initPersistence","window","persistenceEnabled","loadFromPersistence","debug","error","warn","saveToPersistence","_key","_value","generateKey","routes","name","Math","random","toString","substring","routesStr","JSON","stringify","value","hashString","str","hash","i","length","char","charCodeAt","abs","isExpired","item","Date","now","expiresAt","cleanup","key","cache","entries","delete","matchCache","evictLRU","size","config","maxSize","sorted","Array","from","sort","a","b","lastAccessedAt","toDelete","slice","forEach","startCleanupInterval","cleanupTimer","clearInterval","setInterval","get","stats","transformMisses","accessCount","transformHits","set","ttl","createdAt","catch","getMatch","path","matchMisses","undefined","matchHits","setMatch","route","clear","destroy","getStats","totalHits","totalAccess","hitRate","transformCacheSize","matchCacheSize","totalSize","Map","enablePersistence","persistenceKeyPrefix","routeCacheInstance","getRouteCache"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/performance/RoutePreloader.ts"],"sourcesContent":["/**\n * 路由预加载管理器\n * 提供路由组件的预加载功能\n */\n\nimport { logger } from '@vlian/logger';\nimport type { RouteConfig } from '../types';\nimport type { ComponentImport } from '../types';\nimport type { TransformRoutesResult } from '../utils/transform';\n\n/**\n * 预加载策略\n */\nexport enum PreloadStrategy {\n /**\n * 不预加载\n */\n NONE = 'none',\n\n /**\n * 预加载当前路由的下一级路由\n */\n NEXT_LEVEL = 'next-level',\n\n /**\n * 预加载所有路由\n */\n ALL = 'all',\n\n /**\n * 预加载可见路由(根据路由配置的优先级)\n */\n VISIBLE = 'visible',\n}\n\n/**\n * 预加载配置\n */\nexport interface PreloadConfig {\n /**\n * 预加载策略\n * @default PreloadStrategy.NEXT_LEVEL\n */\n strategy?: PreloadStrategy;\n\n /**\n * 预加载延迟(毫秒)\n * @default 1000\n */\n delay?: number;\n\n /**\n * 预加载优先级阈值(只预加载优先级小于等于此值的路由)\n * @default 10\n */\n priorityThreshold?: number;\n\n /**\n * 预加载超时时间(毫秒)\n * @default 5000\n */\n timeout?: number;\n}\n\n/**\n * 预加载任务\n */\ninterface PreloadTask {\n /**\n * 组件导入函数\n */\n importFn: ComponentImport;\n /**\n * 路由名称\n */\n routeName: string;\n /**\n * 优先级\n */\n priority: number;\n /**\n * 状态\n */\n status: 'pending' | 'loading' | 'loaded' | 'failed';\n /**\n * 开始时间\n */\n startTime?: number;\n}\n\n/**\n * 路由预加载管理器\n */\nexport class RoutePreloader {\n private tasks: Map<string, PreloadTask> = new Map();\n private config: Required<PreloadConfig>;\n private preloadTimer: ReturnType<typeof setTimeout> | null = null;\n private idleHandle: number | null = null;\n\n constructor(config: PreloadConfig = {}) {\n this.config = {\n strategy: config.strategy ?? PreloadStrategy.NONE,\n delay: config.delay ?? 1000,\n priorityThreshold: config.priorityThreshold ?? 10,\n timeout: config.timeout ?? 5000,\n };\n }\n\n /**\n * 更新预加载配置\n */\n updateConfig(config: PreloadConfig = {}): void {\n this.config = {\n strategy: config.strategy ?? PreloadStrategy.NONE,\n delay: config.delay ?? 1000,\n priorityThreshold: config.priorityThreshold ?? 10,\n timeout: config.timeout ?? 5000,\n };\n }\n\n private shouldRegister(priority: number): boolean {\n if (this.config.strategy === PreloadStrategy.NONE) {\n return false;\n }\n\n if (\n this.config.strategy === PreloadStrategy.VISIBLE &&\n priority > this.config.priorityThreshold\n ) {\n return false;\n }\n\n return true;\n }\n\n private registerTask(\n key: string,\n importFn: ComponentImport,\n routeName: string,\n priority: number\n ): void {\n if (!this.shouldRegister(priority)) {\n return;\n }\n\n this.tasks.set(key, {\n importFn,\n routeName,\n priority,\n status: 'pending',\n });\n }\n\n /**\n * 注册路由用于预加载\n */\n registerRoute(route: RouteConfig): void {\n if (!route.page && !route.layout) {\n return;\n }\n\n const priority = route.handle?.order ?? 999;\n\n // 注册页面组件\n if (route.page && typeof route.page === 'function') {\n this.registerTask(`${route.name}_page`, route.page, route.name, priority);\n }\n\n // 注册布局组件\n if (route.layout && typeof route.layout === 'function') {\n this.registerTask(`${route.name}_layout`, route.layout, route.name, priority);\n }\n\n // 递归注册子路由\n if (route.children) {\n route.children.forEach((child) => this.registerRoute(child));\n }\n }\n\n /**\n * 注册多个路由\n */\n registerRoutes(\n routes: RouteConfig[],\n resolvers?: Pick<TransformRoutesResult, 'pages' | 'layouts' | 'errors' | 'loadings'>\n ): void {\n const priorityByPath = new Map<string, number>();\n const nameByPath = new Map<string, string>();\n\n const collectPriority = (route: RouteConfig): void => {\n const priority = route.handle?.order ?? 999;\n const routeName = route.name;\n\n const record = (value: unknown) => {\n if (typeof value !== 'string') {\n return;\n }\n if (!priorityByPath.has(value) || (priorityByPath.get(value) ?? 999) > priority) {\n priorityByPath.set(value, priority);\n nameByPath.set(value, routeName);\n }\n };\n\n record(route.page);\n record(route.layout);\n record(route.error ?? route.errors);\n record(route.loading);\n\n route.children?.forEach(collectPriority);\n };\n\n routes.forEach(collectPriority);\n routes.forEach((route) => this.registerRoute(route));\n\n if (!resolvers) {\n return;\n }\n\n const registerResolverMap = (\n map: Map<string, ComponentImport>,\n type: 'page' | 'layout' | 'error' | 'loading'\n ) => {\n for (const [path, importFn] of map.entries()) {\n const routeName = nameByPath.get(path) ?? path;\n const priority = priorityByPath.get(path) ?? 999;\n this.registerTask(`${routeName}_${type}_${path}`, importFn, routeName, priority);\n }\n };\n\n registerResolverMap(resolvers.pages, 'page');\n registerResolverMap(resolvers.layouts, 'layout');\n registerResolverMap(resolvers.errors, 'error');\n registerResolverMap(resolvers.loadings, 'loading');\n }\n\n /**\n * 预加载指定路由\n */\n async preloadRoute(routeName: string): Promise<void> {\n const tasks = Array.from(this.tasks.values()).filter(\n (task) => task.routeName === routeName && task.status === 'pending'\n );\n\n if (tasks.length === 0) {\n return;\n }\n\n await Promise.all(tasks.map((task) => this.preloadTask(task)));\n }\n\n /**\n * 预加载任务\n */\n private async preloadTask(task: PreloadTask): Promise<void> {\n if (task.status !== 'pending') {\n return;\n }\n\n task.status = 'loading';\n task.startTime = Date.now();\n\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n try {\n // 设置超时\n const timeoutPromise = new Promise((_, reject) => {\n timeoutId = setTimeout(() => reject(new Error('预加载超时')), this.config.timeout);\n });\n\n // 执行预加载\n await Promise.race([task.importFn(), timeoutPromise]);\n\n task.status = 'loaded';\n const duration = Date.now() - (task.startTime || 0);\n logger.debug(`路由组件预加载成功: ${task.routeName} (${duration}ms)`);\n } catch (error) {\n task.status = 'failed';\n logger.warn(`路由组件预加载失败: ${task.routeName}`, error);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n /**\n * 开始预加载(根据策略)\n */\n startPreload(): void {\n if (this.config.strategy === PreloadStrategy.NONE) {\n return;\n }\n\n this.stopPreload();\n\n // 延迟预加载,避免影响初始渲染\n this.preloadTimer = setTimeout(() => {\n const browserWindow = typeof window !== 'undefined' ? (window as Window & {\n requestIdleCallback?: (callback: () => void) => number;\n cancelIdleCallback?: (id: number) => void;\n }) : undefined;\n\n if (browserWindow?.requestIdleCallback) {\n this.idleHandle = browserWindow.requestIdleCallback(() => {\n this.executePreload();\n });\n return;\n }\n\n this.executePreload();\n }, this.config.delay);\n }\n\n /**\n * 执行预加载\n */\n private async executePreload(): Promise<void> {\n const tasks = Array.from(this.tasks.values())\n .filter((task) => task.status === 'pending')\n .sort((a, b) => a.priority - b.priority);\n\n if (tasks.length === 0) {\n return;\n }\n\n logger.debug(`开始预加载 ${tasks.length} 个路由组件`);\n\n // 根据策略决定预加载哪些任务\n let tasksToPreload: PreloadTask[] = [];\n\n switch (this.config.strategy) {\n case PreloadStrategy.ALL:\n tasksToPreload = tasks;\n break;\n case PreloadStrategy.NEXT_LEVEL:\n // 只预加载优先级最低的(最可能访问的)\n tasksToPreload = tasks.slice(0, Math.min(5, tasks.length));\n break;\n case PreloadStrategy.VISIBLE:\n tasksToPreload = tasks.filter(\n (task) => task.priority <= this.config.priorityThreshold\n );\n break;\n default:\n return;\n }\n\n // 并行预加载(限制并发数)\n const concurrency = 3;\n for (let i = 0; i < tasksToPreload.length; i += concurrency) {\n const batch = tasksToPreload.slice(i, i + concurrency);\n await Promise.all(batch.map((task) => this.preloadTask(task)));\n }\n\n logger.debug('路由组件预加载完成');\n }\n\n /**\n * 停止预加载\n */\n stopPreload(): void {\n const browserWindow = typeof window !== 'undefined' ? (window as Window & {\n cancelIdleCallback?: (id: number) => void;\n }) : undefined;\n\n if (this.preloadTimer) {\n clearTimeout(this.preloadTimer);\n this.preloadTimer = null;\n }\n if (this.idleHandle !== null && browserWindow?.cancelIdleCallback) {\n browserWindow.cancelIdleCallback(this.idleHandle);\n this.idleHandle = null;\n }\n }\n\n /**\n * 清空所有任务\n */\n clear(): void {\n this.tasks.clear();\n this.stopPreload();\n logger.debug('路由预加载任务已清空');\n }\n\n /**\n * 获取预加载统计信息\n */\n getStats(): {\n total: number;\n pending: number;\n loading: number;\n loaded: number;\n failed: number;\n } {\n const stats = {\n total: this.tasks.size,\n pending: 0,\n loading: 0,\n loaded: 0,\n failed: 0,\n };\n\n for (const task of this.tasks.values()) {\n stats[task.status]++;\n }\n\n return stats;\n }\n}\n\n/**\n * 获取路由预加载管理器单例\n */\nlet routePreloaderInstance: RoutePreloader | null = null;\n\nexport function getRoutePreloader(config?: PreloadConfig): RoutePreloader {\n if (!routePreloaderInstance) {\n routePreloaderInstance = new RoutePreloader(config);\n }\n return routePreloaderInstance;\n}\n"],"names":["PreloadStrategy","RoutePreloader","getRoutePreloader","updateConfig","config","strategy","delay","priorityThreshold","timeout","shouldRegister","priority","registerTask","key","importFn","routeName","tasks","set","status","registerRoute","route","page","layout","handle","order","name","children","forEach","child","registerRoutes","routes","resolvers","priorityByPath","Map","nameByPath","collectPriority","record","value","has","get","error","errors","loading","registerResolverMap","map","type","path","entries","pages","layouts","loadings","preloadRoute","Array","from","values","filter","task","length","Promise","all","preloadTask","startTime","Date","now","timeoutId","timeoutPromise","_","reject","setTimeout","Error","race","duration","logger","debug","warn","clearTimeout","startPreload","stopPreload","preloadTimer","browserWindow","window","undefined","requestIdleCallback","idleHandle","executePreload","sort","a","b","tasksToPreload","slice","Math","min","concurrency","i","batch","cancelIdleCallback","clear","getStats","stats","total","size","pending","loaded","failed","routePreloaderInstance"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/performance/RoutePreloader.ts"],"sourcesContent":["/**\n * 路由预加载管理器\n * 提供路由组件的预加载功能\n */\n\nimport { logger } from '@vlian/logger';\nimport type { RouteConfig } from '../types';\nimport type { ComponentImport } from '../types';\nimport type { TransformRoutesResult } from '../utils/transform';\n\n/**\n * 预加载策略\n */\nexport enum PreloadStrategy {\n /**\n * 不预加载\n */\n NONE = 'none',\n\n /**\n * 预加载当前路由的下一级路由\n */\n NEXT_LEVEL = 'next-level',\n\n /**\n * 预加载所有路由\n */\n ALL = 'all',\n\n /**\n * 预加载可见路由(根据路由配置的优先级)\n */\n VISIBLE = 'visible',\n}\n\n/**\n * 预加载配置\n */\nexport interface PreloadConfig {\n /**\n * 预加载策略\n * @default PreloadStrategy.NEXT_LEVEL\n */\n strategy?: PreloadStrategy;\n\n /**\n * 预加载延迟(毫秒)\n * @default 1000\n */\n delay?: number;\n\n /**\n * 预加载优先级阈值(只预加载优先级小于等于此值的路由)\n * @default 10\n */\n priorityThreshold?: number;\n\n /**\n * 预加载超时时间(毫秒)\n * @default 5000\n */\n timeout?: number;\n}\n\n/**\n * 预加载任务\n */\ninterface PreloadTask {\n /**\n * 组件导入函数\n */\n importFn: ComponentImport;\n /**\n * 路由名称\n */\n routeName: string;\n /**\n * 优先级\n */\n priority: number;\n /**\n * 状态\n */\n status: 'pending' | 'loading' | 'loaded' | 'failed';\n /**\n * 开始时间\n */\n startTime?: number;\n}\n\n/**\n * 路由预加载管理器\n */\nexport class RoutePreloader {\n private tasks: Map<string, PreloadTask> = new Map();\n private config: Required<PreloadConfig>;\n private preloadTimer: ReturnType<typeof setTimeout> | null = null;\n private idleHandle: number | null = null;\n\n constructor(config: PreloadConfig = {}) {\n this.config = {\n strategy: config.strategy ?? PreloadStrategy.NONE,\n delay: config.delay ?? 1000,\n priorityThreshold: config.priorityThreshold ?? 10,\n timeout: config.timeout ?? 5000,\n };\n }\n\n /**\n * 更新预加载配置\n */\n updateConfig(config: PreloadConfig = {}): void {\n this.config = {\n strategy: config.strategy ?? PreloadStrategy.NONE,\n delay: config.delay ?? 1000,\n priorityThreshold: config.priorityThreshold ?? 10,\n timeout: config.timeout ?? 5000,\n };\n }\n\n private shouldRegister(priority: number): boolean {\n if (this.config.strategy === PreloadStrategy.NONE) {\n return false;\n }\n\n if (\n this.config.strategy === PreloadStrategy.VISIBLE &&\n priority > this.config.priorityThreshold\n ) {\n return false;\n }\n\n return true;\n }\n\n private registerTask(\n key: string,\n importFn: ComponentImport,\n routeName: string,\n priority: number\n ): void {\n if (!this.shouldRegister(priority)) {\n return;\n }\n\n this.tasks.set(key, {\n importFn,\n routeName,\n priority,\n status: 'pending',\n });\n }\n\n /**\n * 注册路由用于预加载\n */\n registerRoute(route: RouteConfig): void {\n if (!route.page && !route.layout) {\n return;\n }\n\n const priority = route.handle?.order ?? 999;\n\n // 注册页面组件\n if (route.page && typeof route.page === 'function') {\n this.registerTask(`${route.name}_page`, route.page, route.name, priority);\n }\n\n // 注册布局组件\n if (route.layout && typeof route.layout === 'function') {\n this.registerTask(`${route.name}_layout`, route.layout, route.name, priority);\n }\n\n // 递归注册子路由\n if (route.children) {\n route.children.forEach((child) => this.registerRoute(child));\n }\n }\n\n /**\n * 注册多个路由\n */\n registerRoutes(\n routes: RouteConfig[],\n resolvers?: Pick<TransformRoutesResult, 'pages' | 'layouts' | 'errors' | 'loadings'>\n ): void {\n const priorityByPath = new Map<string, number>();\n const nameByPath = new Map<string, string>();\n\n const collectPriority = (route: RouteConfig): void => {\n const priority = route.handle?.order ?? 999;\n const routeName = route.name;\n\n const record = (value: unknown) => {\n if (typeof value !== 'string') {\n return;\n }\n if (!priorityByPath.has(value) || (priorityByPath.get(value) ?? 999) > priority) {\n priorityByPath.set(value, priority);\n nameByPath.set(value, routeName);\n }\n };\n\n record(route.page);\n record(route.layout);\n record(route.error ?? route.errors);\n record(route.loading);\n\n route.children?.forEach(collectPriority);\n };\n\n routes.forEach(collectPriority);\n routes.forEach((route) => this.registerRoute(route));\n\n if (!resolvers) {\n return;\n }\n\n const registerResolverMap = (\n map: Map<string, ComponentImport>,\n type: 'page' | 'layout' | 'error' | 'loading'\n ) => {\n for (const [path, importFn] of map.entries()) {\n const routeName = nameByPath.get(path) ?? path;\n const priority = priorityByPath.get(path) ?? 999;\n this.registerTask(`${routeName}_${type}_${path}`, importFn, routeName, priority);\n }\n };\n\n registerResolverMap(resolvers.pages, 'page');\n registerResolverMap(resolvers.layouts, 'layout');\n registerResolverMap(resolvers.errors, 'error');\n registerResolverMap(resolvers.loadings, 'loading');\n }\n\n /**\n * 预加载指定路由\n */\n async preloadRoute(routeName: string): Promise<void> {\n const tasks = Array.from(this.tasks.values()).filter(\n (task) => task.routeName === routeName && task.status === 'pending'\n );\n\n if (tasks.length === 0) {\n return;\n }\n\n await Promise.all(tasks.map((task) => this.preloadTask(task)));\n }\n\n /**\n * 预加载任务\n */\n private async preloadTask(task: PreloadTask): Promise<void> {\n if (task.status !== 'pending') {\n return;\n }\n\n task.status = 'loading';\n task.startTime = Date.now();\n\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n try {\n // 设置超时\n const timeoutPromise = new Promise((_, reject) => {\n timeoutId = setTimeout(() => reject(new Error('预加载超时')), this.config.timeout);\n });\n\n // 执行预加载\n await Promise.race([task.importFn(), timeoutPromise]);\n\n task.status = 'loaded';\n const duration = Date.now() - (task.startTime || 0);\n logger.debug(`路由组件预加载成功: ${task.routeName} (${duration}ms)`);\n } catch (error) {\n task.status = 'failed';\n logger.warn(`路由组件预加载失败: ${task.routeName}`, error);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n /**\n * 开始预加载(根据策略)\n */\n startPreload(): void {\n if (this.config.strategy === PreloadStrategy.NONE) {\n return;\n }\n\n this.stopPreload();\n\n // 延迟预加载,避免影响初始渲染\n this.preloadTimer = setTimeout(() => {\n const browserWindow = typeof window !== 'undefined' ? (window as Window & {\n requestIdleCallback?: (callback: () => void) => number;\n cancelIdleCallback?: (id: number) => void;\n }) : undefined;\n\n if (browserWindow?.requestIdleCallback) {\n this.idleHandle = browserWindow.requestIdleCallback(() => {\n this.executePreload();\n });\n return;\n }\n\n this.executePreload();\n }, this.config.delay);\n }\n\n /**\n * 执行预加载\n */\n private async executePreload(): Promise<void> {\n const tasks = Array.from(this.tasks.values())\n .filter((task) => task.status === 'pending')\n .sort((a, b) => a.priority - b.priority);\n\n if (tasks.length === 0) {\n return;\n }\n\n logger.debug(`开始预加载 ${tasks.length} 个路由组件`);\n\n // 根据策略决定预加载哪些任务\n let tasksToPreload: PreloadTask[] = [];\n\n switch (this.config.strategy) {\n case PreloadStrategy.ALL:\n tasksToPreload = tasks;\n break;\n case PreloadStrategy.NEXT_LEVEL:\n // 只预加载优先级最低的(最可能访问的)\n tasksToPreload = tasks.slice(0, Math.min(5, tasks.length));\n break;\n case PreloadStrategy.VISIBLE:\n tasksToPreload = tasks.filter(\n (task) => task.priority <= this.config.priorityThreshold\n );\n break;\n default:\n return;\n }\n\n // 并行预加载(限制并发数)\n const concurrency = 3;\n for (let i = 0; i < tasksToPreload.length; i += concurrency) {\n const batch = tasksToPreload.slice(i, i + concurrency);\n await Promise.all(batch.map((task) => this.preloadTask(task)));\n }\n\n logger.debug('路由组件预加载完成');\n }\n\n /**\n * 停止预加载\n */\n stopPreload(): void {\n const browserWindow = typeof window !== 'undefined' ? (window as Window & {\n cancelIdleCallback?: (id: number) => void;\n }) : undefined;\n\n if (this.preloadTimer) {\n clearTimeout(this.preloadTimer);\n this.preloadTimer = null;\n }\n if (this.idleHandle !== null && browserWindow?.cancelIdleCallback) {\n browserWindow.cancelIdleCallback(this.idleHandle);\n this.idleHandle = null;\n }\n }\n\n /**\n * 清空所有任务\n */\n clear(): void {\n this.tasks.clear();\n this.stopPreload();\n logger.debug('路由预加载任务已清空');\n }\n\n /**\n * 获取预加载统计信息\n */\n getStats(): {\n total: number;\n pending: number;\n loading: number;\n loaded: number;\n failed: number;\n } {\n const stats = {\n total: this.tasks.size,\n pending: 0,\n loading: 0,\n loaded: 0,\n failed: 0,\n };\n\n for (const task of this.tasks.values()) {\n stats[task.status]++;\n }\n\n return stats;\n }\n}\n\n/**\n * 获取路由预加载管理器单例\n */\nlet routePreloaderInstance: RoutePreloader | null = null;\n\nexport function getRoutePreloader(config?: PreloadConfig): RoutePreloader {\n if (!routePreloaderInstance) {\n routePreloaderInstance = new RoutePreloader(config);\n }\n return routePreloaderInstance;\n}\n"],"names":["logger","PreloadStrategy","RoutePreloader","updateConfig","config","strategy","delay","priorityThreshold","timeout","shouldRegister","priority","registerTask","key","importFn","routeName","tasks","set","status","registerRoute","route","page","layout","handle","order","name","children","forEach","child","registerRoutes","routes","resolvers","priorityByPath","Map","nameByPath","collectPriority","record","value","has","get","error","errors","loading","registerResolverMap","map","type","path","entries","pages","layouts","loadings","preloadRoute","Array","from","values","filter","task","length","Promise","all","preloadTask","startTime","Date","now","timeoutId","timeoutPromise","_","reject","setTimeout","Error","race","duration","debug","warn","clearTimeout","startPreload","stopPreload","preloadTimer","browserWindow","window","undefined","requestIdleCallback","idleHandle","executePreload","sort","a","b","tasksToPreload","slice","Math","min","concurrency","i","batch","cancelIdleCallback","clear","getStats","stats","total","size","pending","loaded","failed","routePreloaderInstance","getRoutePreloader"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/performance/index.ts"],"sourcesContent":["/**\n * 路由性能优化模块入口\n */\n\nexport * from './RouteCache';\nexport * from './RoutePreloader';\n"],"names":[],"mappings":"AAAA;;CAEC;;;;qBAEa;qBACA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/performance/index.ts"],"sourcesContent":["/**\n * 路由性能优化模块入口\n */\n\nexport * from './RouteCache';\nexport * from './RoutePreloader';\n"],"names":[],"mappings":"AAAA;;CAEC,GAED,cAAc,eAAe;AAC7B,cAAc,mBAAmB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/plugin/RouterPluginManager.ts"],"sourcesContent":["/**\n * 路由插件管理器\n * 负责插件的注册、执行和生命周期管理\n */\n\nimport { logger } from '@vlian/logger';\nimport type { RouterPlugin, PluginContext, PluginRegisterOptions } from './types';\nimport { PluginLifecycleStage } from './types';\n\n/**\n * 插件状态\n */\ntype PluginStatus = 'registered' | 'initialized' | 'destroyed';\n\n/**\n * 插件注册信息\n */\ninterface PluginRegistration {\n /**\n * 插件实例\n */\n plugin: RouterPlugin;\n\n /**\n * 插件状态\n */\n status: PluginStatus;\n\n /**\n * 注册时间\n */\n registeredAt: number;\n}\n\n/**\n * 路由插件管理器\n */\nexport class RouterPluginManager {\n private plugins: Map<string, PluginRegistration> = new Map();\n\n /**\n * 注册插件\n * \n * @param plugin - 插件实例\n * @param options - 注册选项\n * @returns 取消注册函数\n */\n register(plugin: RouterPlugin, options: PluginRegisterOptions = {}): () => void {\n // 验证插件\n if (!plugin.name) {\n throw new Error('插件必须提供名称');\n }\n\n // 检查是否已存在\n if (this.plugins.has(plugin.name) && !options.overwrite) {\n throw new Error(`插件 \"${plugin.name}\" 已存在`);\n }\n\n // 设置默认值\n const pluginWithDefaults: RouterPlugin = {\n priority: 100,\n enabled: true,\n ...plugin,\n };\n\n // 检查依赖\n if (pluginWithDefaults.dependencies) {\n const missingDeps = pluginWithDefaults.dependencies.filter(\n (dep) => !this.plugins.has(dep)\n );\n if (missingDeps.length > 0) {\n throw new Error(\n `插件 \"${plugin.name}\" 缺少依赖: ${missingDeps.join(', ')}`\n );\n }\n }\n\n // 注册插件\n this.plugins.set(plugin.name, {\n plugin: pluginWithDefaults,\n status: 'registered',\n registeredAt: Date.now(),\n });\n\n logger.debug(`路由插件已注册: ${plugin.name}`);\n\n // 调用注册钩子\n if (pluginWithDefaults.hooks?.onRegister) {\n try {\n const context: PluginContext = {\n config: {} as any, // 在注册阶段可能还没有配置\n meta: { stage: PluginLifecycleStage.REGISTER },\n };\n pluginWithDefaults.hooks.onRegister(context);\n } catch (error) {\n logger.error(`插件注册钩子执行失败: ${plugin.name}`, error);\n }\n }\n\n // 返回取消注册函数\n return () => {\n this.unregister(plugin.name);\n };\n }\n\n /**\n * 批量注册插件\n * \n * @param plugins - 插件数组\n * @param options - 注册选项\n */\n registerBatch(plugins: RouterPlugin[], options: PluginRegisterOptions = {}): void {\n // 按依赖关系排序\n const sortedPlugins = this.sortByDependencies(plugins);\n\n sortedPlugins.forEach((plugin) => {\n this.register(plugin, options);\n });\n }\n\n /**\n * 按依赖关系排序插件(拓扑排序)\n */\n private sortByDependencies(plugins: RouterPlugin[]): RouterPlugin[] {\n const sorted: RouterPlugin[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const visit = (plugin: RouterPlugin): void => {\n if (visiting.has(plugin.name || '')) {\n throw new Error(`检测到循环依赖: ${plugin.name}`);\n }\n\n if (visited.has(plugin.name || '')) {\n return;\n }\n\n visiting.add(plugin.name || '');\n\n // 先访问依赖\n if (plugin.dependencies) {\n plugin.dependencies.forEach((depName) => {\n const dep = plugins.find((p) => p.name === depName);\n if (dep) {\n visit(dep);\n }\n });\n }\n\n visiting.delete(plugin.name || '');\n visited.add(plugin.name || '');\n sorted.push(plugin);\n };\n\n plugins.forEach((plugin) => {\n if (!visited.has(plugin.name || '')) {\n visit(plugin);\n }\n });\n\n return sorted;\n }\n\n /**\n * 取消注册插件\n * \n * @param name - 插件名称\n */\n unregister(name: string): void {\n const registration = this.plugins.get(name);\n if (!registration) {\n return;\n }\n\n // 调用销毁钩子\n if (registration.plugin.hooks?.onDestroy) {\n try {\n const context: PluginContext = {\n config: {} as any,\n meta: { stage: PluginLifecycleStage.DESTROY },\n };\n registration.plugin.hooks.onDestroy(context);\n } catch (error) {\n logger.error(`插件销毁钩子执行失败: ${name}`, error);\n }\n }\n\n this.plugins.delete(name);\n logger.debug(`路由插件已取消注册: ${name}`);\n }\n\n /**\n * 执行插件钩子\n * \n * @param stage - 生命周期阶段\n * @param context - 插件上下文\n */\n async executeHooks(stage: PluginLifecycleStage, context: PluginContext): Promise<void> {\n // 获取启用的插件并按优先级排序\n const enabledPlugins = Array.from(this.plugins.values())\n .filter((reg) => reg.plugin.enabled !== false)\n .sort((a, b) => (a.plugin.priority || 100) - (b.plugin.priority || 100));\n\n // 根据阶段选择钩子\n const hookMap: Partial<Record<PluginLifecycleStage, keyof NonNullable<RouterPlugin['hooks']>>> = {\n [PluginLifecycleStage.REGISTER]: 'onRegister',\n [PluginLifecycleStage.BEFORE_INIT]: 'onBeforeInit',\n [PluginLifecycleStage.AFTER_INIT]: 'onAfterInit',\n [PluginLifecycleStage.BEFORE_TRANSFORM]: 'onBeforeTransform',\n [PluginLifecycleStage.AFTER_TRANSFORM]: 'onAfterTransform',\n [PluginLifecycleStage.BEFORE_MATCH]: 'onBeforeMatch',\n [PluginLifecycleStage.AFTER_MATCH]: 'onAfterMatch',\n [PluginLifecycleStage.DESTROY]: 'onDestroy',\n };\n\n const hookName = hookMap[stage];\n if (!hookName) {\n return;\n }\n\n // 执行钩子\n for (const registration of enabledPlugins) {\n const hook = registration.plugin.hooks?.[hookName];\n if (hook) {\n try {\n await hook(context);\n } catch (error) {\n logger.error(`插件钩子执行失败: ${registration.plugin.name}.${hookName}`, error);\n }\n }\n }\n }\n\n /**\n * 获取插件\n * \n * @param name - 插件名称\n * @returns 插件实例,如果不存在返回 undefined\n */\n getPlugin(name: string): RouterPlugin | undefined {\n return this.plugins.get(name)?.plugin;\n }\n\n /**\n * 获取所有插件\n * \n * @returns 插件数组\n */\n getAllPlugins(): RouterPlugin[] {\n return Array.from(this.plugins.values()).map((reg) => reg.plugin);\n }\n\n /**\n * 获取启用的插件\n * \n * @returns 启用的插件数组\n */\n getEnabledPlugins(): RouterPlugin[] {\n return Array.from(this.plugins.values())\n .filter((reg) => reg.plugin.enabled !== false)\n .map((reg) => reg.plugin);\n }\n\n /**\n * 清空所有插件\n */\n clear(): void {\n // 调用所有插件的销毁钩子\n for (const [name, registration] of this.plugins.entries()) {\n if (registration.plugin.hooks?.onDestroy) {\n try {\n const context: PluginContext = {\n config: {} as any,\n meta: { stage: PluginLifecycleStage.DESTROY },\n };\n registration.plugin.hooks.onDestroy(context);\n } catch (error) {\n logger.error(`插件销毁钩子执行失败: ${name}`, error);\n }\n }\n }\n\n this.plugins.clear();\n logger.debug('所有路由插件已清空');\n }\n\n /**\n * 获取插件数量\n * \n * @returns 插件数量\n */\n getCount(): number {\n return this.plugins.size;\n }\n}\n\n/**\n * 获取路由插件管理器单例\n */\nlet pluginManagerInstance: RouterPluginManager | null = null;\n\nexport function getRouterPluginManager(): RouterPluginManager {\n if (!pluginManagerInstance) {\n pluginManagerInstance = new RouterPluginManager();\n }\n return pluginManagerInstance;\n}\n"],"names":["RouterPluginManager","getRouterPluginManager","register","plugin","options","name","Error","plugins","has","overwrite","pluginWithDefaults","priority","enabled","dependencies","missingDeps","filter","dep","length","join","set","status","registeredAt","Date","now","logger","debug","hooks","onRegister","context","config","meta","stage","PluginLifecycleStage","REGISTER","error","unregister","registerBatch","sortedPlugins","sortByDependencies","forEach","sorted","visited","Set","visiting","visit","add","depName","find","p","delete","push","registration","get","onDestroy","DESTROY","executeHooks","enabledPlugins","Array","from","values","reg","sort","a","b","hookMap","BEFORE_INIT","AFTER_INIT","BEFORE_TRANSFORM","AFTER_TRANSFORM","BEFORE_MATCH","AFTER_MATCH","hookName","hook","getPlugin","getAllPlugins","map","getEnabledPlugins","clear","entries","getCount","size","Map","pluginManagerInstance"],"mappings":"AAAA;;;CAGC;;;;;;;;;;;QAkCYA;eAAAA;;QAwQGC;eAAAA;;;wBAxSO;uBAEc;;;;;;;;;;;;;;AA8B9B,IAAA,AAAMD,sBAAN,MAAMA;IAGX;;;;;;GAMC,GACDE,SAASC,MAAoB,EAAEC,UAAiC,CAAC,CAAC,EAAc;QAC9E,OAAO;QACP,IAAI,CAACD,OAAOE,IAAI,EAAE;YAChB,MAAM,IAAIC,MAAM;QAClB;QAEA,UAAU;QACV,IAAI,IAAI,CAACC,OAAO,CAACC,GAAG,CAACL,OAAOE,IAAI,KAAK,CAACD,QAAQK,SAAS,EAAE;YACvD,MAAM,IAAIH,MAAM,CAAC,IAAI,EAAEH,OAAOE,IAAI,CAAC,KAAK,CAAC;QAC3C;QAEA,QAAQ;QACR,MAAMK,qBAAmC;YACvCC,UAAU;YACVC,SAAS;YACT,GAAGT,MAAM;QACX;QAEA,OAAO;QACP,IAAIO,mBAAmBG,YAAY,EAAE;YACnC,MAAMC,cAAcJ,mBAAmBG,YAAY,CAACE,MAAM,CACxD,CAACC,MAAQ,CAAC,IAAI,CAACT,OAAO,CAACC,GAAG,CAACQ;YAE7B,IAAIF,YAAYG,MAAM,GAAG,GAAG;gBAC1B,MAAM,IAAIX,MACR,CAAC,IAAI,EAAEH,OAAOE,IAAI,CAAC,QAAQ,EAAES,YAAYI,IAAI,CAAC,OAAO;YAEzD;QACF;QAEA,OAAO;QACP,IAAI,CAACX,OAAO,CAACY,GAAG,CAAChB,OAAOE,IAAI,EAAE;YAC5BF,QAAQO;YACRU,QAAQ;YACRC,cAAcC,KAAKC,GAAG;QACxB;QAEAC,cAAM,CAACC,KAAK,CAAC,CAAC,SAAS,EAAEtB,OAAOE,IAAI,EAAE;QAEtC,SAAS;QACT,IAAIK,mBAAmBgB,KAAK,EAAEC,YAAY;YACxC,IAAI;gBACF,MAAMC,UAAyB;oBAC7BC,QAAQ,CAAC;oBACTC,MAAM;wBAAEC,OAAOC,2BAAoB,CAACC,QAAQ;oBAAC;gBAC/C;gBACAvB,mBAAmBgB,KAAK,CAACC,UAAU,CAACC;YACtC,EAAE,OAAOM,OAAO;gBACdV,cAAM,CAACU,KAAK,CAAC,CAAC,YAAY,EAAE/B,OAAOE,IAAI,EAAE,EAAE6B;YAC7C;QACF;QAEA,WAAW;QACX,OAAO;YACL,IAAI,CAACC,UAAU,CAAChC,OAAOE,IAAI;QAC7B;IACF;IAEA;;;;;GAKC,GACD+B,cAAc7B,OAAuB,EAAEH,UAAiC,CAAC,CAAC,EAAQ;QAChF,UAAU;QACV,MAAMiC,gBAAgB,IAAI,CAACC,kBAAkB,CAAC/B;QAE9C8B,cAAcE,OAAO,CAAC,CAACpC;YACrB,IAAI,CAACD,QAAQ,CAACC,QAAQC;QACxB;IACF;IAEA;;GAEC,GACD,AAAQkC,mBAAmB/B,OAAuB,EAAkB;QAClE,MAAMiC,SAAyB,EAAE;QACjC,MAAMC,UAAU,IAAIC;QACpB,MAAMC,WAAW,IAAID;QAErB,MAAME,QAAQ,CAACzC;YACb,IAAIwC,SAASnC,GAAG,CAACL,OAAOE,IAAI,IAAI,KAAK;gBACnC,MAAM,IAAIC,MAAM,CAAC,SAAS,EAAEH,OAAOE,IAAI,EAAE;YAC3C;YAEA,IAAIoC,QAAQjC,GAAG,CAACL,OAAOE,IAAI,IAAI,KAAK;gBAClC;YACF;YAEAsC,SAASE,GAAG,CAAC1C,OAAOE,IAAI,IAAI;YAE5B,QAAQ;YACR,IAAIF,OAAOU,YAAY,EAAE;gBACvBV,OAAOU,YAAY,CAAC0B,OAAO,CAAC,CAACO;oBAC3B,MAAM9B,MAAMT,QAAQwC,IAAI,CAAC,CAACC,IAAMA,EAAE3C,IAAI,KAAKyC;oBAC3C,IAAI9B,KAAK;wBACP4B,MAAM5B;oBACR;gBACF;YACF;YAEA2B,SAASM,MAAM,CAAC9C,OAAOE,IAAI,IAAI;YAC/BoC,QAAQI,GAAG,CAAC1C,OAAOE,IAAI,IAAI;YAC3BmC,OAAOU,IAAI,CAAC/C;QACd;QAEAI,QAAQgC,OAAO,CAAC,CAACpC;YACf,IAAI,CAACsC,QAAQjC,GAAG,CAACL,OAAOE,IAAI,IAAI,KAAK;gBACnCuC,MAAMzC;YACR;QACF;QAEA,OAAOqC;IACT;IAEA;;;;GAIC,GACDL,WAAW9B,IAAY,EAAQ;QAC7B,MAAM8C,eAAe,IAAI,CAAC5C,OAAO,CAAC6C,GAAG,CAAC/C;QACtC,IAAI,CAAC8C,cAAc;YACjB;QACF;QAEA,SAAS;QACT,IAAIA,aAAahD,MAAM,CAACuB,KAAK,EAAE2B,WAAW;YACxC,IAAI;gBACF,MAAMzB,UAAyB;oBAC7BC,QAAQ,CAAC;oBACTC,MAAM;wBAAEC,OAAOC,2BAAoB,CAACsB,OAAO;oBAAC;gBAC9C;gBACAH,aAAahD,MAAM,CAACuB,KAAK,CAAC2B,SAAS,CAACzB;YACtC,EAAE,OAAOM,OAAO;gBACdV,cAAM,CAACU,KAAK,CAAC,CAAC,YAAY,EAAE7B,MAAM,EAAE6B;YACtC;QACF;QAEA,IAAI,CAAC3B,OAAO,CAAC0C,MAAM,CAAC5C;QACpBmB,cAAM,CAACC,KAAK,CAAC,CAAC,WAAW,EAAEpB,MAAM;IACnC;IAEA;;;;;GAKC,GACD,MAAMkD,aAAaxB,KAA2B,EAAEH,OAAsB,EAAiB;QACrF,iBAAiB;QACjB,MAAM4B,iBAAiBC,MAAMC,IAAI,CAAC,IAAI,CAACnD,OAAO,CAACoD,MAAM,IAClD5C,MAAM,CAAC,CAAC6C,MAAQA,IAAIzD,MAAM,CAACS,OAAO,KAAK,OACvCiD,IAAI,CAAC,CAACC,GAAGC,IAAM,AAACD,CAAAA,EAAE3D,MAAM,CAACQ,QAAQ,IAAI,GAAE,IAAMoD,CAAAA,EAAE5D,MAAM,CAACQ,QAAQ,IAAI,GAAE;QAEvE,WAAW;QACX,MAAMqD,UAA2F;YAC/F,CAAChC,2BAAoB,CAACC,QAAQ,CAAC,EAAE;YACjC,CAACD,2BAAoB,CAACiC,WAAW,CAAC,EAAE;YACpC,CAACjC,2BAAoB,CAACkC,UAAU,CAAC,EAAE;YACnC,CAAClC,2BAAoB,CAACmC,gBAAgB,CAAC,EAAE;YACzC,CAACnC,2BAAoB,CAACoC,eAAe,CAAC,EAAE;YACxC,CAACpC,2BAAoB,CAACqC,YAAY,CAAC,EAAE;YACrC,CAACrC,2BAAoB,CAACsC,WAAW,CAAC,EAAE;YACpC,CAACtC,2BAAoB,CAACsB,OAAO,CAAC,EAAE;QAClC;QAEA,MAAMiB,WAAWP,OAAO,CAACjC,MAAM;QAC/B,IAAI,CAACwC,UAAU;YACb;QACF;QAEA,OAAO;QACP,KAAK,MAAMpB,gBAAgBK,eAAgB;YACzC,MAAMgB,OAAOrB,aAAahD,MAAM,CAACuB,KAAK,EAAE,CAAC6C,SAAS;YAClD,IAAIC,MAAM;gBACR,IAAI;oBACF,MAAMA,KAAK5C;gBACb,EAAE,OAAOM,OAAO;oBACdV,cAAM,CAACU,KAAK,CAAC,CAAC,UAAU,EAAEiB,aAAahD,MAAM,CAACE,IAAI,CAAC,CAAC,EAAEkE,UAAU,EAAErC;gBACpE;YACF;QACF;IACF;IAEA;;;;;GAKC,GACDuC,UAAUpE,IAAY,EAA4B;QAChD,OAAO,IAAI,CAACE,OAAO,CAAC6C,GAAG,CAAC/C,OAAOF;IACjC;IAEA;;;;GAIC,GACDuE,gBAAgC;QAC9B,OAAOjB,MAAMC,IAAI,CAAC,IAAI,CAACnD,OAAO,CAACoD,MAAM,IAAIgB,GAAG,CAAC,CAACf,MAAQA,IAAIzD,MAAM;IAClE;IAEA;;;;GAIC,GACDyE,oBAAoC;QAClC,OAAOnB,MAAMC,IAAI,CAAC,IAAI,CAACnD,OAAO,CAACoD,MAAM,IAClC5C,MAAM,CAAC,CAAC6C,MAAQA,IAAIzD,MAAM,CAACS,OAAO,KAAK,OACvC+D,GAAG,CAAC,CAACf,MAAQA,IAAIzD,MAAM;IAC5B;IAEA;;GAEC,GACD0E,QAAc;QACZ,cAAc;QACd,KAAK,MAAM,CAACxE,MAAM8C,aAAa,IAAI,IAAI,CAAC5C,OAAO,CAACuE,OAAO,GAAI;YACzD,IAAI3B,aAAahD,MAAM,CAACuB,KAAK,EAAE2B,WAAW;gBACxC,IAAI;oBACF,MAAMzB,UAAyB;wBAC7BC,QAAQ,CAAC;wBACTC,MAAM;4BAAEC,OAAOC,2BAAoB,CAACsB,OAAO;wBAAC;oBAC9C;oBACAH,aAAahD,MAAM,CAACuB,KAAK,CAAC2B,SAAS,CAACzB;gBACtC,EAAE,OAAOM,OAAO;oBACdV,cAAM,CAACU,KAAK,CAAC,CAAC,YAAY,EAAE7B,MAAM,EAAE6B;gBACtC;YACF;QACF;QAEA,IAAI,CAAC3B,OAAO,CAACsE,KAAK;QAClBrD,cAAM,CAACC,KAAK,CAAC;IACf;IAEA;;;;GAIC,GACDsD,WAAmB;QACjB,OAAO,IAAI,CAACxE,OAAO,CAACyE,IAAI;IAC1B;;QA/PA,uBAAQzE,WAA2C,IAAI0E;;AAgQzD;AAEA;;CAEC,GACD,IAAIC,wBAAoD;AAEjD,SAASjF;IACd,IAAI,CAACiF,uBAAuB;QAC1BA,wBAAwB,IAAIlF;IAC9B;IACA,OAAOkF;AACT"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/plugin/RouterPluginManager.ts"],"sourcesContent":["/**\n * 路由插件管理器\n * 负责插件的注册、执行和生命周期管理\n */\n\nimport { logger } from '@vlian/logger';\nimport type { RouterPlugin, PluginContext, PluginRegisterOptions } from './types';\nimport { PluginLifecycleStage } from './types';\n\n/**\n * 插件状态\n */\ntype PluginStatus = 'registered' | 'initialized' | 'destroyed';\n\n/**\n * 插件注册信息\n */\ninterface PluginRegistration {\n /**\n * 插件实例\n */\n plugin: RouterPlugin;\n\n /**\n * 插件状态\n */\n status: PluginStatus;\n\n /**\n * 注册时间\n */\n registeredAt: number;\n}\n\n/**\n * 路由插件管理器\n */\nexport class RouterPluginManager {\n private plugins: Map<string, PluginRegistration> = new Map();\n\n /**\n * 注册插件\n * \n * @param plugin - 插件实例\n * @param options - 注册选项\n * @returns 取消注册函数\n */\n register(plugin: RouterPlugin, options: PluginRegisterOptions = {}): () => void {\n // 验证插件\n if (!plugin.name) {\n throw new Error('插件必须提供名称');\n }\n\n // 检查是否已存在\n if (this.plugins.has(plugin.name) && !options.overwrite) {\n throw new Error(`插件 \"${plugin.name}\" 已存在`);\n }\n\n // 设置默认值\n const pluginWithDefaults: RouterPlugin = {\n priority: 100,\n enabled: true,\n ...plugin,\n };\n\n // 检查依赖\n if (pluginWithDefaults.dependencies) {\n const missingDeps = pluginWithDefaults.dependencies.filter(\n (dep) => !this.plugins.has(dep)\n );\n if (missingDeps.length > 0) {\n throw new Error(\n `插件 \"${plugin.name}\" 缺少依赖: ${missingDeps.join(', ')}`\n );\n }\n }\n\n // 注册插件\n this.plugins.set(plugin.name, {\n plugin: pluginWithDefaults,\n status: 'registered',\n registeredAt: Date.now(),\n });\n\n logger.debug(`路由插件已注册: ${plugin.name}`);\n\n // 调用注册钩子\n if (pluginWithDefaults.hooks?.onRegister) {\n try {\n const context: PluginContext = {\n config: {} as any, // 在注册阶段可能还没有配置\n meta: { stage: PluginLifecycleStage.REGISTER },\n };\n pluginWithDefaults.hooks.onRegister(context);\n } catch (error) {\n logger.error(`插件注册钩子执行失败: ${plugin.name}`, error);\n }\n }\n\n // 返回取消注册函数\n return () => {\n this.unregister(plugin.name);\n };\n }\n\n /**\n * 批量注册插件\n * \n * @param plugins - 插件数组\n * @param options - 注册选项\n */\n registerBatch(plugins: RouterPlugin[], options: PluginRegisterOptions = {}): void {\n // 按依赖关系排序\n const sortedPlugins = this.sortByDependencies(plugins);\n\n sortedPlugins.forEach((plugin) => {\n this.register(plugin, options);\n });\n }\n\n /**\n * 按依赖关系排序插件(拓扑排序)\n */\n private sortByDependencies(plugins: RouterPlugin[]): RouterPlugin[] {\n const sorted: RouterPlugin[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n\n const visit = (plugin: RouterPlugin): void => {\n if (visiting.has(plugin.name || '')) {\n throw new Error(`检测到循环依赖: ${plugin.name}`);\n }\n\n if (visited.has(plugin.name || '')) {\n return;\n }\n\n visiting.add(plugin.name || '');\n\n // 先访问依赖\n if (plugin.dependencies) {\n plugin.dependencies.forEach((depName) => {\n const dep = plugins.find((p) => p.name === depName);\n if (dep) {\n visit(dep);\n }\n });\n }\n\n visiting.delete(plugin.name || '');\n visited.add(plugin.name || '');\n sorted.push(plugin);\n };\n\n plugins.forEach((plugin) => {\n if (!visited.has(plugin.name || '')) {\n visit(plugin);\n }\n });\n\n return sorted;\n }\n\n /**\n * 取消注册插件\n * \n * @param name - 插件名称\n */\n unregister(name: string): void {\n const registration = this.plugins.get(name);\n if (!registration) {\n return;\n }\n\n // 调用销毁钩子\n if (registration.plugin.hooks?.onDestroy) {\n try {\n const context: PluginContext = {\n config: {} as any,\n meta: { stage: PluginLifecycleStage.DESTROY },\n };\n registration.plugin.hooks.onDestroy(context);\n } catch (error) {\n logger.error(`插件销毁钩子执行失败: ${name}`, error);\n }\n }\n\n this.plugins.delete(name);\n logger.debug(`路由插件已取消注册: ${name}`);\n }\n\n /**\n * 执行插件钩子\n * \n * @param stage - 生命周期阶段\n * @param context - 插件上下文\n */\n async executeHooks(stage: PluginLifecycleStage, context: PluginContext): Promise<void> {\n // 获取启用的插件并按优先级排序\n const enabledPlugins = Array.from(this.plugins.values())\n .filter((reg) => reg.plugin.enabled !== false)\n .sort((a, b) => (a.plugin.priority || 100) - (b.plugin.priority || 100));\n\n // 根据阶段选择钩子\n const hookMap: Partial<Record<PluginLifecycleStage, keyof NonNullable<RouterPlugin['hooks']>>> = {\n [PluginLifecycleStage.REGISTER]: 'onRegister',\n [PluginLifecycleStage.BEFORE_INIT]: 'onBeforeInit',\n [PluginLifecycleStage.AFTER_INIT]: 'onAfterInit',\n [PluginLifecycleStage.BEFORE_TRANSFORM]: 'onBeforeTransform',\n [PluginLifecycleStage.AFTER_TRANSFORM]: 'onAfterTransform',\n [PluginLifecycleStage.BEFORE_MATCH]: 'onBeforeMatch',\n [PluginLifecycleStage.AFTER_MATCH]: 'onAfterMatch',\n [PluginLifecycleStage.DESTROY]: 'onDestroy',\n };\n\n const hookName = hookMap[stage];\n if (!hookName) {\n return;\n }\n\n // 执行钩子\n for (const registration of enabledPlugins) {\n const hook = registration.plugin.hooks?.[hookName];\n if (hook) {\n try {\n await hook(context);\n } catch (error) {\n logger.error(`插件钩子执行失败: ${registration.plugin.name}.${hookName}`, error);\n }\n }\n }\n }\n\n /**\n * 获取插件\n * \n * @param name - 插件名称\n * @returns 插件实例,如果不存在返回 undefined\n */\n getPlugin(name: string): RouterPlugin | undefined {\n return this.plugins.get(name)?.plugin;\n }\n\n /**\n * 获取所有插件\n * \n * @returns 插件数组\n */\n getAllPlugins(): RouterPlugin[] {\n return Array.from(this.plugins.values()).map((reg) => reg.plugin);\n }\n\n /**\n * 获取启用的插件\n * \n * @returns 启用的插件数组\n */\n getEnabledPlugins(): RouterPlugin[] {\n return Array.from(this.plugins.values())\n .filter((reg) => reg.plugin.enabled !== false)\n .map((reg) => reg.plugin);\n }\n\n /**\n * 清空所有插件\n */\n clear(): void {\n // 调用所有插件的销毁钩子\n for (const [name, registration] of this.plugins.entries()) {\n if (registration.plugin.hooks?.onDestroy) {\n try {\n const context: PluginContext = {\n config: {} as any,\n meta: { stage: PluginLifecycleStage.DESTROY },\n };\n registration.plugin.hooks.onDestroy(context);\n } catch (error) {\n logger.error(`插件销毁钩子执行失败: ${name}`, error);\n }\n }\n }\n\n this.plugins.clear();\n logger.debug('所有路由插件已清空');\n }\n\n /**\n * 获取插件数量\n * \n * @returns 插件数量\n */\n getCount(): number {\n return this.plugins.size;\n }\n}\n\n/**\n * 获取路由插件管理器单例\n */\nlet pluginManagerInstance: RouterPluginManager | null = null;\n\nexport function getRouterPluginManager(): RouterPluginManager {\n if (!pluginManagerInstance) {\n pluginManagerInstance = new RouterPluginManager();\n }\n return pluginManagerInstance;\n}\n"],"names":["logger","PluginLifecycleStage","RouterPluginManager","register","plugin","options","name","Error","plugins","has","overwrite","pluginWithDefaults","priority","enabled","dependencies","missingDeps","filter","dep","length","join","set","status","registeredAt","Date","now","debug","hooks","onRegister","context","config","meta","stage","REGISTER","error","unregister","registerBatch","sortedPlugins","sortByDependencies","forEach","sorted","visited","Set","visiting","visit","add","depName","find","p","delete","push","registration","get","onDestroy","DESTROY","executeHooks","enabledPlugins","Array","from","values","reg","sort","a","b","hookMap","BEFORE_INIT","AFTER_INIT","BEFORE_TRANSFORM","AFTER_TRANSFORM","BEFORE_MATCH","AFTER_MATCH","hookName","hook","getPlugin","getAllPlugins","map","getEnabledPlugins","clear","entries","getCount","size","Map","pluginManagerInstance","getRouterPluginManager"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/plugin/index.ts"],"sourcesContent":["/**\n * 路由插件模块入口\n */\n\nexport * from './types';\nexport * from './RouterPluginManager';\n"],"names":[],"mappings":"AAAA;;CAEC;;;;qBAEa;qBACA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/plugin/index.ts"],"sourcesContent":["/**\n * 路由插件模块入口\n */\n\nexport * from './types';\nexport * from './RouterPluginManager';\n"],"names":[],"mappings":"AAAA;;CAEC,GAED,cAAc,UAAU;AACxB,cAAc,wBAAwB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/plugin/types.ts"],"sourcesContent":["/**\n * 路由插件类型定义\n */\n\nimport type { RouterConfig, RouteConfig } from '../types';\nimport type { RouterMiddlewareContext } from '../middleware/types';\n\n/**\n * 插件生命周期阶段\n */\nexport enum PluginLifecycleStage {\n /**\n * 插件注册阶段\n */\n REGISTER = 'register',\n\n /**\n * 路由初始化前\n */\n BEFORE_INIT = 'before-init',\n\n /**\n * 路由初始化后\n */\n AFTER_INIT = 'after-init',\n\n /**\n * 路由转换前\n */\n BEFORE_TRANSFORM = 'before-transform',\n\n /**\n * 路由转换后\n */\n AFTER_TRANSFORM = 'after-transform',\n\n /**\n * 路由匹配前\n */\n BEFORE_MATCH = 'before-match',\n\n /**\n * 路由匹配后\n */\n AFTER_MATCH = 'after-match',\n\n /**\n * 插件销毁阶段\n */\n DESTROY = 'destroy',\n}\n\n/**\n * 插件上下文\n */\nexport interface PluginContext {\n /**\n * 路由配置\n */\n config: RouterConfig;\n\n /**\n * 转换后的路由\n */\n routes?: RouteConfig[];\n\n /**\n * 中间件上下文(在路由匹配时可用)\n */\n middlewareContext?: RouterMiddlewareContext;\n\n /**\n * 插件元数据\n */\n meta?: Record<string, unknown>;\n}\n\n/**\n * 插件钩子函数\n */\nexport type PluginHook = (context: PluginContext) => void | Promise<void>;\n\n/**\n * 路由插件接口\n */\nexport interface RouterPlugin {\n /**\n * 插件名称(唯一标识)\n */\n name: string;\n\n /**\n * 插件版本\n */\n version?: string;\n\n /**\n * 插件描述\n */\n description?: string;\n\n /**\n * 插件优先级(数字越小优先级越高)\n * @default 100\n */\n priority?: number;\n\n /**\n * 是否启用\n * @default true\n */\n enabled?: boolean;\n\n /**\n * 插件依赖(其他插件名称列表)\n */\n dependencies?: string[];\n\n /**\n * 插件配置\n */\n config?: Record<string, unknown>;\n\n /**\n * 生命周期钩子\n */\n hooks?: {\n /**\n * 插件注册时调用\n */\n onRegister?: PluginHook;\n\n /**\n * 路由初始化前调用\n */\n onBeforeInit?: PluginHook;\n\n /**\n * 路由初始化后调用\n */\n onAfterInit?: PluginHook;\n\n /**\n * 路由转换前调用\n */\n onBeforeTransform?: PluginHook;\n\n /**\n * 路由转换后调用\n */\n onAfterTransform?: PluginHook;\n\n /**\n * 路由匹配前调用\n */\n onBeforeMatch?: PluginHook;\n\n /**\n * 路由匹配后调用\n */\n onAfterMatch?: PluginHook;\n\n /**\n * 插件销毁时调用\n */\n onDestroy?: PluginHook;\n };\n}\n\n/**\n * 插件注册选项\n */\nexport interface PluginRegisterOptions {\n /**\n * 是否覆盖已存在的插件\n * @default false\n */\n overwrite?: boolean;\n\n /**\n * 插件配置\n */\n config?: Record<string, unknown>;\n}\n"],"names":["PluginLifecycleStage"],"mappings":"AAAA;;CAEC;;;;+BAQWA;;;eAAAA;;;AAAL,IAAA,AAAKA,8CAAAA;IACV;;GAEC;IAGD;;GAEC;IAGD;;GAEC;IAGD;;GAEC;IAGD;;GAEC;IAGD;;GAEC;IAGD;;GAEC;IAGD;;GAEC;WAtCSA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/plugin/types.ts"],"sourcesContent":["/**\n * 路由插件类型定义\n */\n\nimport type { RouterConfig, RouteConfig } from '../types';\nimport type { RouterMiddlewareContext } from '../middleware/types';\n\n/**\n * 插件生命周期阶段\n */\nexport enum PluginLifecycleStage {\n /**\n * 插件注册阶段\n */\n REGISTER = 'register',\n\n /**\n * 路由初始化前\n */\n BEFORE_INIT = 'before-init',\n\n /**\n * 路由初始化后\n */\n AFTER_INIT = 'after-init',\n\n /**\n * 路由转换前\n */\n BEFORE_TRANSFORM = 'before-transform',\n\n /**\n * 路由转换后\n */\n AFTER_TRANSFORM = 'after-transform',\n\n /**\n * 路由匹配前\n */\n BEFORE_MATCH = 'before-match',\n\n /**\n * 路由匹配后\n */\n AFTER_MATCH = 'after-match',\n\n /**\n * 插件销毁阶段\n */\n DESTROY = 'destroy',\n}\n\n/**\n * 插件上下文\n */\nexport interface PluginContext {\n /**\n * 路由配置\n */\n config: RouterConfig;\n\n /**\n * 转换后的路由\n */\n routes?: RouteConfig[];\n\n /**\n * 中间件上下文(在路由匹配时可用)\n */\n middlewareContext?: RouterMiddlewareContext;\n\n /**\n * 插件元数据\n */\n meta?: Record<string, unknown>;\n}\n\n/**\n * 插件钩子函数\n */\nexport type PluginHook = (context: PluginContext) => void | Promise<void>;\n\n/**\n * 路由插件接口\n */\nexport interface RouterPlugin {\n /**\n * 插件名称(唯一标识)\n */\n name: string;\n\n /**\n * 插件版本\n */\n version?: string;\n\n /**\n * 插件描述\n */\n description?: string;\n\n /**\n * 插件优先级(数字越小优先级越高)\n * @default 100\n */\n priority?: number;\n\n /**\n * 是否启用\n * @default true\n */\n enabled?: boolean;\n\n /**\n * 插件依赖(其他插件名称列表)\n */\n dependencies?: string[];\n\n /**\n * 插件配置\n */\n config?: Record<string, unknown>;\n\n /**\n * 生命周期钩子\n */\n hooks?: {\n /**\n * 插件注册时调用\n */\n onRegister?: PluginHook;\n\n /**\n * 路由初始化前调用\n */\n onBeforeInit?: PluginHook;\n\n /**\n * 路由初始化后调用\n */\n onAfterInit?: PluginHook;\n\n /**\n * 路由转换前调用\n */\n onBeforeTransform?: PluginHook;\n\n /**\n * 路由转换后调用\n */\n onAfterTransform?: PluginHook;\n\n /**\n * 路由匹配前调用\n */\n onBeforeMatch?: PluginHook;\n\n /**\n * 路由匹配后调用\n */\n onAfterMatch?: PluginHook;\n\n /**\n * 插件销毁时调用\n */\n onDestroy?: PluginHook;\n };\n}\n\n/**\n * 插件注册选项\n */\nexport interface PluginRegisterOptions {\n /**\n * 是否覆盖已存在的插件\n * @default false\n */\n overwrite?: boolean;\n\n /**\n * 插件配置\n */\n config?: Record<string, unknown>;\n}\n"],"names":["PluginLifecycleStage"],"mappings":"AAAA;;CAEC,GAKD;;CAEC,GACD,OAAO,IAAA,AAAKA,8CAAAA;IACV;;GAEC;IAGD;;GAEC;IAGD;;GAEC;IAGD;;GAEC;IAGD;;GAEC;IAGD;;GAEC;IAGD;;GAEC;IAGD;;GAEC;WAtCSA;MAwCX"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/router/types.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/router/types.ts"],"sourcesContent":["import type { AppInstance } from '../startup/AppInstance';\nimport type { createBrowserRouter, createMemoryRouter } from 'react-router-dom';\nimport type { TransformOptions } from './utils/transform';\nimport type { PreloadConfig } from './performance/RoutePreloader';\n\nexport type RouteItemHandle = {\n title: string,\n i18nKey?: string,\n order: number,\n icon?: string,\n // 在菜单中隐藏\n hideInMenu?: boolean,\n // 隐藏尾部\n hideFooter?: boolean,\n // 保活\n keepAlive?: boolean,\n // 是否需要的登录\n needLogin?: boolean,\n // 角色\n roles?: Array<string>,\n // 路由名称,唯一Key\n name?: string,\n // 其他\n [key: string]: unknown,\n}\nexport type RouteItem = {\n // 布局 布局对象的key或动态导入函数\n layout?: string | ComponentImport | null,\n // 页面 页面对象的key或动态导入函数\n page?: string | ComponentImport | null,\n // loading 加载对象的key或动态导入函数\n loading?: string | ComponentImport | null,\n // 错误 组件的key或动态导入函数\n errors?: string | ComponentImport | null,\n // 错误(兼容字段)组件的key或动态导入函数\n error?: string | ComponentImport | null,\n // 路由名称,唯一Key\n name: string,\n // 路由\n path: string | undefined,\n // 是否分组路由\n isGroup?: boolean,\n // 是否开启重定向\n enableRedirection?: boolean,\n // 额外参数\n handle: RouteItemHandle,\n children?: RouteItem[]\n}\n\nexport type RouteMapType = Record<string, () => Promise<any>>;\n\n/**\n * DOM 路由选项类型(从 createBrowserRouter 和 createHashRouter 的参数类型提取)\n */\nexport type DOMRouterOpts = Parameters<typeof createBrowserRouter>[1];\n\n/**\n * Memory 路由选项类型(从 createMemoryRouter 的参数类型提取)\n */\nexport type MemoryRouterOpts = Parameters<typeof createMemoryRouter>[1];\n\n/**\n * 路由元数据(兼容 RouteItemHandle)\n * \n * @deprecated 建议直接使用 RouteItem 和 RouteItemHandle\n */\nexport interface RouteMeta {\n /**\n * 路由标题\n */\n title?: string;\n\n /**\n * 图标\n */\n icon?: string;\n\n /**\n * 排序\n */\n order?: number;\n\n /**\n * 权限标识\n */\n auth?: string | string[];\n\n /**\n * 是否在菜单中隐藏\n */\n hideInMenu?: boolean;\n\n /**\n * 是否启用 KeepAlive\n */\n keepAlive?: boolean;\n\n /**\n * 是否需要登录\n */\n needLogin?: boolean;\n\n /**\n * 角色列表\n */\n roles?: string[];\n\n /**\n * 路由名称(唯一标识)\n */\n name?: string;\n\n /**\n * 其他自定义元数据\n */\n [key: string]: unknown;\n}\n\n/**\n * 动态导入函数类型\n * \n * 用于懒加载组件,返回一个 Promise,resolve 后的值为组件模块对象\n * 组件必须使用默认导出(export default)\n */\nexport type ComponentImport = () => Promise<any>;\n\n/**\n * 路由配置项\n * \n * 与 RouteItem 的区别:\n * - layout、page、loading、error/errors 可以是组件路径字符串(如 \"@/pages/index.ts\")或动态导入函数\n * - 如果使用字符串,系统会自动转换为动态导入函数\n * - 如果使用函数,则直接使用,无需转换\n * - 对应的组件必须默认导出(export default xxxx)\n */\nexport interface RouteConfig {\n /**\n * 布局组件路径(字符串)或动态导入函数\n * \n * 字符串示例: \"@/pages/layout.tsx\" 或 \"../../pages/layout.tsx\"\n * 函数示例: () => import(\"@/pages/layout.tsx\")\n * 组件必须默认导出\n */\n layout?: string | ComponentImport | null;\n\n /**\n * 页面组件路径(字符串)或动态导入函数\n * \n * 字符串示例: \"@/pages/index.tsx\" 或 \"../../pages/index.tsx\"\n * 函数示例: () => import(\"@/pages/index.tsx\")\n * 组件必须默认导出\n */\n page?: string | ComponentImport | null;\n\n /**\n * 加载组件路径(字符串)或动态导入函数\n * \n * 字符串示例: \"@/components/Loading.tsx\"\n * 函数示例: () => import(\"@/components/Loading.tsx\")\n * 组件必须默认导出\n */\n loading?: string | ComponentImport | null;\n\n /**\n * 错误组件路径(字符串)或动态导入函数\n * \n * 字符串示例: \"@/pages/error.tsx\"\n * 函数示例: () => import(\"@/pages/error.tsx\")\n * 组件必须默认导出\n */\n errors?: string | ComponentImport | null;\n\n /**\n * 错误组件路径(字符串)或动态导入函数(兼容字段,优先级高于 errors)\n *\n * 字符串示例: \"@/pages/error.tsx\"\n * 函数示例: () => import(\"@/pages/error.tsx\")\n * 组件必须默认导出\n */\n error?: string | ComponentImport | null;\n\n /**\n * 路由名称(唯一标识)\n */\n name: string;\n\n /**\n * 路由路径\n */\n path: string | undefined;\n\n /**\n * 是否为路由组\n */\n isGroup?: boolean;\n\n /**\n * 是否启用重定向\n */\n enableRedirection?: boolean;\n\n /**\n * 路由元数据\n */\n handle: {\n title: string;\n i18nKey?: string;\n order: number;\n icon?: string;\n hideInMenu?: boolean;\n hideFooter?: boolean;\n keepAlive?: boolean;\n needLogin?: boolean;\n roles?: Array<string>;\n name?: string;\n [key: string]: unknown;\n };\n\n /**\n * 子路由配置\n */\n children?: RouteConfig[];\n}\n\n/**\n * 路由位置信息\n */\nexport interface RouteLocation {\n /**\n * 路径\n */\n path: string;\n\n /**\n * 路径参数\n */\n params?: Record<string, unknown>;\n\n /**\n * 查询参数\n */\n query?: Record<string, unknown>;\n\n /**\n * 路由元数据\n */\n meta?: RouteMeta;\n}\n\n/**\n * 导航选项\n */\nexport interface NavigateOptions {\n /**\n * 是否替换当前历史记录\n */\n replace?: boolean;\n\n /**\n * 状态数据\n */\n state?: unknown;\n\n /**\n * 查询参数\n */\n query?: Record<string, unknown>;\n}\n\n/**\n * 路由生命周期钩子\n */\nexport interface RouteLifecycleHooks {\n /**\n * 路由跳转前钩子\n * \n * @param to - 目标路由\n * @param from - 来源路由\n * @returns 如果返回字符串,则跳转到该路径;如果返回 false,则阻止跳转;返回 true 或 undefined 则继续跳转\n */\n beforeEach?: (to: RouteLocation, from?: RouteLocation) => string | false | void | Promise<string | false | void>;\n\n /**\n * 路由跳转后钩子\n * \n * @param to - 目标路由\n * @param from - 来源路由\n */\n afterEach?: (to: RouteLocation, from?: RouteLocation) => void | Promise<void>;\n}\n\n/**\n * 路由模式\n * \n * 对应 react-router-dom 的路由模式:\n * - `browser`: 使用 BrowserRouter(createBrowserRouter)\n * - `hash`: 使用 HashRouter(createHashRouter)\n * - `memory`: 使用 MemoryRouter(createMemoryRouter)\n */\nexport type RouterMode = 'browser' | 'hash' | 'memory';\n\n/**\n * 应用路由接口\n * \n * 这是框架核心依赖的抽象接口,所有路由实现都必须实现此接口\n */\nexport interface AppRouter {\n /**\n * 挂载到应用实例\n * \n * @param app - 应用实例\n */\n mount(app: AppInstance): void;\n\n /**\n * 路由跳转\n * \n * @param to - 目标路径或路由名称\n * @param options - 导航选项\n */\n navigate(to: string, options?: NavigateOptions): void;\n\n /**\n * 获取当前路由信息\n * \n * @returns 当前路由位置信息\n */\n getCurrentRoute(): RouteLocation;\n\n /**\n * 销毁路由实例(可选)\n */\n destroy?(): void;\n}\n\n/**\n * 路径解析配置\n */\nexport interface PathResolveConfig {\n /**\n * 项目根目录路径\n * \n * 用于解析相对路径的基准目录。\n * 如果不提供,将使用调用框架的项目根目录(通常为 process.cwd())。\n * \n * 注意:路径解析主要由构建工具(如 Vite、Webpack)处理,\n * 此配置主要用于文档和错误提示。\n * \n * @example\n * ```typescript\n * router: {\n * pathResolve: {\n * basePath: '/path/to/project',\n * },\n * }\n * ```\n */\n basePath?: string;\n\n /**\n * 路径别名映射\n * \n * 用于将路径别名(如 @/)映射到实际路径。\n * 如果不提供,将使用构建工具的配置(如 vite.config.ts 中的 resolve.alias)。\n * \n * 注意:路径别名解析主要由构建工具处理,\n * 此配置主要用于文档和错误提示。\n * \n * @example\n * ```typescript\n * router: {\n * pathResolve: {\n * pathAliases: {\n * '@': './src',\n * '@components': './src/components',\n * },\n * },\n * }\n * ```\n */\n pathAliases?: Record<string, string>;\n}\n\n/**\n * 路由配置选项\n */\nexport interface RouterConfig {\n /**\n * 是否启用路由\n * \n * - `true`: 启用内置路由(默认)\n * - `false`: 禁用内置路由,使用自定义路由\n * - `'disabled'`: 完全禁用路由\n * \n * @default true\n */\n enabled?: boolean | 'disabled';\n\n /**\n * 路由配置列表\n * \n * 使用 RouteConfig 类型\n * \n * 注意:RouteConfig 中的 layout、page、loading、error/errors 可以是:\n * - 组件路径字符串:系统会自动转换为动态导入函数\n * - 动态导入函数:直接使用,无需转换\n * \n * 路径字符串可以是:\n * - 相对路径:如 `\"./pages/index.tsx\"`、`\"../components/Layout.tsx\"`\n * - 路径别名:如 `\"@/pages/index.tsx\"`(需要在构建工具中配置,如 vite.config.ts)\n * - 绝对路径:如 `\"/src/pages/index.tsx\"`(不推荐)\n * \n * 动态导入函数示例:\n * - `() => import(\"./pages/index.tsx\")`\n * - `() => import(\"@/pages/index.tsx\")`\n * \n * 路径解析由构建工具(如 Vite、Webpack)处理,框架会在运行时验证组件是否有默认导出。\n */\n routes?: RouteConfig[] | (() => RouteConfig[] | Promise<RouteConfig[]>);\n\n /**\n * 路由模式\n * \n * - `browser`: 使用 BrowserRouter(createBrowserRouter)- 默认\n * - `hash`: 使用 HashRouter(createHashRouter)\n * - `memory`: 使用 MemoryRouter(createMemoryRouter)\n * \n * @default 'browser'\n */\n mode?: RouterMode;\n\n /**\n * 路由选项\n * \n * 传递给 react-router-dom 的路由创建方法的选项\n * - `browser` 和 `hash` 模式使用 `DOMRouterOpts`\n * - `memory` 模式使用 `MemoryRouterOpts`\n */\n options?: DOMRouterOpts | MemoryRouterOpts;\n\n /**\n * 路径解析配置\n * \n * 用于配置路径解析选项,主要用于文档和错误提示。\n * 实际的路径解析由构建工具(如 Vite、Webpack)处理。\n */\n pathResolve?: PathResolveConfig;\n\n /**\n * 转换选项\n * \n * 用于配置转换选项,主要用于转换路由配置。\n */\n transformOptions?: TransformOptions;\n\n /**\n * 路由预加载配置\n *\n * 默认策略为 `none`,即按需懒加载路由组件。\n * 如需预加载,可显式配置 `strategy` 为 `next-level` / `visible` / `all`。\n */\n preload?: PreloadConfig;\n\n /**\n * 路由生命周期钩子\n */\n hooks?: RouteLifecycleHooks;\n\n /**\n * 是否启用配置验证(默认 true)\n * \n * 如果为 false,将跳过路由配置的 Zod 验证\n */\n enableValidation?: boolean;\n\n /**\n * 默认路由错误组件\n * \n * 当路由配置中的 `error`/`errors` 为空时,将使用此组件作为错误边界。\n * 如果不提供,将使用框架内置的 `RouteErrorBoundary` 组件。\n * \n * 组件必须使用默认导出(export default)。\n * \n * @example\n * ```typescript\n * router: {\n * defaultRouteErrorComponent: () => import('./components/CustomErrorBoundary'),\n * routes: [\n * {\n * name: 'home',\n * path: '/',\n * page: './pages/Home',\n * // error/errors 为空时,将使用 defaultRouteErrorComponent\n * },\n * ],\n * },\n * ```\n */\n defaultRouteErrorComponent?: ComponentImport;\n\n /**\n * 默认路由加载组件\n * \n * 当路由配置中的 `loading` 为空时,将使用此组件作为加载指示器。\n * 如果不提供,将使用框架内置 Loading 组件。\n * \n * 组件必须使用默认导出(export default)。\n * \n * @example\n * ```typescript\n * router: {\n * defaultRouteLoadingComponent: () => import('./components/CustomLoading'),\n * routes: [\n * {\n * name: 'home',\n * path: '/',\n * page: './pages/Home',\n * // loading 为空时,将使用 defaultRouteLoadingComponent\n * },\n * ],\n * },\n * ```\n */\n defaultRouteLoadingComponent?: ComponentImport;\n\n /**\n * 是否为路由注入 hydrateFallbackElement\n *\n * 默认关闭。仅在 SSR hydration 场景需要时开启。\n * 若未显式配置,会根据 `options.hydrationData` 自动推断。\n *\n * @default false\n */\n enableHydrateFallback?: boolean;\n}\n"],"names":[],"mappings":"AA+XA;;CAEC,GACD,WAoJC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/core/router/utils/adapters/react-router/RouteErrorBoundary.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { FallbackProps } from 'react-error-boundary';\n\nconst isDevelopment = process.env.NODE_ENV === 'development';\n\ninterface RouteErrorLike extends Error {\n status?: number;\n statusText?: string;\n data?: unknown;\n cause?: unknown;\n}\n\nexport const RouteErrorBoundary = ({ error, resetErrorBoundary }: FallbackProps) => {\n const [showDetails, setShowDetails] = useState(false);\n const errorObject: RouteErrorLike | null =\n error !== null && typeof error === 'object' ? (error as RouteErrorLike) : null;\n const errorMessage =\n typeof errorObject?.message === 'string' && errorObject.message !== ''\n ? errorObject.message\n : '未知错误';\n const hasCause = errorObject?.cause !== undefined;\n\n const isNotFoundError =\n errorObject?.status === 404 ||\n (typeof errorObject?.statusText === 'string' && /not\\s*found/i.test(errorObject.statusText)) ||\n /no routes matched location|not found|404/i.test(errorMessage);\n\n const title = isNotFoundError ? '页面不存在(404)' : '出错了,请稍后再试';\n const friendlyMessage = isNotFoundError\n ? '访问的路由未注册或不存在,请检查访问地址。'\n : '请稍后再试或联系技术支持';\n const displayMessage = isDevelopment ? errorMessage : friendlyMessage;\n\n return (\n <div\n role=\"alert\"\n style={{\n minHeight: '100vh',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n padding: 24,\n }}\n >\n <div style={{ maxWidth: 760, width: '100%', border: '1px solid #dde5ec', borderRadius: 10, padding: 20 }}>\n <h2 style={{ marginTop: 0 }}>{title}</h2>\n <p>{displayMessage}</p>\n <div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>\n <button\n onClick={resetErrorBoundary}\n style={{ border: 'none', background: '#2f80ed', color: '#fff', borderRadius: 6, padding: '8px 12px', cursor: 'pointer' }}\n >\n 刷新重试\n </button>\n {isDevelopment && (\n <button\n onClick={() => setShowDetails(!showDetails)}\n style={{ border: '1px solid #cfd7df', background: '#fff', borderRadius: 6, padding: '8px 12px', cursor: 'pointer' }}\n >\n {showDetails ? '收起详情' : '展开详情'}\n </button>\n )}\n </div>\n\n {isDevelopment && showDetails && (\n <div style={{ background: '#f7fafc', borderRadius: 8, padding: 12, fontSize: 12, fontFamily: 'monospace' }}>\n <div style={{ marginBottom: 10 }}><strong>错误信息:</strong>{errorMessage}</div>\n {errorObject?.stack && (\n <div style={{ marginBottom: 10, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>\n <strong>堆栈:</strong>\n <br />\n {errorObject.stack}\n </div>\n )}\n {hasCause && (\n <div>\n <strong>原因:</strong>\n {errorObject?.cause instanceof Error ? errorObject.cause.message : String(errorObject?.cause)}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n"],"names":["RouteErrorBoundary","isDevelopment","process","env","NODE_ENV","error","resetErrorBoundary","showDetails","setShowDetails","useState","errorObject","errorMessage","message","hasCause","cause","undefined","isNotFoundError","status","statusText","test","title","friendlyMessage","displayMessage","div","role","style","minHeight","display","justifyContent","alignItems","padding","maxWidth","width","border","borderRadius","h2","marginTop","p","gap","marginBottom","button","onClick","background","color","cursor","fontSize","fontFamily","strong","stack","whiteSpace","wordBreak","br","Error","String"],"mappings":";;;;+BAYaA;;;eAAAA;;;;uBAZY;AAGzB,MAAMC,gBAAgBC,QAAQC,GAAG,CAACC,QAAQ,KAAK;AASxC,MAAMJ,qBAAqB,CAAC,EAAEK,KAAK,EAAEC,kBAAkB,EAAiB;IAC7E,MAAM,CAACC,aAAaC,eAAe,GAAGC,IAAAA,eAAQ,EAAC;IAC/C,MAAMC,cACJL,UAAU,QAAQ,OAAOA,UAAU,WAAYA,QAA2B;IAC5E,MAAMM,eACJ,OAAOD,aAAaE,YAAY,YAAYF,YAAYE,OAAO,KAAK,KAChEF,YAAYE,OAAO,GACnB;IACN,MAAMC,WAAWH,aAAaI,UAAUC;IAExC,MAAMC,kBACJN,aAAaO,WAAW,OACvB,OAAOP,aAAaQ,eAAe,YAAY,eAAeC,IAAI,CAACT,YAAYQ,UAAU,KAC1F,4CAA4CC,IAAI,CAACR;IAEnD,MAAMS,QAAQJ,kBAAkB,eAAe;IAC/C,MAAMK,kBAAkBL,kBACpB,0BACA;IACJ,MAAMM,iBAAiBrB,gBAAgBU,eAAeU;IAEtD,qBACE,qBAACE;QACCC,MAAK;QACLC,OAAO;YACLC,WAAW;YACXC,SAAS;YACTC,gBAAgB;YAChBC,YAAY;YACZC,SAAS;QACX;kBAEA,cAAA,sBAACP;YAAIE,OAAO;gBAAEM,UAAU;gBAAKC,OAAO;gBAAQC,QAAQ;gBAAqBC,cAAc;gBAAIJ,SAAS;YAAG;;8BACrG,qBAACK;oBAAGV,OAAO;wBAAEW,WAAW;oBAAE;8BAAIhB;;8BAC9B,qBAACiB;8BAAGf;;8BACJ,sBAACC;oBAAIE,OAAO;wBAAEE,SAAS;wBAAQW,KAAK;wBAAGC,cAAc;oBAAG;;sCACtD,qBAACC;4BACCC,SAASnC;4BACTmB,OAAO;gCAAEQ,QAAQ;gCAAQS,YAAY;gCAAWC,OAAO;gCAAQT,cAAc;gCAAGJ,SAAS;gCAAYc,QAAQ;4BAAU;sCACxH;;wBAGA3C,+BACC,qBAACuC;4BACCC,SAAS,IAAMjC,eAAe,CAACD;4BAC/BkB,OAAO;gCAAEQ,QAAQ;gCAAqBS,YAAY;gCAAQR,cAAc;gCAAGJ,SAAS;gCAAYc,QAAQ;4BAAU;sCAEjHrC,cAAc,SAAS;;;;gBAK7BN,iBAAiBM,6BAChB,sBAACgB;oBAAIE,OAAO;wBAAEiB,YAAY;wBAAWR,cAAc;wBAAGJ,SAAS;wBAAIe,UAAU;wBAAIC,YAAY;oBAAY;;sCACvG,sBAACvB;4BAAIE,OAAO;gCAAEc,cAAc;4BAAG;;8CAAG,qBAACQ;8CAAO;;gCAAepC;;;wBACxDD,aAAasC,uBACZ,sBAACzB;4BAAIE,OAAO;gCAAEc,cAAc;gCAAIU,YAAY;gCAAYC,WAAW;4BAAa;;8CAC9E,qBAACH;8CAAO;;8CACR,qBAACI;gCACAzC,YAAYsC,KAAK;;;wBAGrBnC,0BACC,sBAACU;;8CACC,qBAACwB;8CAAO;;gCACPrC,aAAaI,iBAAiBsC,QAAQ1C,YAAYI,KAAK,CAACF,OAAO,GAAGyC,OAAO3C,aAAaI;;;;;;;;AAQvG"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/core/router/utils/adapters/react-router/RouteErrorBoundary.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { FallbackProps } from 'react-error-boundary';\n\nconst isDevelopment = process.env.NODE_ENV === 'development';\n\ninterface RouteErrorLike extends Error {\n status?: number;\n statusText?: string;\n data?: unknown;\n cause?: unknown;\n}\n\nexport const RouteErrorBoundary = ({ error, resetErrorBoundary }: FallbackProps) => {\n const [showDetails, setShowDetails] = useState(false);\n const errorObject: RouteErrorLike | null =\n error !== null && typeof error === 'object' ? (error as RouteErrorLike) : null;\n const errorMessage =\n typeof errorObject?.message === 'string' && errorObject.message !== ''\n ? errorObject.message\n : '未知错误';\n const hasCause = errorObject?.cause !== undefined;\n\n const isNotFoundError =\n errorObject?.status === 404 ||\n (typeof errorObject?.statusText === 'string' && /not\\s*found/i.test(errorObject.statusText)) ||\n /no routes matched location|not found|404/i.test(errorMessage);\n\n const title = isNotFoundError ? '页面不存在(404)' : '出错了,请稍后再试';\n const friendlyMessage = isNotFoundError\n ? '访问的路由未注册或不存在,请检查访问地址。'\n : '请稍后再试或联系技术支持';\n const displayMessage = isDevelopment ? errorMessage : friendlyMessage;\n\n return (\n <div\n role=\"alert\"\n style={{\n minHeight: '100vh',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n padding: 24,\n }}\n >\n <div style={{ maxWidth: 760, width: '100%', border: '1px solid #dde5ec', borderRadius: 10, padding: 20 }}>\n <h2 style={{ marginTop: 0 }}>{title}</h2>\n <p>{displayMessage}</p>\n <div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>\n <button\n onClick={resetErrorBoundary}\n style={{ border: 'none', background: '#2f80ed', color: '#fff', borderRadius: 6, padding: '8px 12px', cursor: 'pointer' }}\n >\n 刷新重试\n </button>\n {isDevelopment && (\n <button\n onClick={() => setShowDetails(!showDetails)}\n style={{ border: '1px solid #cfd7df', background: '#fff', borderRadius: 6, padding: '8px 12px', cursor: 'pointer' }}\n >\n {showDetails ? '收起详情' : '展开详情'}\n </button>\n )}\n </div>\n\n {isDevelopment && showDetails && (\n <div style={{ background: '#f7fafc', borderRadius: 8, padding: 12, fontSize: 12, fontFamily: 'monospace' }}>\n <div style={{ marginBottom: 10 }}><strong>错误信息:</strong>{errorMessage}</div>\n {errorObject?.stack && (\n <div style={{ marginBottom: 10, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>\n <strong>堆栈:</strong>\n <br />\n {errorObject.stack}\n </div>\n )}\n {hasCause && (\n <div>\n <strong>原因:</strong>\n {errorObject?.cause instanceof Error ? errorObject.cause.message : String(errorObject?.cause)}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n"],"names":["useState","isDevelopment","process","env","NODE_ENV","RouteErrorBoundary","error","resetErrorBoundary","showDetails","setShowDetails","errorObject","errorMessage","message","hasCause","cause","undefined","isNotFoundError","status","statusText","test","title","friendlyMessage","displayMessage","div","role","style","minHeight","display","justifyContent","alignItems","padding","maxWidth","width","border","borderRadius","h2","marginTop","p","gap","marginBottom","button","onClick","background","color","cursor","fontSize","fontFamily","strong","stack","whiteSpace","wordBreak","br","Error","String"],"mappings":";AAAA,SAASA,QAAQ,QAAQ,QAAQ;AAGjC,MAAMC,gBAAgBC,QAAQC,GAAG,CAACC,QAAQ,KAAK;AAS/C,OAAO,MAAMC,qBAAqB,CAAC,EAAEC,KAAK,EAAEC,kBAAkB,EAAiB;IAC7E,MAAM,CAACC,aAAaC,eAAe,GAAGT,SAAS;IAC/C,MAAMU,cACJJ,UAAU,QAAQ,OAAOA,UAAU,WAAYA,QAA2B;IAC5E,MAAMK,eACJ,OAAOD,aAAaE,YAAY,YAAYF,YAAYE,OAAO,KAAK,KAChEF,YAAYE,OAAO,GACnB;IACN,MAAMC,WAAWH,aAAaI,UAAUC;IAExC,MAAMC,kBACJN,aAAaO,WAAW,OACvB,OAAOP,aAAaQ,eAAe,YAAY,eAAeC,IAAI,CAACT,YAAYQ,UAAU,KAC1F,4CAA4CC,IAAI,CAACR;IAEnD,MAAMS,QAAQJ,kBAAkB,eAAe;IAC/C,MAAMK,kBAAkBL,kBACpB,0BACA;IACJ,MAAMM,iBAAiBrB,gBAAgBU,eAAeU;IAEtD,qBACE,KAACE;QACCC,MAAK;QACLC,OAAO;YACLC,WAAW;YACXC,SAAS;YACTC,gBAAgB;YAChBC,YAAY;YACZC,SAAS;QACX;kBAEA,cAAA,MAACP;YAAIE,OAAO;gBAAEM,UAAU;gBAAKC,OAAO;gBAAQC,QAAQ;gBAAqBC,cAAc;gBAAIJ,SAAS;YAAG;;8BACrG,KAACK;oBAAGV,OAAO;wBAAEW,WAAW;oBAAE;8BAAIhB;;8BAC9B,KAACiB;8BAAGf;;8BACJ,MAACC;oBAAIE,OAAO;wBAAEE,SAAS;wBAAQW,KAAK;wBAAGC,cAAc;oBAAG;;sCACtD,KAACC;4BACCC,SAASlC;4BACTkB,OAAO;gCAAEQ,QAAQ;gCAAQS,YAAY;gCAAWC,OAAO;gCAAQT,cAAc;gCAAGJ,SAAS;gCAAYc,QAAQ;4BAAU;sCACxH;;wBAGA3C,+BACC,KAACuC;4BACCC,SAAS,IAAMhC,eAAe,CAACD;4BAC/BiB,OAAO;gCAAEQ,QAAQ;gCAAqBS,YAAY;gCAAQR,cAAc;gCAAGJ,SAAS;gCAAYc,QAAQ;4BAAU;sCAEjHpC,cAAc,SAAS;;;;gBAK7BP,iBAAiBO,6BAChB,MAACe;oBAAIE,OAAO;wBAAEiB,YAAY;wBAAWR,cAAc;wBAAGJ,SAAS;wBAAIe,UAAU;wBAAIC,YAAY;oBAAY;;sCACvG,MAACvB;4BAAIE,OAAO;gCAAEc,cAAc;4BAAG;;8CAAG,KAACQ;8CAAO;;gCAAepC;;;wBACxDD,aAAasC,uBACZ,MAACzB;4BAAIE,OAAO;gCAAEc,cAAc;gCAAIU,YAAY;gCAAYC,WAAW;4BAAa;;8CAC9E,KAACH;8CAAO;;8CACR,KAACI;gCACAzC,YAAYsC,KAAK;;;wBAGrBnC,0BACC,MAACU;;8CACC,KAACwB;8CAAO;;gCACPrC,aAAaI,iBAAiBsC,QAAQ1C,YAAYI,KAAK,CAACF,OAAO,GAAGyC,OAAO3C,aAAaI;;;;;;;;AAQvG,EAAE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/core/router/utils/adapters/react-router/transform.tsx"],"sourcesContent":["import type { RouteConfig } from '../../../types';\nimport {\n type RouteObject,\n Navigate\n} from 'react-router-dom';\nimport type { TransformRoutesResult } from '../../transform';\nimport { RouteErrorBoundary } from './RouteErrorBoundary';\nimport type { ComponentImport } from '../../../types';\nimport { logger } from '@vlian/logger';\n\nfunction DefaultRouteHydrateFallback() {\n return (\n <div style={{ padding: 16, textAlign: 'center', color: '#5f6c7b' }}>\n Loading...\n </div>\n );\n}\n\nexport const transformRoutesToReactRoutes = async (\n routes: RouteConfig[],\n transformResult: TransformRoutesResult,\n defaultRouteErrorComponent?: ComponentImport,\n defaultRouteLoadingComponent?: ComponentImport,\n enableHydrateFallback: boolean = false,\n): Promise<RouteObject[]> => {\n\n /**\n * 批量处理路由\n * @param routes 路由组\n */\n function transformRouteToReactRoutes(routes: RouteConfig[]) {\n return routes.flatMap((route: RouteConfig) => transformRouteToReactRoute(route))\n }\n\n /**\n * 处理单个路由\n * @param route 路由\n */\n function transformRouteToReactRoute(route: RouteConfig): RouteObject {\n const {\n isGroup = false,\n enableRedirection = false,\n name,\n path,\n handle,\n children,\n page,\n layout,\n error,\n errors,\n loading,\n } = route;\n const routeError = error ?? errors;\n\n // 获取错误组件\n async function getErrorComponent() {\n // 如果 error/errors 是函数,直接使用\n if (typeof routeError === 'function') {\n return routeError();\n }\n\n const errorsMap = transformResult.errors;\n\n // 判断 error/errors 是否为 string 且不是空字符串\n if (typeof routeError === 'string' && routeError !== '') {\n // 使用 routeError 作为 key 获取 transformResult.errors 的值\n const errorResolver = errorsMap.get(routeError);\n\n // 如果获取不到,返回 null\n if (!errorResolver) {\n return null;\n }\n\n // 如果获取到,返回对应的值(调用动态导入函数)\n if (typeof errorResolver === 'function') {\n return errorResolver();\n }\n\n return null;\n }\n\n // 如果 errors 为空,使用配置的默认错误组件或内置的 RouteErrorBoundary 组件\n if (defaultRouteErrorComponent) {\n // 如果配置了默认错误组件,使用配置的组件\n return defaultRouteErrorComponent();\n }\n\n // 如果没有配置默认错误组件,使用内置的 RouteErrorBoundary 组件\n // 直接导入而非懒加载,因为:\n // 1. RouteErrorBoundary 是框架核心组件,体积小\n // 2. 错误边界需要快速响应,直接导入速度更快\n // 3. 作为基础设施组件,应该保证可用性\n return { default: RouteErrorBoundary };\n }\n\n // 获取转换配置\n function convertConfig(m: any) {\n if (!m) {\n return null;\n }\n const { action, loader, shouldRevalidate, default: Component } = m;\n\n // 如果 Component 不存在,记录警告\n if (!Component) {\n logger.warn(`路由组件未找到 default 导出: ${name}`, m);\n }\n\n return {\n action, // always use action\n loader, // always use loader\n shouldRevalidate,\n Component\n };\n }\n\n // 获取加载组件\n async function getLoadingComponent() {\n if (typeof loading === 'function') {\n return loading();\n }\n\n if (typeof loading === 'string' && loading !== '') {\n const loadingResolver = transformResult.loadings.get(loading);\n if (typeof loadingResolver === 'function') {\n return loadingResolver();\n }\n }\n\n if (defaultRouteLoadingComponent) {\n return defaultRouteLoadingComponent();\n }\n\n return null;\n }\n\n // 获取配置\n async function getConfig(index: boolean = false) {\n // 如果有layout和不是index,返回布局配置\n if (layout && !index) {\n // 如果 layout 是函数,直接使用\n if (typeof layout === 'function') {\n const config = await layout();\n return convertConfig(config);\n }\n\n // 如果 layout 是字符串,从 Map 中获取\n if (typeof layout === 'string') {\n const layoutResolver = transformResult.layouts.get(layout);\n if (!layoutResolver) {\n throw new Error(`未找到名为 ${layout} 的布局组件`);\n }\n const config = await layoutResolver();\n return convertConfig(config);\n }\n }\n\n let pageName = name;\n\n // 如果是notFound则转成404\n if (pageName === 'notFound') {\n pageName = '404'\n }\n\n if (page && (!children?.length || index)) {\n // 如果 page 是函数,直接使用\n if (typeof page === 'function') {\n const config = await page();\n return convertConfig(config);\n }\n\n // 如果 page 是字符串,从 Map 中获取\n if (typeof page === 'string') {\n const viewResolver = transformResult.pages.get(page);\n if (!viewResolver) {\n throw new Error(`未找到名为 ${page} 的页面组件`);\n }\n const config = await viewResolver();\n return convertConfig(config);\n }\n }\n\n return null;\n }\n\n // 获取处理信息,即额外的配置信息\n function getHandle(index: boolean = false) {\n if ((layout || isGroup) && !index) {\n return null\n }\n return {\n ...handle,\n name,\n path\n }\n }\n\n\n const reactRoute: RouteObject = {\n children: [],\n id: name,\n handle: getHandle(),\n lazy: async () => {\n const ErrorBoundary = await getErrorComponent();\n const config = await getConfig();\n const LoadingComponent = await getLoadingComponent();\n const HydrateFallback = LoadingComponent?.default ?? DefaultRouteHydrateFallback;\n\n // 如果配置为空,确保至少返回一个空对象,避免展开 undefined\n if (!config) {\n return {\n ErrorBoundary: ErrorBoundary?.default,\n HydrateFallback,\n };\n }\n\n return {\n ErrorBoundary: ErrorBoundary?.default,\n HydrateFallback,\n ...config\n };\n },\n path\n };\n\n if (enableHydrateFallback) {\n reactRoute.hydrateFallbackElement = <DefaultRouteHydrateFallback />;\n }\n\n // 处理子路由\n if (children?.length) {\n reactRoute.children = children.flatMap(child => transformRouteToReactRoute(child)).sort((a, b) => {\n const orderA = a.handle?.order ?? 99;\n const orderB = b.handle?.order ?? 99;\n return orderA - orderB;\n });\n\n if (page && !isGroup) {\n reactRoute.children.unshift({\n handle: getHandle(true),\n index: true,\n lazy: async () => {\n const ErrorBoundary = await getErrorComponent();\n const LoadingComponent = await getLoadingComponent();\n const HydrateFallback = LoadingComponent?.default ?? DefaultRouteHydrateFallback;\n const Component = page;\n return {\n ErrorBoundary: ErrorBoundary?.default,\n HydrateFallback,\n Component,\n ...(await getConfig(true))\n };\n }\n });\n }\n\n if (enableRedirection && isGroup) {\n const [firstChild] = reactRoute.children;\n if (firstChild?.path) {\n reactRoute.children.unshift({\n index: true,\n handle: getHandle(true),\n element: <Navigate to={firstChild.path as string} replace />\n });\n }\n }\n\n }\n // 若存在 layout 且没有子路由,但同时声明了 page,则自动生成 index 子路由以渲染页面\n // 场景:/test 使用自定义 layout,且没有 children 时仍应渲染 page\n if ((!children || children.length === 0) && layout && page && !isGroup) {\n reactRoute.children = [{\n handle: getHandle(true),\n index: true,\n lazy: async () => {\n const ErrorBoundary = await getErrorComponent();\n const LoadingComponent = await getLoadingComponent();\n const HydrateFallback = LoadingComponent?.default ?? DefaultRouteHydrateFallback;\n const Component = page;\n return {\n ErrorBoundary: ErrorBoundary?.default,\n HydrateFallback,\n Component,\n ...(await getConfig(true))\n };\n }\n }];\n }\n\n return reactRoute;\n }\n\n return transformRouteToReactRoutes(routes);\n}\n"],"names":["transformRoutesToReactRoutes","DefaultRouteHydrateFallback","div","style","padding","textAlign","color","routes","transformResult","defaultRouteErrorComponent","defaultRouteLoadingComponent","enableHydrateFallback","transformRouteToReactRoutes","flatMap","route","transformRouteToReactRoute","isGroup","enableRedirection","name","path","handle","children","page","layout","error","errors","loading","routeError","getErrorComponent","errorsMap","errorResolver","get","default","RouteErrorBoundary","convertConfig","m","action","loader","shouldRevalidate","Component","logger","warn","getLoadingComponent","loadingResolver","loadings","getConfig","index","config","layoutResolver","layouts","Error","pageName","length","viewResolver","pages","getHandle","reactRoute","id","lazy","ErrorBoundary","LoadingComponent","HydrateFallback","hydrateFallbackElement","child","sort","a","b","orderA","order","orderB","unshift","firstChild","element","Navigate","to","replace"],"mappings":"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"}
|