@vlian/framework 1.2.1 → 1.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analytics/index.cjs +24 -0
- package/dist/analytics/index.cjs.map +1 -0
- package/dist/analytics/index.d.ts +2 -0
- package/dist/analytics/index.js +3 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics.umd.js +2406 -0
- package/dist/analytics.umd.js.map +1 -0
- package/dist/components/LocaleSwitch.cjs +118 -0
- package/dist/components/LocaleSwitch.cjs.map +1 -0
- package/dist/components/LocaleSwitch.d.ts +21 -0
- package/dist/components/LocaleSwitch.js +103 -0
- package/dist/components/LocaleSwitch.js.map +1 -0
- package/dist/components/ThemeSwitch.cjs +117 -0
- package/dist/components/ThemeSwitch.cjs.map +1 -0
- package/dist/components/ThemeSwitch.d.ts +20 -0
- package/dist/components/ThemeSwitch.js +102 -0
- package/dist/components/ThemeSwitch.js.map +1 -0
- package/dist/components/index.cjs +16 -0
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.d.ts +5 -2
- package/dist/components/index.js +2 -1
- package/dist/components/index.js.map +1 -1
- package/dist/components/persistence.cjs +60 -0
- package/dist/components/persistence.cjs.map +1 -0
- package/dist/components/persistence.d.ts +12 -0
- package/dist/components/persistence.js +39 -0
- package/dist/components/persistence.js.map +1 -0
- package/dist/core/Test.d.ts +0 -1
- package/dist/core/app/AppContext.cjs +36 -30
- package/dist/core/app/AppContext.cjs.map +1 -1
- package/dist/core/app/AppContext.d.ts +9 -6
- package/dist/core/app/AppContext.js +36 -30
- package/dist/core/app/AppContext.js.map +1 -1
- package/dist/core/app/AppContext.types.d.ts +9 -10
- package/dist/core/app/AppContext.types.js.map +1 -1
- package/dist/core/app/BasicLayout.cjs +57 -22
- package/dist/core/app/BasicLayout.cjs.map +1 -1
- package/dist/core/app/BasicLayout.d.ts +7 -5
- package/dist/core/app/BasicLayout.js +57 -22
- package/dist/core/app/BasicLayout.js.map +1 -1
- package/dist/core/app/DefaultApp.cjs +104 -153
- package/dist/core/app/DefaultApp.cjs.map +1 -1
- package/dist/core/app/DefaultApp.d.ts +0 -21
- package/dist/core/app/DefaultApp.js +104 -153
- package/dist/core/app/DefaultApp.js.map +1 -1
- package/dist/core/app/index.d.ts +0 -1
- package/dist/core/config/AppConfig.cjs.map +1 -1
- package/dist/core/config/AppConfig.d.ts +3 -4
- package/dist/core/config/AppConfig.js.map +1 -1
- package/dist/core/config/ConfigLoader.d.ts +0 -1
- package/dist/core/config/ConfigValidator.d.ts +0 -1
- package/dist/core/config/index.d.ts +0 -1
- package/dist/core/dev/DevTools.cjs +141 -287
- package/dist/core/dev/DevTools.cjs.map +1 -1
- package/dist/core/dev/DevTools.d.ts +1 -32
- package/dist/core/dev/DevTools.js +143 -296
- package/dist/core/dev/DevTools.js.map +1 -1
- package/dist/core/error/ErrorBoundary.cjs +72 -14
- package/dist/core/error/ErrorBoundary.cjs.map +1 -1
- package/dist/core/error/ErrorBoundary.d.ts +7 -9
- package/dist/core/error/ErrorBoundary.js +73 -15
- package/dist/core/error/ErrorBoundary.js.map +1 -1
- package/dist/core/error/ErrorHandler.d.ts +0 -1
- package/dist/core/error/index.d.ts +0 -1
- package/dist/core/event/AppEventBus.d.ts +0 -1
- package/dist/core/event/frameworkEvents.d.ts +0 -1
- package/dist/core/event/hooks.d.ts +0 -1
- package/dist/core/event/index.d.ts +0 -1
- package/dist/core/event/types.d.ts +0 -1
- package/dist/core/event/useEventBus.d.ts +0 -1
- package/dist/core/index.cjs +2 -0
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.js +2 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/initialization/InitializationErrorThrower.d.ts +0 -1
- package/dist/core/initialization/index.d.ts +0 -1
- package/dist/core/initialization/initialization.d.ts +0 -1
- package/dist/core/initialization/initializationErrorState.d.ts +0 -1
- package/dist/core/kernel/defaultAdapters.cjs +185 -0
- package/dist/core/kernel/defaultAdapters.cjs.map +1 -0
- package/dist/core/kernel/defaultAdapters.d.ts +2 -0
- package/dist/core/kernel/defaultAdapters.js +175 -0
- package/dist/core/kernel/defaultAdapters.js.map +1 -0
- package/dist/core/kernel/errors.cjs +71 -0
- package/dist/core/kernel/errors.cjs.map +1 -0
- package/dist/core/kernel/errors.d.ts +18 -0
- package/dist/core/kernel/errors.js +53 -0
- package/dist/core/kernel/errors.js.map +1 -0
- package/dist/core/kernel/index.cjs +22 -0
- package/dist/core/kernel/index.cjs.map +1 -0
- package/dist/core/kernel/index.d.ts +3 -0
- package/dist/core/kernel/index.js +4 -0
- package/dist/core/kernel/index.js.map +1 -0
- package/dist/core/kernel/startKernel.cjs +203 -0
- package/dist/core/kernel/startKernel.cjs.map +1 -0
- package/dist/core/kernel/startKernel.d.ts +2 -0
- package/dist/core/kernel/startKernel.js +193 -0
- package/dist/core/kernel/startKernel.js.map +1 -0
- package/dist/core/kernel/types.cjs +6 -0
- package/dist/core/kernel/types.cjs.map +1 -0
- package/dist/core/kernel/types.d.ts +114 -0
- package/dist/core/kernel/types.js +3 -0
- package/dist/core/kernel/types.js.map +1 -0
- package/dist/core/middleware.d.ts +0 -1
- package/dist/core/plugin/PluginEventBus.d.ts +0 -1
- package/dist/core/plugin/PluginSandbox.d.ts +0 -1
- package/dist/core/plugin.cjs +1 -1
- package/dist/core/plugin.cjs.map +1 -1
- package/dist/core/plugin.d.ts +0 -1
- package/dist/core/plugin.js +1 -1
- package/dist/core/plugin.js.map +1 -1
- package/dist/core/router/RouterManager.cjs +32 -2
- package/dist/core/router/RouterManager.cjs.map +1 -1
- package/dist/core/router/RouterManager.d.ts +5 -1
- package/dist/core/router/RouterManager.js +33 -3
- package/dist/core/router/RouterManager.js.map +1 -1
- package/dist/core/router/adapter/AdapterManager.d.ts +0 -1
- package/dist/core/router/adapter/index.d.ts +0 -1
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.cjs.map +1 -1
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.d.ts +0 -1
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.js.map +1 -1
- package/dist/core/router/adapter/react-router/index.d.ts +0 -1
- package/dist/core/router/adapter/types.cjs.map +1 -1
- package/dist/core/router/adapter/types.d.ts +1 -2
- package/dist/core/router/adapter/types.js.map +1 -1
- package/dist/core/router/dev/RouterDevTools.cjs +148 -296
- package/dist/core/router/dev/RouterDevTools.cjs.map +1 -1
- package/dist/core/router/dev/RouterDevTools.d.ts +1 -6
- package/dist/core/router/dev/RouterDevTools.js +149 -301
- package/dist/core/router/dev/RouterDevTools.js.map +1 -1
- package/dist/core/router/dev/index.d.ts +0 -1
- package/dist/core/router/dynamic/DynamicRouteManager.d.ts +0 -1
- package/dist/core/router/dynamic/index.d.ts +0 -1
- package/dist/core/router/errors/RouterError.d.ts +0 -1
- package/dist/core/router/errors/index.d.ts +0 -1
- package/dist/core/router/index.d.ts +0 -1
- package/dist/core/router/lifecycle/RouterLifecycleManager.d.ts +0 -1
- package/dist/core/router/lifecycle/index.d.ts +0 -1
- package/dist/core/router/middleware/RouterMiddlewareManager.cjs +24 -4
- package/dist/core/router/middleware/RouterMiddlewareManager.cjs.map +1 -1
- package/dist/core/router/middleware/RouterMiddlewareManager.d.ts +1 -1
- package/dist/core/router/middleware/RouterMiddlewareManager.js +24 -4
- package/dist/core/router/middleware/RouterMiddlewareManager.js.map +1 -1
- package/dist/core/router/middleware/auth.d.ts +0 -1
- package/dist/core/router/middleware/index.d.ts +0 -1
- package/dist/core/router/middleware/types.cjs.map +1 -1
- package/dist/core/router/middleware/types.d.ts +1 -2
- package/dist/core/router/middleware/types.js.map +1 -1
- package/dist/core/router/monitoring/RouterMonitoring.d.ts +0 -1
- package/dist/core/router/monitoring/index.d.ts +0 -1
- package/dist/core/router/navigation/RouterNavigation.cjs +69 -14
- package/dist/core/router/navigation/RouterNavigation.cjs.map +1 -1
- package/dist/core/router/navigation/RouterNavigation.d.ts +3 -1
- package/dist/core/router/navigation/RouterNavigation.js +69 -14
- package/dist/core/router/navigation/RouterNavigation.js.map +1 -1
- package/dist/core/router/navigation/index.d.ts +0 -1
- package/dist/core/router/performance/RouteCache.cjs +34 -13
- package/dist/core/router/performance/RouteCache.cjs.map +1 -1
- package/dist/core/router/performance/RouteCache.d.ts +8 -3
- package/dist/core/router/performance/RouteCache.js +34 -13
- package/dist/core/router/performance/RouteCache.js.map +1 -1
- package/dist/core/router/performance/RoutePreloader.cjs +89 -22
- package/dist/core/router/performance/RoutePreloader.cjs.map +1 -1
- package/dist/core/router/performance/RoutePreloader.d.ts +9 -2
- package/dist/core/router/performance/RoutePreloader.js +89 -22
- package/dist/core/router/performance/RoutePreloader.js.map +1 -1
- package/dist/core/router/performance/index.d.ts +0 -1
- package/dist/core/router/plugin/RouterPluginManager.d.ts +0 -1
- package/dist/core/router/plugin/index.d.ts +0 -1
- package/dist/core/router/plugin/types.d.ts +0 -1
- package/dist/core/router/types.d.ts +23 -7
- package/dist/core/router/types.js.map +1 -1
- package/dist/core/router/utils/adapters/react-router/RouteErrorBoundary.cjs +90 -103
- package/dist/core/router/utils/adapters/react-router/RouteErrorBoundary.cjs.map +1 -1
- package/dist/core/router/utils/adapters/react-router/RouteErrorBoundary.d.ts +0 -1
- package/dist/core/router/utils/adapters/react-router/RouteErrorBoundary.js +91 -104
- package/dist/core/router/utils/adapters/react-router/RouteErrorBoundary.js.map +1 -1
- package/dist/core/router/utils/adapters/react-router/transform.cjs +45 -63
- package/dist/core/router/utils/adapters/react-router/transform.cjs.map +1 -1
- package/dist/core/router/utils/adapters/react-router/transform.d.ts +0 -1
- package/dist/core/router/utils/adapters/react-router/transform.js +46 -59
- package/dist/core/router/utils/adapters/react-router/transform.js.map +1 -1
- package/dist/core/router/utils/transform.cjs +80 -71
- package/dist/core/router/utils/transform.cjs.map +1 -1
- package/dist/core/router/utils/transform.d.ts +1 -2
- package/dist/core/router/utils/transform.js +81 -72
- package/dist/core/router/utils/transform.js.map +1 -1
- package/dist/core/router/validation/RouterConfigValidator.d.ts +66 -5
- package/dist/core/router/validation/index.d.ts +0 -1
- package/dist/core/router/validation/schema.cjs +71 -2
- package/dist/core/router/validation/schema.cjs.map +1 -1
- package/dist/core/router/validation/schema.d.ts +102 -7
- package/dist/core/router/validation/schema.js +71 -2
- package/dist/core/router/validation/schema.js.map +1 -1
- package/dist/core/router/version/RouteVersionManager.d.ts +0 -1
- package/dist/core/router/version/index.d.ts +0 -1
- package/dist/core/splash/SplashScreen.cjs +101 -15
- package/dist/core/splash/SplashScreen.cjs.map +1 -1
- package/dist/core/splash/SplashScreen.d.ts +0 -1
- package/dist/core/splash/SplashScreen.js +101 -15
- package/dist/core/splash/SplashScreen.js.map +1 -1
- package/dist/core/splash/index.d.ts +0 -1
- package/dist/core/splash/splashScreenUtils.d.ts +0 -1
- package/dist/core/startup/AppInstance.d.ts +0 -1
- package/dist/core/startup/environment.d.ts +0 -1
- package/dist/core/startup/index.d.ts +0 -1
- package/dist/core/startup/initializeServices.d.ts +0 -1
- package/dist/core/startup/performanceTracker.d.ts +0 -1
- package/dist/core/startup/renderApp.cjs +12 -10
- package/dist/core/startup/renderApp.cjs.map +1 -1
- package/dist/core/startup/renderApp.d.ts +0 -1
- package/dist/core/startup/renderApp.js +12 -10
- package/dist/core/startup/renderApp.js.map +1 -1
- package/dist/core/startup/startApp.cjs +118 -13
- package/dist/core/startup/startApp.cjs.map +1 -1
- package/dist/core/startup/startApp.d.ts +0 -1
- package/dist/core/startup/startApp.js +118 -13
- package/dist/core/startup/startApp.js.map +1 -1
- package/dist/core/types.d.ts +34 -21
- package/dist/core/types.js.map +1 -1
- package/dist/core/ui-adapter/adapters.cjs +45 -0
- package/dist/core/ui-adapter/adapters.cjs.map +1 -0
- package/dist/core/ui-adapter/adapters.d.ts +4 -0
- package/dist/core/ui-adapter/adapters.js +27 -0
- package/dist/core/ui-adapter/adapters.js.map +1 -0
- package/dist/core/ui-adapter/index.cjs +21 -0
- package/dist/core/ui-adapter/index.cjs.map +1 -0
- package/dist/core/ui-adapter/index.d.ts +2 -0
- package/dist/core/ui-adapter/index.js +3 -0
- package/dist/core/ui-adapter/index.js.map +1 -0
- package/dist/core/ui-adapter/types.cjs +6 -0
- package/dist/core/ui-adapter/types.cjs.map +1 -0
- package/dist/core/ui-adapter/types.d.ts +24 -0
- package/dist/core/ui-adapter/types.js +3 -0
- package/dist/core/ui-adapter/types.js.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/index.umd.d.ts +0 -1
- package/dist/index.umd.js +7684 -6056
- package/dist/index.umd.js.map +1 -1
- package/dist/library/index.d.ts +0 -1
- package/dist/library/locale/index.d.ts +0 -1
- package/dist/library/locale/langs/en-us/index.d.ts +0 -1
- package/dist/library/locale/langs/zh-cn/index.d.ts +0 -1
- package/dist/library/locale/types.d.ts +0 -1
- package/dist/library/storage/cache.d.ts +0 -1
- package/dist/library/storage/encryption.d.ts +0 -1
- package/dist/library/storage/index.d.ts +0 -1
- package/dist/request/adapter/RequestAdapter.d.ts +0 -1
- package/dist/request/adapter/axiosAdapter.d.ts +0 -1
- package/dist/request/adapter/fetchAdapter.d.ts +0 -1
- package/dist/request/adapter/index.d.ts +0 -1
- package/dist/request/adapter/kyAdapter.d.ts +0 -1
- package/dist/request/adapter/undiciAdapter.d.ts +0 -1
- package/dist/request/core/RequestClient.d.ts +0 -1
- package/dist/request/core/index.d.ts +0 -1
- package/dist/request/index.d.ts +0 -1
- package/dist/request/plugin/RequestPlugin.d.ts +0 -1
- package/dist/request/plugin/cache.d.ts +0 -1
- package/dist/request/plugin/csrfPlugin.d.ts +0 -1
- package/dist/request/plugin/index.d.ts +0 -1
- package/dist/request/plugin/monitoring.d.ts +0 -1
- package/dist/request/plugin/queue.d.ts +0 -1
- package/dist/request/plugin/retry.d.ts +0 -1
- package/dist/request/plugin/validation.d.ts +0 -1
- package/dist/request/runtime/RequestContext.d.ts +0 -1
- package/dist/request/runtime/index.d.ts +0 -1
- package/dist/request/types.d.ts +0 -1
- package/dist/request/utils/RequestQueueManager.d.ts +0 -1
- package/dist/request/utils/dependencyCheck.d.ts +0 -1
- package/dist/request/utils/index.d.ts +0 -1
- package/dist/request.umd.js +5392 -0
- package/dist/request.umd.js.map +1 -0
- package/dist/state/StateManager.d.ts +0 -1
- package/dist/state/adapters/AdapterFactory.d.ts +0 -1
- package/dist/state/adapters/DefaultAdapter.d.ts +0 -1
- package/dist/state/adapters/ReduxAdapter.d.ts +0 -1
- package/dist/state/adapters/ZustandAdapter.d.ts +0 -1
- package/dist/state/adapters/index.d.ts +0 -1
- package/dist/state/adapters/types.d.ts +0 -1
- package/dist/state/core/DerivedStateInstance.d.ts +0 -1
- package/dist/state/core/StateInstance.d.ts +0 -1
- package/dist/state/core/StateRegistry.d.ts +0 -1
- package/dist/state/core/StateScope.d.ts +0 -1
- package/dist/state/core/index.d.ts +0 -1
- package/dist/state/index.d.ts +0 -1
- package/dist/state/types.d.ts +0 -1
- package/dist/state.umd.js +1414 -0
- package/dist/state.umd.js.map +1 -0
- package/dist/types.d.ts +0 -1
- package/dist/utils/analytics.d.ts +0 -1
- package/dist/utils/configSecurity.d.ts +0 -1
- package/dist/utils/csrf.d.ts +0 -1
- package/dist/utils/errors/ErrorCodes.d.ts +0 -1
- package/dist/utils/errors.cjs +44 -1
- package/dist/utils/errors.cjs.map +1 -1
- package/dist/utils/errors.d.ts +5 -1
- package/dist/utils/errors.js +44 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/logger.d.ts +0 -1
- package/dist/utils/logger.types.d.ts +0 -1
- package/dist/utils/monitoring.d.ts +0 -1
- package/dist/utils/performance.d.ts +0 -1
- package/dist/utils/resourceLoader.d.ts +0 -1
- package/dist/utils/runtimeSecurity.d.ts +0 -1
- package/dist/utils/security.d.ts +0 -1
- package/dist/utils/traceId.d.ts +0 -1
- package/dist/utils/validation.d.ts +0 -1
- package/package.json +24 -9
- package/dist/components/index.d.ts.map +0 -1
- package/dist/core/Test.d.ts.map +0 -1
- package/dist/core/app/AppContext.d.ts.map +0 -1
- package/dist/core/app/AppContext.types.d.ts.map +0 -1
- package/dist/core/app/BasicLayout.d.ts.map +0 -1
- package/dist/core/app/DefaultApp.d.ts.map +0 -1
- package/dist/core/app/index.d.ts.map +0 -1
- package/dist/core/config/AppConfig.d.ts.map +0 -1
- package/dist/core/config/ConfigLoader.d.ts.map +0 -1
- package/dist/core/config/ConfigValidator.d.ts.map +0 -1
- package/dist/core/config/index.d.ts.map +0 -1
- package/dist/core/dev/DevTools.d.ts.map +0 -1
- package/dist/core/error/ErrorBoundary.d.ts.map +0 -1
- package/dist/core/error/ErrorHandler.d.ts.map +0 -1
- package/dist/core/error/index.d.ts.map +0 -1
- package/dist/core/event/AppEventBus.d.ts.map +0 -1
- package/dist/core/event/frameworkEvents.d.ts.map +0 -1
- package/dist/core/event/hooks.d.ts.map +0 -1
- package/dist/core/event/index.d.ts.map +0 -1
- package/dist/core/event/types.d.ts.map +0 -1
- package/dist/core/event/useEventBus.d.ts.map +0 -1
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/initialization/InitializationErrorThrower.d.ts.map +0 -1
- package/dist/core/initialization/index.d.ts.map +0 -1
- package/dist/core/initialization/initialization.d.ts.map +0 -1
- package/dist/core/initialization/initializationErrorState.d.ts.map +0 -1
- package/dist/core/middleware.d.ts.map +0 -1
- package/dist/core/plugin/PluginEventBus.d.ts.map +0 -1
- package/dist/core/plugin/PluginSandbox.d.ts.map +0 -1
- package/dist/core/plugin.d.ts.map +0 -1
- package/dist/core/router/RouterManager.d.ts.map +0 -1
- package/dist/core/router/adapter/AdapterManager.d.ts.map +0 -1
- package/dist/core/router/adapter/index.d.ts.map +0 -1
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.d.ts.map +0 -1
- package/dist/core/router/adapter/react-router/index.d.ts.map +0 -1
- package/dist/core/router/adapter/types.d.ts.map +0 -1
- package/dist/core/router/dev/RouterDevTools.d.ts.map +0 -1
- package/dist/core/router/dev/index.d.ts.map +0 -1
- package/dist/core/router/dynamic/DynamicRouteManager.d.ts.map +0 -1
- package/dist/core/router/dynamic/index.d.ts.map +0 -1
- package/dist/core/router/errors/RouterError.d.ts.map +0 -1
- package/dist/core/router/errors/index.d.ts.map +0 -1
- package/dist/core/router/index.d.ts.map +0 -1
- package/dist/core/router/lifecycle/RouterLifecycleManager.d.ts.map +0 -1
- package/dist/core/router/lifecycle/index.d.ts.map +0 -1
- package/dist/core/router/middleware/RouterMiddlewareManager.d.ts.map +0 -1
- package/dist/core/router/middleware/auth.d.ts.map +0 -1
- package/dist/core/router/middleware/index.d.ts.map +0 -1
- package/dist/core/router/middleware/types.d.ts.map +0 -1
- package/dist/core/router/monitoring/RouterMonitoring.d.ts.map +0 -1
- package/dist/core/router/monitoring/index.d.ts.map +0 -1
- package/dist/core/router/navigation/RouterNavigation.d.ts.map +0 -1
- package/dist/core/router/navigation/index.d.ts.map +0 -1
- package/dist/core/router/performance/RouteCache.d.ts.map +0 -1
- package/dist/core/router/performance/RoutePreloader.d.ts.map +0 -1
- package/dist/core/router/performance/index.d.ts.map +0 -1
- package/dist/core/router/plugin/RouterPluginManager.d.ts.map +0 -1
- package/dist/core/router/plugin/index.d.ts.map +0 -1
- package/dist/core/router/plugin/types.d.ts.map +0 -1
- package/dist/core/router/types.d.ts.map +0 -1
- package/dist/core/router/utils/adapters/react-router/RouteErrorBoundary.d.ts.map +0 -1
- package/dist/core/router/utils/adapters/react-router/transform.d.ts.map +0 -1
- package/dist/core/router/utils/transform.d.ts.map +0 -1
- package/dist/core/router/validation/RouterConfigValidator.d.ts.map +0 -1
- package/dist/core/router/validation/index.d.ts.map +0 -1
- package/dist/core/router/validation/schema.d.ts.map +0 -1
- package/dist/core/router/version/RouteVersionManager.d.ts.map +0 -1
- package/dist/core/router/version/index.d.ts.map +0 -1
- package/dist/core/splash/SplashScreen.d.ts.map +0 -1
- package/dist/core/splash/index.d.ts.map +0 -1
- package/dist/core/splash/splashScreenUtils.d.ts.map +0 -1
- package/dist/core/startup/AppInstance.d.ts.map +0 -1
- package/dist/core/startup/environment.d.ts.map +0 -1
- package/dist/core/startup/index.d.ts.map +0 -1
- package/dist/core/startup/initializeServices.d.ts.map +0 -1
- package/dist/core/startup/performanceTracker.d.ts.map +0 -1
- package/dist/core/startup/renderApp.d.ts.map +0 -1
- package/dist/core/startup/startApp.d.ts.map +0 -1
- package/dist/core/types.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.umd.d.ts.map +0 -1
- package/dist/library/index.d.ts.map +0 -1
- package/dist/library/locale/index.d.ts.map +0 -1
- package/dist/library/locale/langs/en-us/index.d.ts.map +0 -1
- package/dist/library/locale/langs/zh-cn/index.d.ts.map +0 -1
- package/dist/library/locale/types.d.ts.map +0 -1
- package/dist/library/storage/cache.d.ts.map +0 -1
- package/dist/library/storage/encryption.d.ts.map +0 -1
- package/dist/library/storage/index.d.ts.map +0 -1
- package/dist/request/adapter/RequestAdapter.d.ts.map +0 -1
- package/dist/request/adapter/axiosAdapter.d.ts.map +0 -1
- package/dist/request/adapter/fetchAdapter.d.ts.map +0 -1
- package/dist/request/adapter/index.d.ts.map +0 -1
- package/dist/request/adapter/kyAdapter.d.ts.map +0 -1
- package/dist/request/adapter/undiciAdapter.d.ts.map +0 -1
- package/dist/request/core/RequestClient.d.ts.map +0 -1
- package/dist/request/core/index.d.ts.map +0 -1
- package/dist/request/index.d.ts.map +0 -1
- package/dist/request/plugin/RequestPlugin.d.ts.map +0 -1
- package/dist/request/plugin/cache.d.ts.map +0 -1
- package/dist/request/plugin/csrfPlugin.d.ts.map +0 -1
- package/dist/request/plugin/index.d.ts.map +0 -1
- package/dist/request/plugin/monitoring.d.ts.map +0 -1
- package/dist/request/plugin/queue.d.ts.map +0 -1
- package/dist/request/plugin/retry.d.ts.map +0 -1
- package/dist/request/plugin/validation.d.ts.map +0 -1
- package/dist/request/runtime/RequestContext.d.ts.map +0 -1
- package/dist/request/runtime/index.d.ts.map +0 -1
- package/dist/request/types.d.ts.map +0 -1
- package/dist/request/utils/RequestQueueManager.d.ts.map +0 -1
- package/dist/request/utils/dependencyCheck.d.ts.map +0 -1
- package/dist/request/utils/index.d.ts.map +0 -1
- package/dist/state/StateManager.d.ts.map +0 -1
- package/dist/state/adapters/AdapterFactory.d.ts.map +0 -1
- package/dist/state/adapters/DefaultAdapter.d.ts.map +0 -1
- package/dist/state/adapters/ReduxAdapter.d.ts.map +0 -1
- package/dist/state/adapters/ZustandAdapter.d.ts.map +0 -1
- package/dist/state/adapters/index.d.ts.map +0 -1
- package/dist/state/adapters/types.d.ts.map +0 -1
- package/dist/state/core/DerivedStateInstance.d.ts.map +0 -1
- package/dist/state/core/StateInstance.d.ts.map +0 -1
- package/dist/state/core/StateRegistry.d.ts.map +0 -1
- package/dist/state/core/StateScope.d.ts.map +0 -1
- package/dist/state/core/index.d.ts.map +0 -1
- package/dist/state/index.d.ts.map +0 -1
- package/dist/state/types.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/utils/analytics.d.ts.map +0 -1
- package/dist/utils/configSecurity.d.ts.map +0 -1
- package/dist/utils/csrf.d.ts.map +0 -1
- package/dist/utils/errors/ErrorCodes.d.ts.map +0 -1
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.types.d.ts.map +0 -1
- package/dist/utils/monitoring.d.ts.map +0 -1
- package/dist/utils/performance.d.ts.map +0 -1
- package/dist/utils/resourceLoader.d.ts.map +0 -1
- package/dist/utils/runtimeSecurity.d.ts.map +0 -1
- package/dist/utils/security.d.ts.map +0 -1
- package/dist/utils/traceId.d.ts.map +0 -1
- package/dist/utils/validation.d.ts.map +0 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React, { useEffect, useState, useRef, memo, useCallback } from "react";
|
|
3
|
-
import { Spin, Progress } from "antd";
|
|
4
3
|
import { logger } from "../../utils";
|
|
5
4
|
import { initialization, initializationErrorState } from "../initialization";
|
|
6
5
|
/**
|
|
@@ -12,6 +11,12 @@ import { initialization, initializationErrorState } from "../initialization";
|
|
|
12
11
|
const [currentStep, setCurrentStep] = useState('准备初始化...');
|
|
13
12
|
const [isInitializing, setIsInitializing] = useState(false);
|
|
14
13
|
const [estimatedTime, setEstimatedTime] = useState(null);
|
|
14
|
+
const [isSystemDark, setIsSystemDark] = useState(()=>{
|
|
15
|
+
if (typeof window === 'undefined') {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
19
|
+
});
|
|
15
20
|
const hasCompletedRef = useRef(false);
|
|
16
21
|
const onCompleteRef = useRef(onComplete);
|
|
17
22
|
const optionsRef = useRef(options);
|
|
@@ -131,6 +136,51 @@ import { initialization, initializationErrorState } from "../initialization";
|
|
|
131
136
|
}, [
|
|
132
137
|
debouncedProgressUpdate
|
|
133
138
|
]);
|
|
139
|
+
useEffect(()=>{
|
|
140
|
+
if (typeof window === 'undefined') {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
|
144
|
+
const onSystemThemeChange = (event)=>{
|
|
145
|
+
setIsSystemDark(event.matches);
|
|
146
|
+
};
|
|
147
|
+
setIsSystemDark(mediaQuery.matches);
|
|
148
|
+
if (typeof mediaQuery.addEventListener === 'function') {
|
|
149
|
+
mediaQuery.addEventListener('change', onSystemThemeChange);
|
|
150
|
+
return ()=>mediaQuery.removeEventListener('change', onSystemThemeChange);
|
|
151
|
+
}
|
|
152
|
+
mediaQuery.addListener(onSystemThemeChange);
|
|
153
|
+
return ()=>mediaQuery.removeListener(onSystemThemeChange);
|
|
154
|
+
}, []);
|
|
155
|
+
const resolvedMode = React.useMemo(()=>{
|
|
156
|
+
const mode = optionsRef.current.theme?.mode || 'light';
|
|
157
|
+
if (mode === 'system') {
|
|
158
|
+
return isSystemDark ? 'dark' : 'light';
|
|
159
|
+
}
|
|
160
|
+
return mode === 'dark' ? 'dark' : 'light';
|
|
161
|
+
}, [
|
|
162
|
+
isSystemDark
|
|
163
|
+
]);
|
|
164
|
+
const palette = React.useMemo(()=>{
|
|
165
|
+
if (resolvedMode === 'dark') {
|
|
166
|
+
return {
|
|
167
|
+
background: '#0b1220',
|
|
168
|
+
text: '#e2e8f0',
|
|
169
|
+
subText: '#94a3b8',
|
|
170
|
+
track: '#1f2937',
|
|
171
|
+
spinnerTrack: '#334155'
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
background: '#f5f7fb',
|
|
176
|
+
text: '#51606f',
|
|
177
|
+
subText: '#94a3b8',
|
|
178
|
+
track: '#e9eff5',
|
|
179
|
+
spinnerTrack: '#d9e2ec'
|
|
180
|
+
};
|
|
181
|
+
}, [
|
|
182
|
+
resolvedMode
|
|
183
|
+
]);
|
|
134
184
|
// 如果提供了自定义启动屏组件,使用自定义组件
|
|
135
185
|
const CustomSplashScreen = optionsRef.current.splashScreen;
|
|
136
186
|
if (CustomSplashScreen) {
|
|
@@ -155,31 +205,64 @@ import { initialization, initializationErrorState } from "../initialization";
|
|
|
155
205
|
justifyContent: 'center',
|
|
156
206
|
height: '100vh',
|
|
157
207
|
width: '100%',
|
|
158
|
-
gap: 24
|
|
208
|
+
gap: 24,
|
|
209
|
+
background: palette.background,
|
|
210
|
+
color: palette.text
|
|
159
211
|
},
|
|
160
212
|
children: [
|
|
161
|
-
/*#__PURE__*/ _jsx(Spin, {
|
|
162
|
-
size: "large",
|
|
163
|
-
spinning: isInitializing,
|
|
164
|
-
"aria-label": "加载中"
|
|
165
|
-
}),
|
|
166
213
|
/*#__PURE__*/ _jsx("div", {
|
|
214
|
+
"aria-label": "加载中",
|
|
215
|
+
style: {
|
|
216
|
+
width: 42,
|
|
217
|
+
height: 42,
|
|
218
|
+
border: `4px solid ${palette.spinnerTrack}`,
|
|
219
|
+
borderTopColor: 'var(--app-primary-color, #2f80ed)',
|
|
220
|
+
borderRadius: '50%',
|
|
221
|
+
animation: 'secra-spin 1s linear infinite'
|
|
222
|
+
}
|
|
223
|
+
}),
|
|
224
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
167
225
|
style: {
|
|
168
226
|
width: '300px'
|
|
169
227
|
},
|
|
170
|
-
children:
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
228
|
+
children: [
|
|
229
|
+
/*#__PURE__*/ _jsx("div", {
|
|
230
|
+
"aria-label": `加载进度 ${progress}%`,
|
|
231
|
+
style: {
|
|
232
|
+
height: 12,
|
|
233
|
+
background: palette.track,
|
|
234
|
+
borderRadius: 999,
|
|
235
|
+
overflow: 'hidden'
|
|
236
|
+
},
|
|
237
|
+
children: /*#__PURE__*/ _jsx("div", {
|
|
238
|
+
style: {
|
|
239
|
+
width: `${Math.max(0, Math.min(100, progress))}%`,
|
|
240
|
+
height: '100%',
|
|
241
|
+
background: 'var(--app-primary-color, #2f80ed)',
|
|
242
|
+
transition: 'width 0.2s ease'
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
}),
|
|
246
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
247
|
+
style: {
|
|
248
|
+
marginTop: 8,
|
|
249
|
+
textAlign: 'right',
|
|
250
|
+
fontSize: 12,
|
|
251
|
+
color: palette.text
|
|
252
|
+
},
|
|
253
|
+
children: [
|
|
254
|
+
progress,
|
|
255
|
+
"%"
|
|
256
|
+
]
|
|
257
|
+
})
|
|
258
|
+
]
|
|
176
259
|
}),
|
|
177
260
|
/*#__PURE__*/ _jsxs("div", {
|
|
178
261
|
role: "status",
|
|
179
262
|
"aria-live": "polite",
|
|
180
263
|
style: {
|
|
181
264
|
fontSize: 14,
|
|
182
|
-
color:
|
|
265
|
+
color: palette.text,
|
|
183
266
|
textAlign: 'center'
|
|
184
267
|
},
|
|
185
268
|
children: [
|
|
@@ -187,7 +270,7 @@ import { initialization, initializationErrorState } from "../initialization";
|
|
|
187
270
|
estimatedTime !== null && estimatedTime > 0 && /*#__PURE__*/ _jsxs("div", {
|
|
188
271
|
style: {
|
|
189
272
|
fontSize: 12,
|
|
190
|
-
color:
|
|
273
|
+
color: palette.subText,
|
|
191
274
|
marginTop: 8
|
|
192
275
|
},
|
|
193
276
|
children: [
|
|
@@ -197,6 +280,9 @@ import { initialization, initializationErrorState } from "../initialization";
|
|
|
197
280
|
]
|
|
198
281
|
})
|
|
199
282
|
]
|
|
283
|
+
}),
|
|
284
|
+
/*#__PURE__*/ _jsx("style", {
|
|
285
|
+
children: `@keyframes secra-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }`
|
|
200
286
|
})
|
|
201
287
|
]
|
|
202
288
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/splash/SplashScreen.tsx"],"sourcesContent":["import React, { useEffect, useState, useRef, memo, useCallback } from 'react';\nimport { Spin, Progress } from 'antd';\nimport { logger } from '../../utils';\nimport { initialization, initializationErrorState } from '../initialization';\nimport type { StartOptions, SplashScreenCustomProps } from '../types';\nimport type { InitializationContext } from '../initialization';\n\ninterface SplashScreenProps {\n options: StartOptions;\n onComplete: (context: InitializationContext) => void;\n}\n\n/**\n * 启动页组件\n * \n * 在启动页中执行初始化,并使用 Ant Design 5 的 Spin 和 Progress 组件展示启动进度\n */\nconst SplashScreen: React.FC<SplashScreenProps> = memo(({ options, onComplete }) => {\n const [progress, setProgress] = useState(0);\n const [currentStep, setCurrentStep] = useState<string>('准备初始化...');\n const [isInitializing, setIsInitializing] = useState(false);\n const [estimatedTime, setEstimatedTime] = useState<number | null>(null);\n const hasCompletedRef = useRef(false);\n const onCompleteRef = useRef(onComplete);\n const optionsRef = useRef(options);\n const startTimeRef = useRef<number>(Date.now());\n const minDisplayTimeRef = useRef<number>(options.minSplashScreenTime ?? 500); // 最小显示时间,默认 500ms\n const progressUpdateTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const rafRef = useRef<number | null>(null);\n const lastProgressRef = useRef(0);\n const progressHistoryRef = useRef<Array<{ progress: number; time: number }>>([]);\n\n // 保持引用最新\n useEffect(() => {\n onCompleteRef.current = onComplete;\n optionsRef.current = options;\n minDisplayTimeRef.current = options.minSplashScreenTime ?? 500;\n }, [onComplete, options]);\n\n // 自适应防抖进度更新函数(使用 requestAnimationFrame 优化)\n const debouncedProgressUpdate = useCallback((progressValue: number, step?: string) => {\n // 取消之前的更新\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n }\n\n // 记录进度历史用于时间预估\n const now = Date.now();\n progressHistoryRef.current.push({ progress: progressValue, time: now });\n // 只保留最近10个记录\n if (progressHistoryRef.current.length > 10) {\n progressHistoryRef.current.shift();\n }\n\n // 计算预估时间\n if (progressHistoryRef.current.length >= 2 && progressValue > 0) {\n const history = progressHistoryRef.current;\n const first = history[0]!;\n const last = history[history.length - 1]!;\n const progressDelta = last.progress - first.progress;\n const timeDelta = last.time - first.time;\n\n if (progressDelta > 0 && timeDelta > 0) {\n const progressPerMs = progressDelta / timeDelta;\n const remainingProgress = 100 - progressValue;\n const estimatedMs = remainingProgress / progressPerMs;\n setEstimatedTime(Math.max(0, Math.round(estimatedMs)));\n }\n }\n\n // 使用 requestAnimationFrame 优化更新\n rafRef.current = requestAnimationFrame(() => {\n setProgress(progressValue);\n if (step) {\n setCurrentStep(step);\n }\n lastProgressRef.current = progressValue;\n rafRef.current = null;\n });\n }, []);\n\n useEffect(() => {\n if (hasCompletedRef.current) return;\n hasCompletedRef.current = true;\n startTimeRef.current = Date.now();\n\n const performInitialization = async () => {\n try {\n setIsInitializing(true);\n setProgress(0);\n setCurrentStep('开始初始化...');\n\n logger.info('启动页开始执行初始化');\n\n // 执行初始化,传入防抖的进度回调\n const context = await initialization(optionsRef.current, (progressValue, step) => {\n debouncedProgressUpdate(progressValue, step);\n });\n\n logger.info('启动页初始化完成', context);\n\n // 动态调整最小显示时间(如果初始化很快,减少最小显示时间)\n const elapsedTime = Date.now() - startTimeRef.current;\n const dynamicMinTime = elapsedTime < 200 ? Math.min(minDisplayTimeRef.current, 300) : minDisplayTimeRef.current;\n const remainingTime = Math.max(0, dynamicMinTime - elapsedTime);\n\n if (remainingTime > 0) {\n await new Promise((resolve) => setTimeout(resolve, remainingTime));\n }\n\n // 清理防抖定时器\n if (progressUpdateTimerRef.current) {\n clearTimeout(progressUpdateTimerRef.current);\n progressUpdateTimerRef.current = null;\n }\n\n // 确保进度条显示 100%\n setProgress(100);\n setCurrentStep('初始化完成');\n\n // 初始化完成,调用回调\n onCompleteRef.current(context);\n } catch (error) {\n logger.error('启动页初始化失败:', error);\n // 设置错误状态,让 ErrorBoundary 能够捕获\n initializationErrorState.setError(error);\n setCurrentStep('初始化失败,请刷新页面重试');\n // 即使失败也调用 onComplete,让应用能够处理错误\n onCompleteRef.current({\n config: {},\n progress: 0,\n isReady: false,\n duration: 0,\n });\n } finally {\n setIsInitializing(false);\n }\n };\n\n performInitialization();\n\n // 清理函数\n return () => {\n if (progressUpdateTimerRef.current) {\n clearTimeout(progressUpdateTimerRef.current);\n }\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n }\n };\n }, [debouncedProgressUpdate]);\n\n // 如果提供了自定义启动屏组件,使用自定义组件\n const CustomSplashScreen = optionsRef.current.splashScreen;\n if (CustomSplashScreen) {\n const customProps: SplashScreenCustomProps = {\n progress,\n currentStep,\n isInitializing,\n };\n return <CustomSplashScreen {...customProps} />;\n }\n\n // 默认启动屏 UI\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n aria-label=\"应用正在加载\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100vh',\n width: '100%',\n gap: 24,\n }}\n >\n <Spin size=\"large\" spinning={isInitializing} aria-label=\"加载中\" />\n <div style={{ width: '300px' }}>\n <Progress\n percent={progress}\n status={isInitializing ? 'active' : 'success'}\n showInfo\n aria-label={`加载进度 ${progress}%`}\n />\n </div>\n <div\n role=\"status\"\n aria-live=\"polite\"\n style={{\n fontSize: 14,\n color: '#666',\n textAlign: 'center',\n }}\n >\n {currentStep}\n {estimatedTime !== null && estimatedTime > 0 && (\n <div style={{ fontSize: 12, color: '#999', marginTop: 8 }}>\n 预计还需 {Math.ceil(estimatedTime / 1000)} 秒\n </div>\n )}\n </div>\n </div>\n );\n});\n\nSplashScreen.displayName = 'SplashScreen';\n\nexport { SplashScreen };"],"names":["React","useEffect","useState","useRef","memo","useCallback","Spin","Progress","logger","initialization","initializationErrorState","SplashScreen","options","onComplete","progress","setProgress","currentStep","setCurrentStep","isInitializing","setIsInitializing","estimatedTime","setEstimatedTime","hasCompletedRef","onCompleteRef","optionsRef","startTimeRef","Date","now","minDisplayTimeRef","minSplashScreenTime","progressUpdateTimerRef","rafRef","lastProgressRef","progressHistoryRef","current","debouncedProgressUpdate","progressValue","step","cancelAnimationFrame","push","time","length","shift","history","first","last","progressDelta","timeDelta","progressPerMs","remainingProgress","estimatedMs","Math","max","round","requestAnimationFrame","performInitialization","info","context","elapsedTime","dynamicMinTime","min","remainingTime","Promise","resolve","setTimeout","clearTimeout","error","setError","config","isReady","duration","CustomSplashScreen","splashScreen","customProps","div","role","aria-live","aria-label","style","display","flexDirection","alignItems","justifyContent","height","width","gap","size","spinning","percent","status","showInfo","fontSize","color","textAlign","marginTop","ceil","displayName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/core/splash/SplashScreen.tsx"],"sourcesContent":["import React, { useEffect, useState, useRef, memo, useCallback } from 'react';\nimport { logger } from '../../utils';\nimport { initialization, initializationErrorState } from '../initialization';\nimport type { StartOptions, SplashScreenCustomProps } from '../types';\nimport type { InitializationContext } from '../initialization';\n\ninterface SplashScreenProps {\n options: StartOptions;\n onComplete: (context: InitializationContext) => void;\n}\n\n/**\n * 启动页组件\n * \n * 在启动页中执行初始化,并使用 Ant Design 5 的 Spin 和 Progress 组件展示启动进度\n */\nconst SplashScreen: React.FC<SplashScreenProps> = memo(({ options, onComplete }) => {\n const [progress, setProgress] = useState(0);\n const [currentStep, setCurrentStep] = useState<string>('准备初始化...');\n const [isInitializing, setIsInitializing] = useState(false);\n const [estimatedTime, setEstimatedTime] = useState<number | null>(null);\n const [isSystemDark, setIsSystemDark] = useState<boolean>(() => {\n if (typeof window === 'undefined') {\n return false;\n }\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n });\n const hasCompletedRef = useRef(false);\n const onCompleteRef = useRef(onComplete);\n const optionsRef = useRef(options);\n const startTimeRef = useRef<number>(Date.now());\n const minDisplayTimeRef = useRef<number>(options.minSplashScreenTime ?? 500); // 最小显示时间,默认 500ms\n const progressUpdateTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const rafRef = useRef<number | null>(null);\n const lastProgressRef = useRef(0);\n const progressHistoryRef = useRef<Array<{ progress: number; time: number }>>([]);\n\n // 保持引用最新\n useEffect(() => {\n onCompleteRef.current = onComplete;\n optionsRef.current = options;\n minDisplayTimeRef.current = options.minSplashScreenTime ?? 500;\n }, [onComplete, options]);\n\n // 自适应防抖进度更新函数(使用 requestAnimationFrame 优化)\n const debouncedProgressUpdate = useCallback((progressValue: number, step?: string) => {\n // 取消之前的更新\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n }\n\n // 记录进度历史用于时间预估\n const now = Date.now();\n progressHistoryRef.current.push({ progress: progressValue, time: now });\n // 只保留最近10个记录\n if (progressHistoryRef.current.length > 10) {\n progressHistoryRef.current.shift();\n }\n\n // 计算预估时间\n if (progressHistoryRef.current.length >= 2 && progressValue > 0) {\n const history = progressHistoryRef.current;\n const first = history[0]!;\n const last = history[history.length - 1]!;\n const progressDelta = last.progress - first.progress;\n const timeDelta = last.time - first.time;\n\n if (progressDelta > 0 && timeDelta > 0) {\n const progressPerMs = progressDelta / timeDelta;\n const remainingProgress = 100 - progressValue;\n const estimatedMs = remainingProgress / progressPerMs;\n setEstimatedTime(Math.max(0, Math.round(estimatedMs)));\n }\n }\n\n // 使用 requestAnimationFrame 优化更新\n rafRef.current = requestAnimationFrame(() => {\n setProgress(progressValue);\n if (step) {\n setCurrentStep(step);\n }\n lastProgressRef.current = progressValue;\n rafRef.current = null;\n });\n }, []);\n\n useEffect(() => {\n if (hasCompletedRef.current) return;\n hasCompletedRef.current = true;\n startTimeRef.current = Date.now();\n\n const performInitialization = async () => {\n try {\n setIsInitializing(true);\n setProgress(0);\n setCurrentStep('开始初始化...');\n\n logger.info('启动页开始执行初始化');\n\n // 执行初始化,传入防抖的进度回调\n const context = await initialization(optionsRef.current, (progressValue, step) => {\n debouncedProgressUpdate(progressValue, step);\n });\n\n logger.info('启动页初始化完成', context);\n\n // 动态调整最小显示时间(如果初始化很快,减少最小显示时间)\n const elapsedTime = Date.now() - startTimeRef.current;\n const dynamicMinTime = elapsedTime < 200 ? Math.min(minDisplayTimeRef.current, 300) : minDisplayTimeRef.current;\n const remainingTime = Math.max(0, dynamicMinTime - elapsedTime);\n\n if (remainingTime > 0) {\n await new Promise((resolve) => setTimeout(resolve, remainingTime));\n }\n\n // 清理防抖定时器\n if (progressUpdateTimerRef.current) {\n clearTimeout(progressUpdateTimerRef.current);\n progressUpdateTimerRef.current = null;\n }\n\n // 确保进度条显示 100%\n setProgress(100);\n setCurrentStep('初始化完成');\n\n // 初始化完成,调用回调\n onCompleteRef.current(context);\n } catch (error) {\n logger.error('启动页初始化失败:', error);\n // 设置错误状态,让 ErrorBoundary 能够捕获\n initializationErrorState.setError(error);\n setCurrentStep('初始化失败,请刷新页面重试');\n // 即使失败也调用 onComplete,让应用能够处理错误\n onCompleteRef.current({\n config: {},\n progress: 0,\n isReady: false,\n duration: 0,\n });\n } finally {\n setIsInitializing(false);\n }\n };\n\n performInitialization();\n\n // 清理函数\n return () => {\n if (progressUpdateTimerRef.current) {\n clearTimeout(progressUpdateTimerRef.current);\n }\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n }\n };\n }, [debouncedProgressUpdate]);\n\n useEffect(() => {\n if (typeof window === 'undefined') {\n return;\n }\n\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n const onSystemThemeChange = (event: MediaQueryListEvent) => {\n setIsSystemDark(event.matches);\n };\n\n setIsSystemDark(mediaQuery.matches);\n\n if (typeof mediaQuery.addEventListener === 'function') {\n mediaQuery.addEventListener('change', onSystemThemeChange);\n return () => mediaQuery.removeEventListener('change', onSystemThemeChange);\n }\n\n mediaQuery.addListener(onSystemThemeChange);\n return () => mediaQuery.removeListener(onSystemThemeChange);\n }, []);\n\n const resolvedMode = React.useMemo<'light' | 'dark'>(() => {\n const mode = optionsRef.current.theme?.mode || 'light';\n if (mode === 'system') {\n return isSystemDark ? 'dark' : 'light';\n }\n return mode === 'dark' ? 'dark' : 'light';\n }, [isSystemDark]);\n\n const palette = React.useMemo(() => {\n if (resolvedMode === 'dark') {\n return {\n background: '#0b1220',\n text: '#e2e8f0',\n subText: '#94a3b8',\n track: '#1f2937',\n spinnerTrack: '#334155',\n };\n }\n\n return {\n background: '#f5f7fb',\n text: '#51606f',\n subText: '#94a3b8',\n track: '#e9eff5',\n spinnerTrack: '#d9e2ec',\n };\n }, [resolvedMode]);\n\n // 如果提供了自定义启动屏组件,使用自定义组件\n const CustomSplashScreen = optionsRef.current.splashScreen;\n if (CustomSplashScreen) {\n const customProps: SplashScreenCustomProps = {\n progress,\n currentStep,\n isInitializing,\n };\n return <CustomSplashScreen {...customProps} />;\n }\n\n // 默认启动屏 UI\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n aria-label=\"应用正在加载\"\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100vh',\n width: '100%',\n gap: 24,\n background: palette.background,\n color: palette.text,\n }}\n >\n <div\n aria-label=\"加载中\"\n style={{\n width: 42,\n height: 42,\n border: `4px solid ${palette.spinnerTrack}`,\n borderTopColor: 'var(--app-primary-color, #2f80ed)',\n borderRadius: '50%',\n animation: 'secra-spin 1s linear infinite',\n }}\n />\n <div style={{ width: '300px' }}>\n <div\n aria-label={`加载进度 ${progress}%`}\n style={{\n height: 12,\n background: palette.track,\n borderRadius: 999,\n overflow: 'hidden',\n }}\n >\n <div\n style={{\n width: `${Math.max(0, Math.min(100, progress))}%`,\n height: '100%',\n background: 'var(--app-primary-color, #2f80ed)',\n transition: 'width 0.2s ease',\n }}\n />\n </div>\n <div style={{ marginTop: 8, textAlign: 'right', fontSize: 12, color: palette.text }}>\n {progress}%\n </div>\n </div>\n <div\n role=\"status\"\n aria-live=\"polite\"\n style={{\n fontSize: 14,\n color: palette.text,\n textAlign: 'center',\n }}\n >\n {currentStep}\n {estimatedTime !== null && estimatedTime > 0 && (\n <div style={{ fontSize: 12, color: palette.subText, marginTop: 8 }}>\n 预计还需 {Math.ceil(estimatedTime / 1000)} 秒\n </div>\n )}\n </div>\n <style>\n {`@keyframes secra-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }`}\n </style>\n </div>\n );\n});\n\nSplashScreen.displayName = 'SplashScreen';\n\nexport { SplashScreen };\n"],"names":["React","useEffect","useState","useRef","memo","useCallback","logger","initialization","initializationErrorState","SplashScreen","options","onComplete","progress","setProgress","currentStep","setCurrentStep","isInitializing","setIsInitializing","estimatedTime","setEstimatedTime","isSystemDark","setIsSystemDark","window","matchMedia","matches","hasCompletedRef","onCompleteRef","optionsRef","startTimeRef","Date","now","minDisplayTimeRef","minSplashScreenTime","progressUpdateTimerRef","rafRef","lastProgressRef","progressHistoryRef","current","debouncedProgressUpdate","progressValue","step","cancelAnimationFrame","push","time","length","shift","history","first","last","progressDelta","timeDelta","progressPerMs","remainingProgress","estimatedMs","Math","max","round","requestAnimationFrame","performInitialization","info","context","elapsedTime","dynamicMinTime","min","remainingTime","Promise","resolve","setTimeout","clearTimeout","error","setError","config","isReady","duration","mediaQuery","onSystemThemeChange","event","addEventListener","removeEventListener","addListener","removeListener","resolvedMode","useMemo","mode","theme","palette","background","text","subText","track","spinnerTrack","CustomSplashScreen","splashScreen","customProps","div","role","aria-live","aria-label","style","display","flexDirection","alignItems","justifyContent","height","width","gap","color","border","borderTopColor","borderRadius","animation","overflow","transition","marginTop","textAlign","fontSize","ceil","displayName"],"mappings":"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"}
|
|
@@ -133,11 +133,12 @@ securityConfig: _securityConfig })=>{
|
|
|
133
133
|
/*#__PURE__*/ (0, _jsxruntime.jsx)(_app.AppContextProvider, {
|
|
134
134
|
initialTheme: options.theme,
|
|
135
135
|
initialLocale: initialLocale,
|
|
136
|
-
initialAntdConfig: options.antd,
|
|
136
|
+
initialAntdConfig: options.uiProvider || options.antd,
|
|
137
137
|
initialInitializationContext: context,
|
|
138
138
|
stateManager: services.stateManager,
|
|
139
|
-
antdApp: options.antdApp,
|
|
139
|
+
antdApp: options.uiApp || options.antdApp,
|
|
140
140
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_app.BasicLayout, {
|
|
141
|
+
globalProvider: options.globalProvider,
|
|
141
142
|
children: appContent
|
|
142
143
|
})
|
|
143
144
|
})
|
|
@@ -148,7 +149,7 @@ OptimizedAppContent.displayName = 'OptimizedAppContent';
|
|
|
148
149
|
let AppRenderer = class AppRenderer {
|
|
149
150
|
/**
|
|
150
151
|
* 初始化渲染器
|
|
151
|
-
*
|
|
152
|
+
*
|
|
152
153
|
* @param container - React应用的挂载容器
|
|
153
154
|
* @param rootOptions - React根节点配置选项
|
|
154
155
|
*/ initialize(container, rootOptions) {
|
|
@@ -159,12 +160,12 @@ let AppRenderer = class AppRenderer {
|
|
|
159
160
|
}
|
|
160
161
|
/**
|
|
161
162
|
* 渲染应用
|
|
162
|
-
*
|
|
163
|
+
*
|
|
163
164
|
* 优化:
|
|
164
165
|
* 1. 默认启用安全防护(XSS防护)
|
|
165
166
|
* 2. 优化组件渲染性能,使用 useMemo 缓存计算结果
|
|
166
167
|
* 3. 将安全配置计算提取到初始化阶段
|
|
167
|
-
*
|
|
168
|
+
*
|
|
168
169
|
* @param options - 启动配置选项
|
|
169
170
|
* @param services - 服务实例
|
|
170
171
|
* @param context - 初始化上下文(可选)
|
|
@@ -226,9 +227,9 @@ let AppRenderer = class AppRenderer {
|
|
|
226
227
|
}
|
|
227
228
|
/**
|
|
228
229
|
* 渲染启动页
|
|
229
|
-
*
|
|
230
|
+
*
|
|
230
231
|
* 注意:启动页不使用 RouterWrapper,因为启动页应该在路由系统之前渲染
|
|
231
|
-
*
|
|
232
|
+
*
|
|
232
233
|
* @param options - 启动配置选项
|
|
233
234
|
* @param services - 服务实例
|
|
234
235
|
* @param onComplete - 启动页完成回调
|
|
@@ -249,10 +250,11 @@ let AppRenderer = class AppRenderer {
|
|
|
249
250
|
/*#__PURE__*/ (0, _jsxruntime.jsx)(_app.AppContextProvider, {
|
|
250
251
|
initialTheme: options.theme,
|
|
251
252
|
initialLocale: initialLocale,
|
|
252
|
-
initialAntdConfig: options.antd,
|
|
253
|
+
initialAntdConfig: options.uiProvider || options.antd,
|
|
253
254
|
stateManager: services.stateManager,
|
|
254
|
-
antdApp: options.antdApp,
|
|
255
|
+
antdApp: options.uiApp || options.antdApp,
|
|
255
256
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_app.BasicLayout, {
|
|
257
|
+
globalProvider: options.globalProvider,
|
|
256
258
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_splash.SplashScreen, {
|
|
257
259
|
options: options,
|
|
258
260
|
onComplete: onComplete
|
|
@@ -265,7 +267,7 @@ let AppRenderer = class AppRenderer {
|
|
|
265
267
|
}
|
|
266
268
|
/**
|
|
267
269
|
* 渲染错误页面
|
|
268
|
-
*
|
|
270
|
+
*
|
|
269
271
|
* @param options - 启动配置选项
|
|
270
272
|
* @param services - 服务实例
|
|
271
273
|
* @param error - 错误信息
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/startup/renderApp.tsx"],"sourcesContent":["/**\n * 应用渲染模块\n * 负责渲染React应用\n */\n\nimport { createRoot } from 'react-dom/client';\nimport type { Root } from 'react-dom/client';\nimport { StrictMode, useMemo, useCallback, memo } from 'react';\nimport type { Container, RootOptions } from 'react-dom/client';\nimport { BasicLayout, DefaultApp, AppContextProvider } from '../app';\nimport type { LangType } from '../../library/locale/types';\nimport { ErrorBoundary } from '../error';\nimport { InitializationErrorThrower } from '../initialization';\nimport type { StartOptions } from '../types';\nimport type { InitializationContext } from '../initialization';\nimport type { MonitoringService } from '../../utils/monitoring';\nimport type { StateManager } from '../../state';\nimport { SplashScreen } from '../splash';\nimport { SecurityUtils } from '../../utils/security';\nimport { getRouterManager } from '../router/RouterManager';\nimport { RouterProvider } from \"react-router-dom\";\n\n/**\n * 安全配置类型\n */\ninterface SecurityConfig {\n enableXSSProtection: boolean;\n validateConfig: boolean;\n sanitizeUserInput: boolean;\n csrf?: StartOptions['security'] extends infer S\n ? S extends { csrf?: infer C }\n ? C\n : never\n : never;\n}\n\n/**\n * 优化的应用内容组件\n * 使用 useMemo 缓存计算结果,提升渲染性能\n */\ninterface OptimizedAppContentProps {\n options: StartOptions;\n services: {\n monitoring: MonitoringService;\n stateManager: StateManager;\n };\n context?: InitializationContext;\n securityConfig: SecurityConfig;\n}\n\nconst OptimizedAppContent = memo<OptimizedAppContentProps>(({\n options,\n services,\n context,\n // securityConfig 用于未来扩展,当前暂不使用\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n securityConfig: _securityConfig,\n}) => {\n // 优化:使用 useMemo 缓存初始语言计算\n const initialLocale = useMemo<LangType>(() => {\n return options.locale\n ? (Object.keys(options.locale)[0] as LangType) || 'zh-CN'\n : 'zh-CN';\n }, [options.locale]);\n\n // 优化:使用 useMemo 缓存路由判断结果\n const shouldUseRouter = useMemo(() => {\n const routerEnabled = options.router\n ? options.router.enabled !== false && options.router.enabled !== 'disabled'\n : false;\n \n if (!routerEnabled) {\n return false;\n }\n \n const routerManager = getRouterManager();\n const router = routerManager.getRouter();\n return router !== null;\n }, [options.router]);\n\n // 优化:使用 useMemo 缓存路由实例\n const router = useMemo(() => {\n if (!shouldUseRouter) {\n return null;\n }\n const routerManager = getRouterManager();\n return routerManager.getRouter();\n }, [shouldUseRouter]);\n\n // 优化:使用 useCallback 缓存错误处理函数\n const handleError = useCallback((error: unknown) => {\n services.monitoring.captureError(error);\n }, [services.monitoring]);\n\n // 优化:使用 useMemo 缓存应用内容\n const appContent = useMemo(() => {\n if (shouldUseRouter && router) {\n return <RouterProvider router={router} />;\n }\n return options.app || <DefaultApp />;\n }, [shouldUseRouter, router, options.app]);\n\n return (\n <ErrorBoundary\n fallback={options.errorFallback}\n onError={handleError}\n >\n <InitializationErrorThrower />\n <AppContextProvider\n initialTheme={options.theme}\n initialLocale={initialLocale}\n initialAntdConfig={options.antd}\n initialInitializationContext={context}\n stateManager={services.stateManager}\n antdApp={options.antdApp}\n >\n <BasicLayout>\n {appContent}\n </BasicLayout>\n </AppContextProvider>\n </ErrorBoundary>\n );\n});\n\nOptimizedAppContent.displayName = 'OptimizedAppContent';\n\n/**\n * 应用渲染器\n */\nexport class AppRenderer {\n private root: Root | null = null;\n private container: Container | null = null;\n\n /**\n * 初始化渲染器\n * \n * @param container - React应用的挂载容器\n * @param rootOptions - React根节点配置选项\n */\n initialize(container: Container, rootOptions?: RootOptions): void {\n this.container = container;\n if (!this.root) {\n this.root = createRoot(container, rootOptions);\n }\n }\n\n /**\n * 渲染应用\n * \n * 优化:\n * 1. 默认启用安全防护(XSS防护)\n * 2. 优化组件渲染性能,使用 useMemo 缓存计算结果\n * 3. 将安全配置计算提取到初始化阶段\n * \n * @param options - 启动配置选项\n * @param services - 服务实例\n * @param context - 初始化上下文(可选)\n */\n async renderApp(\n options: StartOptions,\n services: {\n monitoring: MonitoringService;\n stateManager: StateManager;\n },\n context?: InitializationContext\n ): Promise<void> {\n if (!this.root) {\n throw new Error('渲染器未初始化,请先调用 initialize()');\n }\n\n // 优化:安全配置在初始化阶段计算(在 startApp 中预计算)\n // 这里只使用预计算的值,避免在渲染时重复计算\n const securityConfig: SecurityConfig = {\n enableXSSProtection: options.security?.enableXSSProtection ?? true,\n validateConfig: options.security?.validateConfig ?? true,\n sanitizeUserInput: options.security?.sanitizeUserInput ?? true,\n csrf: options.security?.csrf,\n };\n\n // 优化:安全验证在初始化阶段完成,这里只进行必要的运行时检查\n // 如果启用了安全模式(默认启用),对配置进行验证\n if (securityConfig.enableXSSProtection && securityConfig.validateConfig) {\n // 异步验证配置,不阻塞渲染\n Promise.resolve().then(() => {\n try {\n const configStr = JSON.stringify(options);\n const validation = SecurityUtils.validateInput(configStr);\n if (!validation.safe) {\n services.monitoring.captureError(\n new Error('配置项包含不安全内容'),\n { reason: validation.reason }\n );\n }\n } catch (error) {\n // 忽略序列化错误(某些配置项可能包含不可序列化的内容)\n }\n });\n }\n\n // 初始化 CSRF 防护(如果启用,异步执行,不阻塞渲染)\n if (securityConfig.enableXSSProtection && securityConfig.csrf?.enabled !== false) {\n import('../../utils/csrf').then(({ initCSRFManager }) => {\n initCSRFManager({\n headerName: securityConfig.csrf?.headerName,\n cookieName: securityConfig.csrf?.cookieName,\n getToken: securityConfig.csrf?.getToken,\n validateToken: securityConfig.csrf?.validateToken,\n });\n }).catch((error) => {\n // CSRF 初始化失败不影响应用启动,但记录警告\n if (process.env.NODE_ENV === 'development') {\n console.warn('CSRF 防护初始化失败:', error);\n }\n });\n }\n\n // 使用优化的应用内容组件,内部使用 useMemo 缓存计算结果\n this.root.render(\n <StrictMode>\n <OptimizedAppContent\n options={options}\n services={services}\n context={context}\n securityConfig={securityConfig}\n />\n </StrictMode>\n );\n }\n\n /**\n * 渲染启动页\n * \n * 注意:启动页不使用 RouterWrapper,因为启动页应该在路由系统之前渲染\n * \n * @param options - 启动配置选项\n * @param services - 服务实例\n * @param onComplete - 启动页完成回调\n */\n renderSplashScreen(\n options: StartOptions,\n services: {\n monitoring: MonitoringService;\n stateManager: StateManager;\n },\n onComplete: (context: InitializationContext) => void\n ): void {\n if (!this.root) {\n throw new Error('渲染器未初始化,请先调用 initialize()');\n }\n\n // 获取初始语言(从 locale 配置中推断,或使用默认值)\n const initialLocale: LangType = options.locale\n ? (Object.keys(options.locale)[0] as LangType) || 'zh-CN'\n : 'zh-CN';\n\n this.root.render(\n <StrictMode>\n <ErrorBoundary\n fallback={options.errorFallback}\n onError={(error) => {\n services.monitoring.captureError(error);\n }}\n >\n <InitializationErrorThrower />\n <AppContextProvider\n initialTheme={options.theme}\n initialLocale={initialLocale}\n initialAntdConfig={options.antd}\n stateManager={services.stateManager}\n antdApp={options.antdApp}\n >\n {/* \n 启动页不使用 RouterWrapper,因为:\n 1. 启动页应该在路由系统初始化之前渲染\n 2. 启动页完成后才会渲染主应用,此时路由系统已经初始化完成\n */}\n <BasicLayout>\n <SplashScreen options={options} onComplete={onComplete} />\n </BasicLayout>\n </AppContextProvider>\n </ErrorBoundary>\n </StrictMode>\n );\n }\n\n /**\n * 渲染错误页面\n * \n * @param options - 启动配置选项\n * @param services - 服务实例\n * @param error - 错误信息\n */\n renderError(\n options: StartOptions,\n services: {\n monitoring: MonitoringService;\n }\n ): void {\n if (!this.root) {\n throw new Error('渲染器未初始化,请先调用 initialize()');\n }\n\n this.root.render(\n <StrictMode>\n <ErrorBoundary\n fallback={options.errorFallback}\n onError={(err) => {\n services.monitoring.captureError(err);\n if (options.errorMonitor?.onError) {\n options.errorMonitor.onError(err);\n }\n }}\n >\n <InitializationErrorThrower />\n <div>框架启动失败</div>\n </ErrorBoundary>\n </StrictMode>\n );\n }\n\n /**\n * 销毁渲染器\n */\n destroy(): void {\n if (this.root) {\n this.root.unmount();\n this.root = null;\n }\n this.container = null;\n }\n\n /**\n * 获取容器\n */\n getContainer(): Container | null {\n return this.container;\n }\n}\n"],"names":["AppRenderer","OptimizedAppContent","memo","options","services","context","securityConfig","_securityConfig","initialLocale","useMemo","locale","Object","keys","shouldUseRouter","routerEnabled","router","enabled","routerManager","getRouterManager","getRouter","handleError","useCallback","error","monitoring","captureError","appContent","RouterProvider","app","DefaultApp","ErrorBoundary","fallback","errorFallback","onError","InitializationErrorThrower","AppContextProvider","initialTheme","theme","initialAntdConfig","antd","initialInitializationContext","stateManager","antdApp","BasicLayout","displayName","initialize","container","rootOptions","root","createRoot","renderApp","Error","enableXSSProtection","security","validateConfig","sanitizeUserInput","csrf","Promise","resolve","then","configStr","JSON","stringify","validation","SecurityUtils","validateInput","safe","reason","initCSRFManager","headerName","cookieName","getToken","validateToken","catch","process","env","NODE_ENV","console","warn","render","StrictMode","renderSplashScreen","onComplete","SplashScreen","renderError","err","errorMonitor","div","destroy","unmount","getContainer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/core/startup/renderApp.tsx"],"sourcesContent":["/**\n * 应用渲染模块\n * 负责渲染React应用\n */\n\nimport { createRoot } from 'react-dom/client';\nimport type { Root } from 'react-dom/client';\nimport { StrictMode, useMemo, useCallback, memo } from 'react';\nimport type { Container, RootOptions } from 'react-dom/client';\nimport { BasicLayout, DefaultApp, AppContextProvider } from '../app';\nimport type { LangType } from '../../library/locale/types';\nimport { ErrorBoundary } from '../error';\nimport { InitializationErrorThrower } from '../initialization';\nimport type { StartOptions } from '../types';\nimport type { InitializationContext } from '../initialization';\nimport type { MonitoringService } from '../../utils/monitoring';\nimport type { StateManager } from '../../state';\nimport { SplashScreen } from '../splash';\nimport { SecurityUtils } from '../../utils/security';\nimport { getRouterManager } from '../router/RouterManager';\nimport { RouterProvider } from \"react-router-dom\";\n\n/**\n * 安全配置类型\n */\ninterface SecurityConfig {\n enableXSSProtection: boolean;\n validateConfig: boolean;\n sanitizeUserInput: boolean;\n csrf?: StartOptions['security'] extends infer S\n ? S extends { csrf?: infer C }\n ? C\n : never\n : never;\n}\n\n/**\n * 优化的应用内容组件\n * 使用 useMemo 缓存计算结果,提升渲染性能\n */\ninterface OptimizedAppContentProps {\n options: StartOptions;\n services: {\n monitoring: MonitoringService;\n stateManager: StateManager;\n };\n context?: InitializationContext;\n securityConfig: SecurityConfig;\n}\n\nconst OptimizedAppContent = memo<OptimizedAppContentProps>(({\n options,\n services,\n context,\n // securityConfig 用于未来扩展,当前暂不使用\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n securityConfig: _securityConfig,\n}) => {\n // 优化:使用 useMemo 缓存初始语言计算\n const initialLocale = useMemo<LangType>(() => {\n return options.locale\n ? (Object.keys(options.locale)[0] as LangType) || 'zh-CN'\n : 'zh-CN';\n }, [options.locale]);\n\n // 优化:使用 useMemo 缓存路由判断结果\n const shouldUseRouter = useMemo(() => {\n const routerEnabled = options.router\n ? options.router.enabled !== false && options.router.enabled !== 'disabled'\n : false;\n\n if (!routerEnabled) {\n return false;\n }\n\n const routerManager = getRouterManager();\n const router = routerManager.getRouter();\n return router !== null;\n }, [options.router]);\n\n // 优化:使用 useMemo 缓存路由实例\n const router = useMemo(() => {\n if (!shouldUseRouter) {\n return null;\n }\n const routerManager = getRouterManager();\n return routerManager.getRouter();\n }, [shouldUseRouter]);\n\n // 优化:使用 useCallback 缓存错误处理函数\n const handleError = useCallback((error: unknown) => {\n services.monitoring.captureError(error);\n }, [services.monitoring]);\n\n // 优化:使用 useMemo 缓存应用内容\n const appContent = useMemo(() => {\n if (shouldUseRouter && router) {\n return <RouterProvider router={router} />;\n }\n return options.app || <DefaultApp />;\n }, [shouldUseRouter, router, options.app]);\n\n return (\n <ErrorBoundary\n fallback={options.errorFallback}\n onError={handleError}\n >\n <InitializationErrorThrower />\n <AppContextProvider\n initialTheme={options.theme}\n initialLocale={initialLocale}\n initialAntdConfig={options.uiProvider || options.antd}\n initialInitializationContext={context}\n stateManager={services.stateManager}\n antdApp={options.uiApp || options.antdApp}\n >\n <BasicLayout globalProvider={options.globalProvider}>\n {appContent}\n </BasicLayout>\n </AppContextProvider>\n </ErrorBoundary>\n );\n});\n\nOptimizedAppContent.displayName = 'OptimizedAppContent';\n\n/**\n * 应用渲染器\n */\nexport class AppRenderer {\n private root: Root | null = null;\n private container: Container | null = null;\n\n /**\n * 初始化渲染器\n *\n * @param container - React应用的挂载容器\n * @param rootOptions - React根节点配置选项\n */\n initialize(container: Container, rootOptions?: RootOptions): void {\n this.container = container;\n if (!this.root) {\n this.root = createRoot(container, rootOptions);\n }\n }\n\n /**\n * 渲染应用\n *\n * 优化:\n * 1. 默认启用安全防护(XSS防护)\n * 2. 优化组件渲染性能,使用 useMemo 缓存计算结果\n * 3. 将安全配置计算提取到初始化阶段\n *\n * @param options - 启动配置选项\n * @param services - 服务实例\n * @param context - 初始化上下文(可选)\n */\n async renderApp(\n options: StartOptions,\n services: {\n monitoring: MonitoringService;\n stateManager: StateManager;\n },\n context?: InitializationContext\n ): Promise<void> {\n if (!this.root) {\n throw new Error('渲染器未初始化,请先调用 initialize()');\n }\n\n // 优化:安全配置在初始化阶段计算(在 startApp 中预计算)\n // 这里只使用预计算的值,避免在渲染时重复计算\n const securityConfig: SecurityConfig = {\n enableXSSProtection: options.security?.enableXSSProtection ?? true,\n validateConfig: options.security?.validateConfig ?? true,\n sanitizeUserInput: options.security?.sanitizeUserInput ?? true,\n csrf: options.security?.csrf,\n };\n\n // 优化:安全验证在初始化阶段完成,这里只进行必要的运行时检查\n // 如果启用了安全模式(默认启用),对配置进行验证\n if (securityConfig.enableXSSProtection && securityConfig.validateConfig) {\n // 异步验证配置,不阻塞渲染\n Promise.resolve().then(() => {\n try {\n const configStr = JSON.stringify(options);\n const validation = SecurityUtils.validateInput(configStr);\n if (!validation.safe) {\n services.monitoring.captureError(\n new Error('配置项包含不安全内容'),\n { reason: validation.reason }\n );\n }\n } catch (error) {\n // 忽略序列化错误(某些配置项可能包含不可序列化的内容)\n }\n });\n }\n\n // 初始化 CSRF 防护(如果启用,异步执行,不阻塞渲染)\n if (securityConfig.enableXSSProtection && securityConfig.csrf?.enabled !== false) {\n import('../../utils/csrf').then(({ initCSRFManager }) => {\n initCSRFManager({\n headerName: securityConfig.csrf?.headerName,\n cookieName: securityConfig.csrf?.cookieName,\n getToken: securityConfig.csrf?.getToken,\n validateToken: securityConfig.csrf?.validateToken,\n });\n }).catch((error) => {\n // CSRF 初始化失败不影响应用启动,但记录警告\n if (process.env.NODE_ENV === 'development') {\n console.warn('CSRF 防护初始化失败:', error);\n }\n });\n }\n\n // 使用优化的应用内容组件,内部使用 useMemo 缓存计算结果\n this.root.render(\n <StrictMode>\n <OptimizedAppContent\n options={options}\n services={services}\n context={context}\n securityConfig={securityConfig}\n />\n </StrictMode>\n );\n }\n\n /**\n * 渲染启动页\n *\n * 注意:启动页不使用 RouterWrapper,因为启动页应该在路由系统之前渲染\n *\n * @param options - 启动配置选项\n * @param services - 服务实例\n * @param onComplete - 启动页完成回调\n */\n renderSplashScreen(\n options: StartOptions,\n services: {\n monitoring: MonitoringService;\n stateManager: StateManager;\n },\n onComplete: (context: InitializationContext) => void\n ): void {\n if (!this.root) {\n throw new Error('渲染器未初始化,请先调用 initialize()');\n }\n\n // 获取初始语言(从 locale 配置中推断,或使用默认值)\n const initialLocale: LangType = options.locale\n ? (Object.keys(options.locale)[0] as LangType) || 'zh-CN'\n : 'zh-CN';\n\n this.root.render(\n <StrictMode>\n <ErrorBoundary\n fallback={options.errorFallback}\n onError={(error) => {\n services.monitoring.captureError(error);\n }}\n >\n <InitializationErrorThrower />\n <AppContextProvider\n initialTheme={options.theme}\n initialLocale={initialLocale}\n initialAntdConfig={options.uiProvider || options.antd}\n stateManager={services.stateManager}\n antdApp={options.uiApp || options.antdApp}\n >\n {/*\n 启动页不使用 RouterWrapper,因为:\n 1. 启动页应该在路由系统初始化之前渲染\n 2. 启动页完成后才会渲染主应用,此时路由系统已经初始化完成\n */}\n <BasicLayout globalProvider={options.globalProvider}>\n <SplashScreen options={options} onComplete={onComplete} />\n </BasicLayout>\n </AppContextProvider>\n </ErrorBoundary>\n </StrictMode>\n );\n }\n\n /**\n * 渲染错误页面\n *\n * @param options - 启动配置选项\n * @param services - 服务实例\n * @param error - 错误信息\n */\n renderError(\n options: StartOptions,\n services: {\n monitoring: MonitoringService;\n }\n ): void {\n if (!this.root) {\n throw new Error('渲染器未初始化,请先调用 initialize()');\n }\n\n this.root.render(\n <StrictMode>\n <ErrorBoundary\n fallback={options.errorFallback}\n onError={(err) => {\n services.monitoring.captureError(err);\n if (options.errorMonitor?.onError) {\n options.errorMonitor.onError(err);\n }\n }}\n >\n <InitializationErrorThrower />\n <div>框架启动失败</div>\n </ErrorBoundary>\n </StrictMode>\n );\n }\n\n /**\n * 销毁渲染器\n */\n destroy(): void {\n if (this.root) {\n this.root.unmount();\n this.root = null;\n }\n this.container = null;\n }\n\n /**\n * 获取容器\n */\n getContainer(): Container | null {\n return this.container;\n }\n}\n"],"names":["AppRenderer","OptimizedAppContent","memo","options","services","context","securityConfig","_securityConfig","initialLocale","useMemo","locale","Object","keys","shouldUseRouter","routerEnabled","router","enabled","routerManager","getRouterManager","getRouter","handleError","useCallback","error","monitoring","captureError","appContent","RouterProvider","app","DefaultApp","ErrorBoundary","fallback","errorFallback","onError","InitializationErrorThrower","AppContextProvider","initialTheme","theme","initialAntdConfig","uiProvider","antd","initialInitializationContext","stateManager","antdApp","uiApp","BasicLayout","globalProvider","displayName","initialize","container","rootOptions","root","createRoot","renderApp","Error","enableXSSProtection","security","validateConfig","sanitizeUserInput","csrf","Promise","resolve","then","configStr","JSON","stringify","validation","SecurityUtils","validateInput","safe","reason","initCSRFManager","headerName","cookieName","getToken","validateToken","catch","process","env","NODE_ENV","console","warn","render","StrictMode","renderSplashScreen","onComplete","SplashScreen","renderError","err","errorMonitor","div","destroy","unmount","getContainer"],"mappings":"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"}
|
|
@@ -82,11 +82,12 @@ securityConfig: _securityConfig })=>{
|
|
|
82
82
|
/*#__PURE__*/ _jsx(AppContextProvider, {
|
|
83
83
|
initialTheme: options.theme,
|
|
84
84
|
initialLocale: initialLocale,
|
|
85
|
-
initialAntdConfig: options.antd,
|
|
85
|
+
initialAntdConfig: options.uiProvider || options.antd,
|
|
86
86
|
initialInitializationContext: context,
|
|
87
87
|
stateManager: services.stateManager,
|
|
88
|
-
antdApp: options.antdApp,
|
|
88
|
+
antdApp: options.uiApp || options.antdApp,
|
|
89
89
|
children: /*#__PURE__*/ _jsx(BasicLayout, {
|
|
90
|
+
globalProvider: options.globalProvider,
|
|
90
91
|
children: appContent
|
|
91
92
|
})
|
|
92
93
|
})
|
|
@@ -99,7 +100,7 @@ OptimizedAppContent.displayName = 'OptimizedAppContent';
|
|
|
99
100
|
*/ export class AppRenderer {
|
|
100
101
|
/**
|
|
101
102
|
* 初始化渲染器
|
|
102
|
-
*
|
|
103
|
+
*
|
|
103
104
|
* @param container - React应用的挂载容器
|
|
104
105
|
* @param rootOptions - React根节点配置选项
|
|
105
106
|
*/ initialize(container, rootOptions) {
|
|
@@ -110,12 +111,12 @@ OptimizedAppContent.displayName = 'OptimizedAppContent';
|
|
|
110
111
|
}
|
|
111
112
|
/**
|
|
112
113
|
* 渲染应用
|
|
113
|
-
*
|
|
114
|
+
*
|
|
114
115
|
* 优化:
|
|
115
116
|
* 1. 默认启用安全防护(XSS防护)
|
|
116
117
|
* 2. 优化组件渲染性能,使用 useMemo 缓存计算结果
|
|
117
118
|
* 3. 将安全配置计算提取到初始化阶段
|
|
118
|
-
*
|
|
119
|
+
*
|
|
119
120
|
* @param options - 启动配置选项
|
|
120
121
|
* @param services - 服务实例
|
|
121
122
|
* @param context - 初始化上下文(可选)
|
|
@@ -177,9 +178,9 @@ OptimizedAppContent.displayName = 'OptimizedAppContent';
|
|
|
177
178
|
}
|
|
178
179
|
/**
|
|
179
180
|
* 渲染启动页
|
|
180
|
-
*
|
|
181
|
+
*
|
|
181
182
|
* 注意:启动页不使用 RouterWrapper,因为启动页应该在路由系统之前渲染
|
|
182
|
-
*
|
|
183
|
+
*
|
|
183
184
|
* @param options - 启动配置选项
|
|
184
185
|
* @param services - 服务实例
|
|
185
186
|
* @param onComplete - 启动页完成回调
|
|
@@ -200,10 +201,11 @@ OptimizedAppContent.displayName = 'OptimizedAppContent';
|
|
|
200
201
|
/*#__PURE__*/ _jsx(AppContextProvider, {
|
|
201
202
|
initialTheme: options.theme,
|
|
202
203
|
initialLocale: initialLocale,
|
|
203
|
-
initialAntdConfig: options.antd,
|
|
204
|
+
initialAntdConfig: options.uiProvider || options.antd,
|
|
204
205
|
stateManager: services.stateManager,
|
|
205
|
-
antdApp: options.antdApp,
|
|
206
|
+
antdApp: options.uiApp || options.antdApp,
|
|
206
207
|
children: /*#__PURE__*/ _jsx(BasicLayout, {
|
|
208
|
+
globalProvider: options.globalProvider,
|
|
207
209
|
children: /*#__PURE__*/ _jsx(SplashScreen, {
|
|
208
210
|
options: options,
|
|
209
211
|
onComplete: onComplete
|
|
@@ -216,7 +218,7 @@ OptimizedAppContent.displayName = 'OptimizedAppContent';
|
|
|
216
218
|
}
|
|
217
219
|
/**
|
|
218
220
|
* 渲染错误页面
|
|
219
|
-
*
|
|
221
|
+
*
|
|
220
222
|
* @param options - 启动配置选项
|
|
221
223
|
* @param services - 服务实例
|
|
222
224
|
* @param error - 错误信息
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/startup/renderApp.tsx"],"sourcesContent":["/**\n * 应用渲染模块\n * 负责渲染React应用\n */\n\nimport { createRoot } from 'react-dom/client';\nimport type { Root } from 'react-dom/client';\nimport { StrictMode, useMemo, useCallback, memo } from 'react';\nimport type { Container, RootOptions } from 'react-dom/client';\nimport { BasicLayout, DefaultApp, AppContextProvider } from '../app';\nimport type { LangType } from '../../library/locale/types';\nimport { ErrorBoundary } from '../error';\nimport { InitializationErrorThrower } from '../initialization';\nimport type { StartOptions } from '../types';\nimport type { InitializationContext } from '../initialization';\nimport type { MonitoringService } from '../../utils/monitoring';\nimport type { StateManager } from '../../state';\nimport { SplashScreen } from '../splash';\nimport { SecurityUtils } from '../../utils/security';\nimport { getRouterManager } from '../router/RouterManager';\nimport { RouterProvider } from \"react-router-dom\";\n\n/**\n * 安全配置类型\n */\ninterface SecurityConfig {\n enableXSSProtection: boolean;\n validateConfig: boolean;\n sanitizeUserInput: boolean;\n csrf?: StartOptions['security'] extends infer S\n ? S extends { csrf?: infer C }\n ? C\n : never\n : never;\n}\n\n/**\n * 优化的应用内容组件\n * 使用 useMemo 缓存计算结果,提升渲染性能\n */\ninterface OptimizedAppContentProps {\n options: StartOptions;\n services: {\n monitoring: MonitoringService;\n stateManager: StateManager;\n };\n context?: InitializationContext;\n securityConfig: SecurityConfig;\n}\n\nconst OptimizedAppContent = memo<OptimizedAppContentProps>(({\n options,\n services,\n context,\n // securityConfig 用于未来扩展,当前暂不使用\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n securityConfig: _securityConfig,\n}) => {\n // 优化:使用 useMemo 缓存初始语言计算\n const initialLocale = useMemo<LangType>(() => {\n return options.locale\n ? (Object.keys(options.locale)[0] as LangType) || 'zh-CN'\n : 'zh-CN';\n }, [options.locale]);\n\n // 优化:使用 useMemo 缓存路由判断结果\n const shouldUseRouter = useMemo(() => {\n const routerEnabled = options.router\n ? options.router.enabled !== false && options.router.enabled !== 'disabled'\n : false;\n \n if (!routerEnabled) {\n return false;\n }\n \n const routerManager = getRouterManager();\n const router = routerManager.getRouter();\n return router !== null;\n }, [options.router]);\n\n // 优化:使用 useMemo 缓存路由实例\n const router = useMemo(() => {\n if (!shouldUseRouter) {\n return null;\n }\n const routerManager = getRouterManager();\n return routerManager.getRouter();\n }, [shouldUseRouter]);\n\n // 优化:使用 useCallback 缓存错误处理函数\n const handleError = useCallback((error: unknown) => {\n services.monitoring.captureError(error);\n }, [services.monitoring]);\n\n // 优化:使用 useMemo 缓存应用内容\n const appContent = useMemo(() => {\n if (shouldUseRouter && router) {\n return <RouterProvider router={router} />;\n }\n return options.app || <DefaultApp />;\n }, [shouldUseRouter, router, options.app]);\n\n return (\n <ErrorBoundary\n fallback={options.errorFallback}\n onError={handleError}\n >\n <InitializationErrorThrower />\n <AppContextProvider\n initialTheme={options.theme}\n initialLocale={initialLocale}\n initialAntdConfig={options.antd}\n initialInitializationContext={context}\n stateManager={services.stateManager}\n antdApp={options.antdApp}\n >\n <BasicLayout>\n {appContent}\n </BasicLayout>\n </AppContextProvider>\n </ErrorBoundary>\n );\n});\n\nOptimizedAppContent.displayName = 'OptimizedAppContent';\n\n/**\n * 应用渲染器\n */\nexport class AppRenderer {\n private root: Root | null = null;\n private container: Container | null = null;\n\n /**\n * 初始化渲染器\n * \n * @param container - React应用的挂载容器\n * @param rootOptions - React根节点配置选项\n */\n initialize(container: Container, rootOptions?: RootOptions): void {\n this.container = container;\n if (!this.root) {\n this.root = createRoot(container, rootOptions);\n }\n }\n\n /**\n * 渲染应用\n * \n * 优化:\n * 1. 默认启用安全防护(XSS防护)\n * 2. 优化组件渲染性能,使用 useMemo 缓存计算结果\n * 3. 将安全配置计算提取到初始化阶段\n * \n * @param options - 启动配置选项\n * @param services - 服务实例\n * @param context - 初始化上下文(可选)\n */\n async renderApp(\n options: StartOptions,\n services: {\n monitoring: MonitoringService;\n stateManager: StateManager;\n },\n context?: InitializationContext\n ): Promise<void> {\n if (!this.root) {\n throw new Error('渲染器未初始化,请先调用 initialize()');\n }\n\n // 优化:安全配置在初始化阶段计算(在 startApp 中预计算)\n // 这里只使用预计算的值,避免在渲染时重复计算\n const securityConfig: SecurityConfig = {\n enableXSSProtection: options.security?.enableXSSProtection ?? true,\n validateConfig: options.security?.validateConfig ?? true,\n sanitizeUserInput: options.security?.sanitizeUserInput ?? true,\n csrf: options.security?.csrf,\n };\n\n // 优化:安全验证在初始化阶段完成,这里只进行必要的运行时检查\n // 如果启用了安全模式(默认启用),对配置进行验证\n if (securityConfig.enableXSSProtection && securityConfig.validateConfig) {\n // 异步验证配置,不阻塞渲染\n Promise.resolve().then(() => {\n try {\n const configStr = JSON.stringify(options);\n const validation = SecurityUtils.validateInput(configStr);\n if (!validation.safe) {\n services.monitoring.captureError(\n new Error('配置项包含不安全内容'),\n { reason: validation.reason }\n );\n }\n } catch (error) {\n // 忽略序列化错误(某些配置项可能包含不可序列化的内容)\n }\n });\n }\n\n // 初始化 CSRF 防护(如果启用,异步执行,不阻塞渲染)\n if (securityConfig.enableXSSProtection && securityConfig.csrf?.enabled !== false) {\n import('../../utils/csrf').then(({ initCSRFManager }) => {\n initCSRFManager({\n headerName: securityConfig.csrf?.headerName,\n cookieName: securityConfig.csrf?.cookieName,\n getToken: securityConfig.csrf?.getToken,\n validateToken: securityConfig.csrf?.validateToken,\n });\n }).catch((error) => {\n // CSRF 初始化失败不影响应用启动,但记录警告\n if (process.env.NODE_ENV === 'development') {\n console.warn('CSRF 防护初始化失败:', error);\n }\n });\n }\n\n // 使用优化的应用内容组件,内部使用 useMemo 缓存计算结果\n this.root.render(\n <StrictMode>\n <OptimizedAppContent\n options={options}\n services={services}\n context={context}\n securityConfig={securityConfig}\n />\n </StrictMode>\n );\n }\n\n /**\n * 渲染启动页\n * \n * 注意:启动页不使用 RouterWrapper,因为启动页应该在路由系统之前渲染\n * \n * @param options - 启动配置选项\n * @param services - 服务实例\n * @param onComplete - 启动页完成回调\n */\n renderSplashScreen(\n options: StartOptions,\n services: {\n monitoring: MonitoringService;\n stateManager: StateManager;\n },\n onComplete: (context: InitializationContext) => void\n ): void {\n if (!this.root) {\n throw new Error('渲染器未初始化,请先调用 initialize()');\n }\n\n // 获取初始语言(从 locale 配置中推断,或使用默认值)\n const initialLocale: LangType = options.locale\n ? (Object.keys(options.locale)[0] as LangType) || 'zh-CN'\n : 'zh-CN';\n\n this.root.render(\n <StrictMode>\n <ErrorBoundary\n fallback={options.errorFallback}\n onError={(error) => {\n services.monitoring.captureError(error);\n }}\n >\n <InitializationErrorThrower />\n <AppContextProvider\n initialTheme={options.theme}\n initialLocale={initialLocale}\n initialAntdConfig={options.antd}\n stateManager={services.stateManager}\n antdApp={options.antdApp}\n >\n {/* \n 启动页不使用 RouterWrapper,因为:\n 1. 启动页应该在路由系统初始化之前渲染\n 2. 启动页完成后才会渲染主应用,此时路由系统已经初始化完成\n */}\n <BasicLayout>\n <SplashScreen options={options} onComplete={onComplete} />\n </BasicLayout>\n </AppContextProvider>\n </ErrorBoundary>\n </StrictMode>\n );\n }\n\n /**\n * 渲染错误页面\n * \n * @param options - 启动配置选项\n * @param services - 服务实例\n * @param error - 错误信息\n */\n renderError(\n options: StartOptions,\n services: {\n monitoring: MonitoringService;\n }\n ): void {\n if (!this.root) {\n throw new Error('渲染器未初始化,请先调用 initialize()');\n }\n\n this.root.render(\n <StrictMode>\n <ErrorBoundary\n fallback={options.errorFallback}\n onError={(err) => {\n services.monitoring.captureError(err);\n if (options.errorMonitor?.onError) {\n options.errorMonitor.onError(err);\n }\n }}\n >\n <InitializationErrorThrower />\n <div>框架启动失败</div>\n </ErrorBoundary>\n </StrictMode>\n );\n }\n\n /**\n * 销毁渲染器\n */\n destroy(): void {\n if (this.root) {\n this.root.unmount();\n this.root = null;\n }\n this.container = null;\n }\n\n /**\n * 获取容器\n */\n getContainer(): Container | null {\n return this.container;\n }\n}\n"],"names":["createRoot","StrictMode","useMemo","useCallback","memo","BasicLayout","DefaultApp","AppContextProvider","ErrorBoundary","InitializationErrorThrower","SplashScreen","SecurityUtils","getRouterManager","RouterProvider","OptimizedAppContent","options","services","context","securityConfig","_securityConfig","initialLocale","locale","Object","keys","shouldUseRouter","routerEnabled","router","enabled","routerManager","getRouter","handleError","error","monitoring","captureError","appContent","app","fallback","errorFallback","onError","initialTheme","theme","initialAntdConfig","antd","initialInitializationContext","stateManager","antdApp","displayName","AppRenderer","initialize","container","rootOptions","root","renderApp","Error","enableXSSProtection","security","validateConfig","sanitizeUserInput","csrf","Promise","resolve","then","configStr","JSON","stringify","validation","validateInput","safe","reason","initCSRFManager","headerName","cookieName","getToken","validateToken","catch","process","env","NODE_ENV","console","warn","render","renderSplashScreen","onComplete","renderError","err","errorMonitor","div","destroy","unmount","getContainer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/core/startup/renderApp.tsx"],"sourcesContent":["/**\n * 应用渲染模块\n * 负责渲染React应用\n */\n\nimport { createRoot } from 'react-dom/client';\nimport type { Root } from 'react-dom/client';\nimport { StrictMode, useMemo, useCallback, memo } from 'react';\nimport type { Container, RootOptions } from 'react-dom/client';\nimport { BasicLayout, DefaultApp, AppContextProvider } from '../app';\nimport type { LangType } from '../../library/locale/types';\nimport { ErrorBoundary } from '../error';\nimport { InitializationErrorThrower } from '../initialization';\nimport type { StartOptions } from '../types';\nimport type { InitializationContext } from '../initialization';\nimport type { MonitoringService } from '../../utils/monitoring';\nimport type { StateManager } from '../../state';\nimport { SplashScreen } from '../splash';\nimport { SecurityUtils } from '../../utils/security';\nimport { getRouterManager } from '../router/RouterManager';\nimport { RouterProvider } from \"react-router-dom\";\n\n/**\n * 安全配置类型\n */\ninterface SecurityConfig {\n enableXSSProtection: boolean;\n validateConfig: boolean;\n sanitizeUserInput: boolean;\n csrf?: StartOptions['security'] extends infer S\n ? S extends { csrf?: infer C }\n ? C\n : never\n : never;\n}\n\n/**\n * 优化的应用内容组件\n * 使用 useMemo 缓存计算结果,提升渲染性能\n */\ninterface OptimizedAppContentProps {\n options: StartOptions;\n services: {\n monitoring: MonitoringService;\n stateManager: StateManager;\n };\n context?: InitializationContext;\n securityConfig: SecurityConfig;\n}\n\nconst OptimizedAppContent = memo<OptimizedAppContentProps>(({\n options,\n services,\n context,\n // securityConfig 用于未来扩展,当前暂不使用\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n securityConfig: _securityConfig,\n}) => {\n // 优化:使用 useMemo 缓存初始语言计算\n const initialLocale = useMemo<LangType>(() => {\n return options.locale\n ? (Object.keys(options.locale)[0] as LangType) || 'zh-CN'\n : 'zh-CN';\n }, [options.locale]);\n\n // 优化:使用 useMemo 缓存路由判断结果\n const shouldUseRouter = useMemo(() => {\n const routerEnabled = options.router\n ? options.router.enabled !== false && options.router.enabled !== 'disabled'\n : false;\n\n if (!routerEnabled) {\n return false;\n }\n\n const routerManager = getRouterManager();\n const router = routerManager.getRouter();\n return router !== null;\n }, [options.router]);\n\n // 优化:使用 useMemo 缓存路由实例\n const router = useMemo(() => {\n if (!shouldUseRouter) {\n return null;\n }\n const routerManager = getRouterManager();\n return routerManager.getRouter();\n }, [shouldUseRouter]);\n\n // 优化:使用 useCallback 缓存错误处理函数\n const handleError = useCallback((error: unknown) => {\n services.monitoring.captureError(error);\n }, [services.monitoring]);\n\n // 优化:使用 useMemo 缓存应用内容\n const appContent = useMemo(() => {\n if (shouldUseRouter && router) {\n return <RouterProvider router={router} />;\n }\n return options.app || <DefaultApp />;\n }, [shouldUseRouter, router, options.app]);\n\n return (\n <ErrorBoundary\n fallback={options.errorFallback}\n onError={handleError}\n >\n <InitializationErrorThrower />\n <AppContextProvider\n initialTheme={options.theme}\n initialLocale={initialLocale}\n initialAntdConfig={options.uiProvider || options.antd}\n initialInitializationContext={context}\n stateManager={services.stateManager}\n antdApp={options.uiApp || options.antdApp}\n >\n <BasicLayout globalProvider={options.globalProvider}>\n {appContent}\n </BasicLayout>\n </AppContextProvider>\n </ErrorBoundary>\n );\n});\n\nOptimizedAppContent.displayName = 'OptimizedAppContent';\n\n/**\n * 应用渲染器\n */\nexport class AppRenderer {\n private root: Root | null = null;\n private container: Container | null = null;\n\n /**\n * 初始化渲染器\n *\n * @param container - React应用的挂载容器\n * @param rootOptions - React根节点配置选项\n */\n initialize(container: Container, rootOptions?: RootOptions): void {\n this.container = container;\n if (!this.root) {\n this.root = createRoot(container, rootOptions);\n }\n }\n\n /**\n * 渲染应用\n *\n * 优化:\n * 1. 默认启用安全防护(XSS防护)\n * 2. 优化组件渲染性能,使用 useMemo 缓存计算结果\n * 3. 将安全配置计算提取到初始化阶段\n *\n * @param options - 启动配置选项\n * @param services - 服务实例\n * @param context - 初始化上下文(可选)\n */\n async renderApp(\n options: StartOptions,\n services: {\n monitoring: MonitoringService;\n stateManager: StateManager;\n },\n context?: InitializationContext\n ): Promise<void> {\n if (!this.root) {\n throw new Error('渲染器未初始化,请先调用 initialize()');\n }\n\n // 优化:安全配置在初始化阶段计算(在 startApp 中预计算)\n // 这里只使用预计算的值,避免在渲染时重复计算\n const securityConfig: SecurityConfig = {\n enableXSSProtection: options.security?.enableXSSProtection ?? true,\n validateConfig: options.security?.validateConfig ?? true,\n sanitizeUserInput: options.security?.sanitizeUserInput ?? true,\n csrf: options.security?.csrf,\n };\n\n // 优化:安全验证在初始化阶段完成,这里只进行必要的运行时检查\n // 如果启用了安全模式(默认启用),对配置进行验证\n if (securityConfig.enableXSSProtection && securityConfig.validateConfig) {\n // 异步验证配置,不阻塞渲染\n Promise.resolve().then(() => {\n try {\n const configStr = JSON.stringify(options);\n const validation = SecurityUtils.validateInput(configStr);\n if (!validation.safe) {\n services.monitoring.captureError(\n new Error('配置项包含不安全内容'),\n { reason: validation.reason }\n );\n }\n } catch (error) {\n // 忽略序列化错误(某些配置项可能包含不可序列化的内容)\n }\n });\n }\n\n // 初始化 CSRF 防护(如果启用,异步执行,不阻塞渲染)\n if (securityConfig.enableXSSProtection && securityConfig.csrf?.enabled !== false) {\n import('../../utils/csrf').then(({ initCSRFManager }) => {\n initCSRFManager({\n headerName: securityConfig.csrf?.headerName,\n cookieName: securityConfig.csrf?.cookieName,\n getToken: securityConfig.csrf?.getToken,\n validateToken: securityConfig.csrf?.validateToken,\n });\n }).catch((error) => {\n // CSRF 初始化失败不影响应用启动,但记录警告\n if (process.env.NODE_ENV === 'development') {\n console.warn('CSRF 防护初始化失败:', error);\n }\n });\n }\n\n // 使用优化的应用内容组件,内部使用 useMemo 缓存计算结果\n this.root.render(\n <StrictMode>\n <OptimizedAppContent\n options={options}\n services={services}\n context={context}\n securityConfig={securityConfig}\n />\n </StrictMode>\n );\n }\n\n /**\n * 渲染启动页\n *\n * 注意:启动页不使用 RouterWrapper,因为启动页应该在路由系统之前渲染\n *\n * @param options - 启动配置选项\n * @param services - 服务实例\n * @param onComplete - 启动页完成回调\n */\n renderSplashScreen(\n options: StartOptions,\n services: {\n monitoring: MonitoringService;\n stateManager: StateManager;\n },\n onComplete: (context: InitializationContext) => void\n ): void {\n if (!this.root) {\n throw new Error('渲染器未初始化,请先调用 initialize()');\n }\n\n // 获取初始语言(从 locale 配置中推断,或使用默认值)\n const initialLocale: LangType = options.locale\n ? (Object.keys(options.locale)[0] as LangType) || 'zh-CN'\n : 'zh-CN';\n\n this.root.render(\n <StrictMode>\n <ErrorBoundary\n fallback={options.errorFallback}\n onError={(error) => {\n services.monitoring.captureError(error);\n }}\n >\n <InitializationErrorThrower />\n <AppContextProvider\n initialTheme={options.theme}\n initialLocale={initialLocale}\n initialAntdConfig={options.uiProvider || options.antd}\n stateManager={services.stateManager}\n antdApp={options.uiApp || options.antdApp}\n >\n {/*\n 启动页不使用 RouterWrapper,因为:\n 1. 启动页应该在路由系统初始化之前渲染\n 2. 启动页完成后才会渲染主应用,此时路由系统已经初始化完成\n */}\n <BasicLayout globalProvider={options.globalProvider}>\n <SplashScreen options={options} onComplete={onComplete} />\n </BasicLayout>\n </AppContextProvider>\n </ErrorBoundary>\n </StrictMode>\n );\n }\n\n /**\n * 渲染错误页面\n *\n * @param options - 启动配置选项\n * @param services - 服务实例\n * @param error - 错误信息\n */\n renderError(\n options: StartOptions,\n services: {\n monitoring: MonitoringService;\n }\n ): void {\n if (!this.root) {\n throw new Error('渲染器未初始化,请先调用 initialize()');\n }\n\n this.root.render(\n <StrictMode>\n <ErrorBoundary\n fallback={options.errorFallback}\n onError={(err) => {\n services.monitoring.captureError(err);\n if (options.errorMonitor?.onError) {\n options.errorMonitor.onError(err);\n }\n }}\n >\n <InitializationErrorThrower />\n <div>框架启动失败</div>\n </ErrorBoundary>\n </StrictMode>\n );\n }\n\n /**\n * 销毁渲染器\n */\n destroy(): void {\n if (this.root) {\n this.root.unmount();\n this.root = null;\n }\n this.container = null;\n }\n\n /**\n * 获取容器\n */\n getContainer(): Container | null {\n return this.container;\n }\n}\n"],"names":["createRoot","StrictMode","useMemo","useCallback","memo","BasicLayout","DefaultApp","AppContextProvider","ErrorBoundary","InitializationErrorThrower","SplashScreen","SecurityUtils","getRouterManager","RouterProvider","OptimizedAppContent","options","services","context","securityConfig","_securityConfig","initialLocale","locale","Object","keys","shouldUseRouter","routerEnabled","router","enabled","routerManager","getRouter","handleError","error","monitoring","captureError","appContent","app","fallback","errorFallback","onError","initialTheme","theme","initialAntdConfig","uiProvider","antd","initialInitializationContext","stateManager","antdApp","uiApp","globalProvider","displayName","AppRenderer","initialize","container","rootOptions","root","renderApp","Error","enableXSSProtection","security","validateConfig","sanitizeUserInput","csrf","Promise","resolve","then","configStr","JSON","stringify","validation","validateInput","safe","reason","initCSRFManager","headerName","cookieName","getToken","validateToken","catch","process","env","NODE_ENV","console","warn","render","renderSplashScreen","onComplete","renderError","err","errorMonitor","div","destroy","unmount","getContainer"],"mappings":"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"}
|