@vlian/framework 1.2.25 → 1.2.38
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.umd.js +208 -2395
- package/dist/analytics.umd.js.map +1 -1
- package/dist/core/Test.cjs +2 -2
- package/dist/core/Test.cjs.map +1 -1
- package/dist/core/Test.js +1 -1
- package/dist/core/Test.js.map +1 -1
- package/dist/core/config/ConfigLoader.cjs +7 -7
- package/dist/core/config/ConfigLoader.cjs.map +1 -1
- package/dist/core/config/ConfigLoader.js +1 -1
- package/dist/core/config/ConfigLoader.js.map +1 -1
- package/dist/core/error/ErrorBoundary.cjs +6 -6
- package/dist/core/error/ErrorBoundary.cjs.map +1 -1
- package/dist/core/error/ErrorBoundary.d.ts +1 -1
- package/dist/core/error/ErrorBoundary.js +2 -2
- package/dist/core/error/ErrorBoundary.js.map +1 -1
- package/dist/core/error/ErrorHandler.cjs +19 -19
- package/dist/core/error/ErrorHandler.cjs.map +1 -1
- package/dist/core/error/ErrorHandler.d.ts +2 -2
- package/dist/core/error/ErrorHandler.js +2 -2
- package/dist/core/error/ErrorHandler.js.map +1 -1
- package/dist/core/event/AppEventBus.cjs +5 -5
- package/dist/core/event/AppEventBus.cjs.map +1 -1
- package/dist/core/event/AppEventBus.js +1 -1
- package/dist/core/event/AppEventBus.js.map +1 -1
- package/dist/core/initialization/InitializationErrorThrower.cjs.map +1 -1
- package/dist/core/initialization/InitializationErrorThrower.js.map +1 -1
- package/dist/core/initialization/initialization.cjs +3 -3
- package/dist/core/initialization/initialization.cjs.map +1 -1
- package/dist/core/initialization/initialization.d.ts +1 -1
- package/dist/core/initialization/initialization.js +1 -1
- package/dist/core/initialization/initialization.js.map +1 -1
- package/dist/core/initialization/initializationErrorState.cjs +2 -2
- package/dist/core/initialization/initializationErrorState.cjs.map +1 -1
- package/dist/core/initialization/initializationErrorState.d.ts +1 -1
- package/dist/core/initialization/initializationErrorState.js +1 -1
- package/dist/core/initialization/initializationErrorState.js.map +1 -1
- package/dist/core/kernel/defaultAdapters.cjs +14 -13
- package/dist/core/kernel/defaultAdapters.cjs.map +1 -1
- package/dist/core/kernel/defaultAdapters.js +2 -1
- package/dist/core/kernel/defaultAdapters.js.map +1 -1
- package/dist/core/kernel/types.d.ts +1 -1
- package/dist/core/kernel/types.js.map +1 -1
- package/dist/core/router/RouterManager.cjs +9 -9
- package/dist/core/router/RouterManager.cjs.map +1 -1
- package/dist/core/router/RouterManager.js +1 -1
- package/dist/core/router/RouterManager.js.map +1 -1
- package/dist/core/router/adapter/AdapterManager.cjs +10 -10
- package/dist/core/router/adapter/AdapterManager.cjs.map +1 -1
- package/dist/core/router/adapter/AdapterManager.js +1 -1
- package/dist/core/router/adapter/AdapterManager.js.map +1 -1
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.cjs +4 -4
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.cjs.map +1 -1
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.js +1 -1
- package/dist/core/router/adapter/react-router/ReactRouterAdapter.js.map +1 -1
- package/dist/core/router/dynamic/DynamicRouteManager.cjs +8 -8
- package/dist/core/router/dynamic/DynamicRouteManager.cjs.map +1 -1
- package/dist/core/router/dynamic/DynamicRouteManager.js +1 -1
- package/dist/core/router/dynamic/DynamicRouteManager.js.map +1 -1
- package/dist/core/router/errors/RouterError.cjs +4 -4
- package/dist/core/router/errors/RouterError.cjs.map +1 -1
- package/dist/core/router/errors/RouterError.d.ts +1 -1
- package/dist/core/router/errors/RouterError.js +1 -1
- package/dist/core/router/errors/RouterError.js.map +1 -1
- package/dist/core/router/lifecycle/RouterLifecycleManager.cjs +8 -8
- package/dist/core/router/lifecycle/RouterLifecycleManager.cjs.map +1 -1
- package/dist/core/router/lifecycle/RouterLifecycleManager.js +1 -1
- package/dist/core/router/lifecycle/RouterLifecycleManager.js.map +1 -1
- package/dist/core/router/middleware/RouterMiddlewareManager.cjs +11 -11
- package/dist/core/router/middleware/RouterMiddlewareManager.cjs.map +1 -1
- package/dist/core/router/middleware/RouterMiddlewareManager.js +1 -1
- package/dist/core/router/middleware/RouterMiddlewareManager.js.map +1 -1
- package/dist/core/router/middleware/auth.cjs +4 -4
- package/dist/core/router/middleware/auth.cjs.map +1 -1
- package/dist/core/router/middleware/auth.js +1 -1
- package/dist/core/router/middleware/auth.js.map +1 -1
- package/dist/core/router/monitoring/RouterMonitoring.cjs +2 -2
- package/dist/core/router/monitoring/RouterMonitoring.cjs.map +1 -1
- package/dist/core/router/monitoring/RouterMonitoring.js +2 -2
- package/dist/core/router/monitoring/RouterMonitoring.js.map +1 -1
- package/dist/core/router/navigation/RouterNavigation.cjs +7 -7
- package/dist/core/router/navigation/RouterNavigation.cjs.map +1 -1
- package/dist/core/router/navigation/RouterNavigation.js +1 -1
- package/dist/core/router/navigation/RouterNavigation.js.map +1 -1
- package/dist/core/router/performance/RouteCache.cjs +7 -7
- package/dist/core/router/performance/RouteCache.cjs.map +1 -1
- package/dist/core/router/performance/RouteCache.js +1 -1
- package/dist/core/router/performance/RouteCache.js.map +1 -1
- package/dist/core/router/performance/RoutePreloader.cjs +6 -6
- package/dist/core/router/performance/RoutePreloader.cjs.map +1 -1
- package/dist/core/router/performance/RoutePreloader.js +1 -1
- package/dist/core/router/performance/RoutePreloader.js.map +1 -1
- package/dist/core/router/plugin/RouterPluginManager.cjs +8 -8
- package/dist/core/router/plugin/RouterPluginManager.cjs.map +1 -1
- package/dist/core/router/plugin/RouterPluginManager.js +1 -1
- package/dist/core/router/plugin/RouterPluginManager.js.map +1 -1
- package/dist/core/router/utils/adapters/react-router/transform.cjs +6 -2
- package/dist/core/router/utils/adapters/react-router/transform.cjs.map +1 -1
- package/dist/core/router/utils/adapters/react-router/transform.js +5 -1
- package/dist/core/router/utils/adapters/react-router/transform.js.map +1 -1
- package/dist/core/router/utils/transform.cjs +13 -12
- package/dist/core/router/utils/transform.cjs.map +1 -1
- package/dist/core/router/utils/transform.js +2 -1
- package/dist/core/router/utils/transform.js.map +1 -1
- package/dist/core/router/validation/RouterConfigValidator.cjs +2 -2
- package/dist/core/router/validation/RouterConfigValidator.cjs.map +1 -1
- package/dist/core/router/validation/RouterConfigValidator.js +1 -1
- package/dist/core/router/validation/RouterConfigValidator.js.map +1 -1
- package/dist/core/router/version/RouteVersionManager.cjs +6 -6
- package/dist/core/router/version/RouteVersionManager.cjs.map +1 -1
- package/dist/core/router/version/RouteVersionManager.js +1 -1
- package/dist/core/router/version/RouteVersionManager.js.map +1 -1
- package/dist/core/splash/SplashScreen.cjs +4 -4
- package/dist/core/splash/SplashScreen.cjs.map +1 -1
- package/dist/core/splash/SplashScreen.js +1 -1
- package/dist/core/splash/SplashScreen.js.map +1 -1
- package/dist/core/startup/initializeServices.cjs +15 -15
- package/dist/core/startup/initializeServices.cjs.map +1 -1
- package/dist/core/startup/initializeServices.d.ts +2 -2
- package/dist/core/startup/initializeServices.js +3 -3
- package/dist/core/startup/initializeServices.js.map +1 -1
- package/dist/core/startup/performanceTracker.cjs.map +1 -1
- package/dist/core/startup/performanceTracker.d.ts +1 -1
- package/dist/core/startup/performanceTracker.js.map +1 -1
- package/dist/core/startup/renderApp.cjs +3 -3
- package/dist/core/startup/renderApp.cjs.map +1 -1
- package/dist/core/startup/renderApp.d.ts +1 -1
- package/dist/core/startup/renderApp.js +2 -2
- package/dist/core/startup/renderApp.js.map +1 -1
- package/dist/core/startup/startApp.cjs +24 -24
- package/dist/core/startup/startApp.cjs.map +1 -1
- package/dist/core/startup/startApp.js +5 -5
- package/dist/core/startup/startApp.js.map +1 -1
- package/dist/core/types.d.ts +3 -3
- package/dist/core/types.js.map +1 -1
- package/dist/index.cjs +15 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +2150 -23125
- package/dist/index.umd.js.map +1 -1
- package/dist/kernel/constants.cjs +67 -0
- package/dist/kernel/constants.cjs.map +1 -0
- package/dist/kernel/constants.d.ts +5 -0
- package/dist/kernel/constants.js +43 -0
- package/dist/kernel/constants.js.map +1 -0
- package/dist/kernel/index.cjs +40 -0
- package/dist/kernel/index.cjs.map +1 -0
- package/dist/kernel/index.d.ts +3 -0
- package/dist/kernel/index.js +4 -0
- package/dist/kernel/index.js.map +1 -0
- package/dist/kernel/kernel.cjs +296 -0
- package/dist/kernel/kernel.cjs.map +1 -0
- package/dist/kernel/kernel.d.ts +40 -0
- package/dist/kernel/kernel.js +272 -0
- package/dist/kernel/kernel.js.map +1 -0
- package/dist/kernel/manager/cacheManager.cjs +46 -0
- package/dist/kernel/manager/cacheManager.cjs.map +1 -0
- package/dist/kernel/manager/cacheManager.d.ts +6 -0
- package/dist/kernel/manager/cacheManager.js +36 -0
- package/dist/kernel/manager/cacheManager.js.map +1 -0
- package/dist/kernel/manager/i18nManager.cjs +68 -0
- package/dist/kernel/manager/i18nManager.cjs.map +1 -0
- package/dist/kernel/manager/i18nManager.d.ts +8 -0
- package/dist/kernel/manager/i18nManager.js +58 -0
- package/dist/kernel/manager/i18nManager.js.map +1 -0
- package/dist/kernel/manager/index.cjs +30 -0
- package/dist/kernel/manager/index.cjs.map +1 -0
- package/dist/kernel/manager/index.d.ts +4 -0
- package/dist/kernel/manager/index.js +6 -0
- package/dist/kernel/manager/index.js.map +1 -0
- package/dist/kernel/manager/loggerManager.cjs +70 -0
- package/dist/kernel/manager/loggerManager.cjs.map +1 -0
- package/dist/kernel/manager/loggerManager.d.ts +14 -0
- package/dist/kernel/manager/loggerManager.js +60 -0
- package/dist/kernel/manager/loggerManager.js.map +1 -0
- package/dist/kernel/manager/persistence.cjs +93 -0
- package/dist/kernel/manager/persistence.cjs.map +1 -0
- package/dist/kernel/manager/persistence.d.ts +3 -0
- package/dist/kernel/manager/persistence.js +75 -0
- package/dist/kernel/manager/persistence.js.map +1 -0
- package/dist/kernel/manager/themeManager.cjs +85 -0
- package/dist/kernel/manager/themeManager.cjs.map +1 -0
- package/dist/kernel/manager/themeManager.d.ts +9 -0
- package/dist/kernel/manager/themeManager.js +75 -0
- package/dist/kernel/manager/themeManager.js.map +1 -0
- package/dist/kernel/types.cjs +6 -0
- package/dist/kernel/types.cjs.map +1 -0
- package/dist/kernel/types.d.ts +72 -0
- package/dist/kernel/types.js +3 -0
- package/dist/kernel/types.js.map +1 -0
- package/dist/library/storage/encryption.cjs +12 -13
- package/dist/library/storage/encryption.cjs.map +1 -1
- package/dist/library/storage/encryption.js +1 -2
- package/dist/library/storage/encryption.js.map +1 -1
- package/dist/request/adapter.d.ts +1 -0
- package/dist/request/core.d.ts +1 -0
- package/dist/request/index.d.ts +1 -42
- package/dist/request/plugin/csrfPlugin.d.ts +2 -2
- package/dist/request/plugin/queue.d.ts +2 -2
- package/dist/request/plugin.d.ts +1 -0
- package/dist/request/runtime.d.ts +1 -0
- package/dist/request/types.d.ts +1 -394
- package/dist/request/utils.d.ts +1 -0
- package/dist/state.umd.js +1 -1
- package/dist/utils/csrf.cjs +13 -152
- package/dist/utils/csrf.cjs.map +1 -1
- package/dist/utils/csrf.d.ts +1 -72
- package/dist/utils/csrf.js +1 -142
- package/dist/utils/csrf.js.map +1 -1
- package/dist/utils/errors/ErrorCodes.cjs +6 -76
- package/dist/utils/errors/ErrorCodes.cjs.map +1 -1
- package/dist/utils/errors/ErrorCodes.d.ts +1 -45
- package/dist/utils/errors/ErrorCodes.js +1 -84
- package/dist/utils/errors/ErrorCodes.js.map +1 -1
- package/dist/utils/errors.cjs +53 -326
- package/dist/utils/errors.cjs.map +1 -1
- package/dist/utils/errors.d.ts +19 -172
- package/dist/utils/errors.js +16 -352
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/logger.cjs +5 -374
- package/dist/utils/logger.cjs.map +1 -1
- package/dist/utils/logger.d.ts +2 -189
- package/dist/utils/logger.js +1 -379
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/logger.types.cjs +3 -12
- package/dist/utils/logger.types.cjs.map +1 -1
- package/dist/utils/logger.types.d.ts +2 -57
- package/dist/utils/logger.types.js +1 -10
- package/dist/utils/logger.types.js.map +1 -1
- package/dist/utils/monitoring.cjs +11 -302
- package/dist/utils/monitoring.cjs.map +1 -1
- package/dist/utils/monitoring.d.ts +1 -163
- package/dist/utils/monitoring.js +1 -294
- package/dist/utils/monitoring.js.map +1 -1
- package/dist/utils/performance.cjs +5 -352
- package/dist/utils/performance.cjs.map +1 -1
- package/dist/utils/performance.d.ts +2 -246
- package/dist/utils/performance.js +1 -354
- package/dist/utils/performance.js.map +1 -1
- package/dist/utils/resourceLoader.cjs +5 -303
- package/dist/utils/resourceLoader.cjs.map +1 -1
- package/dist/utils/resourceLoader.d.ts +2 -130
- package/dist/utils/resourceLoader.js +1 -305
- package/dist/utils/resourceLoader.js.map +1 -1
- package/dist/utils/runtimeSecurity.cjs +2 -140
- package/dist/utils/runtimeSecurity.cjs.map +1 -1
- package/dist/utils/runtimeSecurity.d.ts +2 -104
- package/dist/utils/runtimeSecurity.js +1 -141
- package/dist/utils/runtimeSecurity.js.map +1 -1
- package/dist/utils/security.cjs +3 -314
- package/dist/utils/security.cjs.map +1 -1
- package/dist/utils/security.d.ts +2 -80
- package/dist/utils/security.js +1 -311
- package/dist/utils/security.js.map +1 -1
- package/dist/utils/traceId.cjs +10 -111
- package/dist/utils/traceId.cjs.map +1 -1
- package/dist/utils/traceId.d.ts +1 -63
- package/dist/utils/traceId.js +1 -116
- package/dist/utils/traceId.js.map +1 -1
- package/dist/utils/validation.cjs +3 -173
- package/dist/utils/validation.cjs.map +1 -1
- package/dist/utils/validation.d.ts +2 -110
- package/dist/utils/validation.js +1 -175
- package/dist/utils/validation.js.map +1 -1
- package/package.json +15 -24
- package/dist/lazy/index.cjs +0 -104
- package/dist/lazy/index.cjs.map +0 -1
- package/dist/lazy/index.d.ts +0 -19
- package/dist/lazy/index.js +0 -24
- package/dist/lazy/index.js.map +0 -1
- package/dist/request/adapter/RequestAdapter.cjs +0 -78
- package/dist/request/adapter/RequestAdapter.cjs.map +0 -1
- package/dist/request/adapter/axiosAdapter.cjs +0 -164
- package/dist/request/adapter/axiosAdapter.cjs.map +0 -1
- package/dist/request/adapter/fetchAdapter.cjs +0 -134
- package/dist/request/adapter/fetchAdapter.cjs.map +0 -1
- package/dist/request/adapter/index.cjs +0 -80
- package/dist/request/adapter/index.cjs.map +0 -1
- package/dist/request/adapter/kyAdapter.cjs +0 -191
- package/dist/request/adapter/kyAdapter.cjs.map +0 -1
- package/dist/request/adapter/undiciAdapter.cjs +0 -213
- package/dist/request/adapter/undiciAdapter.cjs.map +0 -1
- package/dist/request/core/RequestClient.cjs +0 -558
- package/dist/request/core/RequestClient.cjs.map +0 -1
- package/dist/request/core/index.cjs +0 -15
- package/dist/request/core/index.cjs.map +0 -1
- package/dist/request/index.cjs +0 -149
- package/dist/request/index.cjs.map +0 -1
- package/dist/request/plugin/RequestPlugin.cjs +0 -218
- package/dist/request/plugin/RequestPlugin.cjs.map +0 -1
- package/dist/request/plugin/cache.cjs +0 -269
- package/dist/request/plugin/cache.cjs.map +0 -1
- package/dist/request/plugin/csrfPlugin.cjs +0 -40
- package/dist/request/plugin/csrfPlugin.cjs.map +0 -1
- package/dist/request/plugin/index.cjs +0 -53
- package/dist/request/plugin/index.cjs.map +0 -1
- package/dist/request/plugin/monitoring.cjs +0 -216
- package/dist/request/plugin/monitoring.cjs.map +0 -1
- package/dist/request/plugin/queue.cjs +0 -140
- package/dist/request/plugin/queue.cjs.map +0 -1
- package/dist/request/plugin/retry.cjs +0 -98
- package/dist/request/plugin/retry.cjs.map +0 -1
- package/dist/request/plugin/validation.cjs +0 -121
- package/dist/request/plugin/validation.cjs.map +0 -1
- package/dist/request/runtime/RequestContext.cjs +0 -77
- package/dist/request/runtime/RequestContext.cjs.map +0 -1
- package/dist/request/runtime/index.cjs +0 -32
- package/dist/request/runtime/index.cjs.map +0 -1
- package/dist/request/types.cjs +0 -112
- package/dist/request/types.cjs.map +0 -1
- package/dist/request/utils/RequestQueueManager.cjs +0 -168
- package/dist/request/utils/RequestQueueManager.cjs.map +0 -1
- package/dist/request/utils/dependencyCheck.cjs +0 -237
- package/dist/request/utils/dependencyCheck.cjs.map +0 -1
- package/dist/request/utils/index.cjs +0 -30
- package/dist/request/utils/index.cjs.map +0 -1
- package/dist/request.umd.js +0 -5392
- package/dist/request.umd.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/monitoring/RouterMonitoring.ts"],"sourcesContent":["/**\n * 路由监控服务\n * 提供路由访问统计、性能监控、错误监控等功能\n */\n\nimport { getMonitoring } from '../../../utils/monitoring';\nimport { logger } from '../../../utils/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
|
+
{"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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"}
|
|
@@ -11,7 +11,7 @@ Object.defineProperty(exports, "RouterNavigation", {
|
|
|
11
11
|
return RouterNavigation;
|
|
12
12
|
}
|
|
13
13
|
});
|
|
14
|
-
const
|
|
14
|
+
const _logger = require("@vlian/logger");
|
|
15
15
|
const _lifecycle = require("../lifecycle");
|
|
16
16
|
const _middleware = require("../middleware");
|
|
17
17
|
function _define_property(obj, key, value) {
|
|
@@ -113,12 +113,12 @@ let RouterNavigation = class RouterNavigation {
|
|
|
113
113
|
let finalPath = targetPath;
|
|
114
114
|
// 如果 beforeEach 返回 false,阻止导航
|
|
115
115
|
if (beforeEachResult === false) {
|
|
116
|
-
|
|
116
|
+
_logger.logger.debug('路由导航被阻止: beforeEach 返回 false');
|
|
117
117
|
return;
|
|
118
118
|
}
|
|
119
119
|
// 如果 beforeEach 返回字符串,重定向到该路径
|
|
120
120
|
if (typeof beforeEachResult === 'string') {
|
|
121
|
-
|
|
121
|
+
_logger.logger.debug(`路由导航重定向: ${beforeEachResult}`);
|
|
122
122
|
finalPath = this.buildTargetPath(beforeEachResult);
|
|
123
123
|
}
|
|
124
124
|
// 执行中间件
|
|
@@ -135,13 +135,13 @@ let RouterNavigation = class RouterNavigation {
|
|
|
135
135
|
// 如果中间件阻止导航
|
|
136
136
|
if (!middlewareResult.allow) {
|
|
137
137
|
if (middlewareResult.redirect) {
|
|
138
|
-
|
|
138
|
+
_logger.logger.debug(`路由导航被中间件重定向: ${middlewareResult.redirect}`);
|
|
139
139
|
return this.navigateInternal(middlewareResult.redirect, {
|
|
140
140
|
...options,
|
|
141
141
|
query: undefined
|
|
142
142
|
}, depth + 1, visited);
|
|
143
143
|
}
|
|
144
|
-
|
|
144
|
+
_logger.logger.debug(`路由导航被中间件阻止: ${middlewareResult.reason || '未知原因'}`);
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
147
|
// 执行导航
|
|
@@ -166,7 +166,7 @@ let RouterNavigation = class RouterNavigation {
|
|
|
166
166
|
totalTime: duration
|
|
167
167
|
});
|
|
168
168
|
} catch (error) {
|
|
169
|
-
|
|
169
|
+
_logger.logger.error('路由导航失败', error);
|
|
170
170
|
throw error;
|
|
171
171
|
}
|
|
172
172
|
}
|
|
@@ -216,7 +216,7 @@ let RouterNavigation = class RouterNavigation {
|
|
|
216
216
|
} else if (fallback) {
|
|
217
217
|
await this.navigate(fallback);
|
|
218
218
|
} else {
|
|
219
|
-
|
|
219
|
+
_logger.logger.warn('没有历史记录,无法返回');
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
222
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/navigation/RouterNavigation.ts"],"sourcesContent":["/**\n * 路由导航 API\n * 提供框架级别的路由导航能力,封装 react-router-dom 的导航功能\n */\n\nimport { logger } from '../../../utils';\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
|
+
{"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":"AAAA;;;CAGC;;;;+BAWYA;;;eAAAA;;;wBATU;2BAEmB;4BACC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMpC,IAAA,AAAMA,mBAAN,MAAMA;IAGX,OAAeC,gBACbC,EAAU,EACVC,KAA+B,EACvB;QACR,MAAMC,OACJ,OAAOC,WAAW,eAAeA,OAAOC,QAAQ,EAAEC,SAC9CF,OAAOC,QAAQ,CAACC,MAAM,GACtB;QAEN,MAAMC,MAAM,IAAIC,IAAIP,IAAIE;QAExB,IAAID,SAASO,OAAOC,IAAI,CAACR,OAAOS,MAAM,GAAG,GAAG;YAC1C,MAAMC,SAAS,IAAIC,gBAAgBN,IAAIO,MAAM;YAC7CL,OAAOM,OAAO,CAACb,OAAOc,OAAO,CAAC,CAAC,CAACC,KAAKC,MAAM;gBACzC,IAAIA,UAAUC,aAAaD,UAAU,MAAM;oBACzCN,OAAOQ,MAAM,CAACH;oBACd;gBACF;gBACAL,OAAOS,GAAG,CAACJ,KAAKK,OAAOJ;YACzB;YACAX,IAAIO,MAAM,GAAGF,OAAOW,QAAQ;QAC9B;QAEA,OAAO,GAAGhB,IAAIiB,QAAQ,GAAGjB,IAAIO,MAAM,GAAGP,IAAIkB,IAAI,EAAE;IAClD;IAEA,aAAqBC,iBACnBzB,EAAU,EACV0B,OAAoC,EACpCC,KAAa,EACbC,OAAoB,EACL;QACf,MAAMC,YAAYC,YAAYC,GAAG;QAEjC,IAAIJ,QAAQ,IAAI,CAACK,aAAa,EAAE;YAC9B,MAAM,IAAIC,MAAM,CAAC,YAAY,EAAE,IAAI,CAACD,aAAa,CAAC,WAAW,CAAC;QAChE;QAEA,MAAME,aAAa,IAAI,CAACnC,eAAe,CAACC,IAAI0B,SAASzB;QACrD,IAAI2B,QAAQO,GAAG,CAACD,aAAa;YAC3B,MAAM,IAAID,MAAM,CAAC,UAAU,EAAEC,YAAY;QAC3C;QACAN,QAAQQ,GAAG,CAACF;QAEZ,MAAMG,gBAAgB,MAAM,mEAAA,QAAO,sBAAoBC,IAAI,CAAC,CAACC,IAAMA,EAAEC,gBAAgB;QACrF,MAAMC,SAASJ,cAAcK,SAAS;QAEtC,IAAI,CAACD,QAAQ;YACX,MAAM,IAAIR,MAAM;QAClB;QAEA,WAAW;QACX,MAAMU,kBAAkB,IAAI,CAACC,eAAe;QAE5C,WAAW;QACX,MAAMC,iBAAgC;YACpCC,MAAMZ;YACNjC,OAAOyB,SAASzB;QAClB;QAEA,WAAW;QACX,MAAM8C,mBAAmBC,IAAAA,oCAAyB;QAClD,MAAMC,mBAAmB,MAAMF,iBAAiBG,UAAU,CACxDL,gBACAF;QAGF,IAAIQ,YAAYjB;QAEhB,8BAA8B;QAC9B,IAAIe,qBAAqB,OAAO;YAC9BG,cAAM,CAACC,KAAK,CAAC;YACb;QACF;QAEA,8BAA8B;QAC9B,IAAI,OAAOJ,qBAAqB,UAAU;YACxCG,cAAM,CAACC,KAAK,CAAC,CAAC,SAAS,EAAEJ,kBAAkB;YAC3CE,YAAY,IAAI,CAACpD,eAAe,CAACkD;QACnC;QAEA,QAAQ;QACR,MAAMK,oBAAoBC,IAAAA,sCAA0B;QACpD,MAAMC,oBAA6C;YACjDxD,IAAI;gBACF,GAAG6C,cAAc;gBACjBC,MAAMK;YACR;YACAM,MAAMd;YACNjB;QACF;QAEA,MAAMgC,mBAAmB,MAAMJ,kBAAkBK,OAAO,CAACH;QAEzD,YAAY;QACZ,IAAI,CAACE,iBAAiBE,KAAK,EAAE;YAC3B,IAAIF,iBAAiBG,QAAQ,EAAE;gBAC7BT,cAAM,CAACC,KAAK,CAAC,CAAC,aAAa,EAAEK,iBAAiBG,QAAQ,EAAE;gBACxD,OAAO,IAAI,CAACpC,gBAAgB,CAC1BiC,iBAAiBG,QAAQ,EACzB;oBAAE,GAAGnC,OAAO;oBAAEzB,OAAOiB;gBAAU,GAC/BS,QAAQ,GACRC;YAEJ;YACAwB,cAAM,CAACC,KAAK,CAAC,CAAC,YAAY,EAAEK,iBAAiBI,MAAM,IAAI,QAAQ;YAC/D;QACF;QAEA,OAAO;QACP,IAAI;YACF,IAAIpC,SAASqC,SAAS;gBACpBtB,OAAOuB,QAAQ,CAACb,WAAW;oBAAEY,SAAS;oBAAME,OAAOvC,QAAQuC,KAAK;gBAAC;YACnE,OAAO;gBACLxB,OAAOuB,QAAQ,CAACb,WAAW;oBAAEc,OAAOvC,SAASuC;gBAAM;YACrD;YAEA,kBAAkB;YAClB,MAAMlB,iBAAiBmB,SAAS,CAC9B;gBACE,GAAGrB,cAAc;gBACjBC,MAAMK;YACR,GACAR;YAGF,MAAMwB,WAAWrC,YAAYC,GAAG,KAAKF;YACrCQ,cAAc+B,aAAa,GAAGC,qBAAqB,CAAClB,WAAW;gBAC7DmB,WAAWH;YACb;QACF,EAAE,OAAOI,OAAO;YACdnB,cAAM,CAACmB,KAAK,CAAC,UAAUA;YACvB,MAAMA;QACR;IACF;IAEA;;;;;GAKC,GACD,aAAaP,SACXhE,EAAU,EACV0B,OAAyB,EACV;QACf,OAAO,IAAI,CAACD,gBAAgB,CAACzB,IAAI0B,SAAS,GAAG,IAAI8C;IACnD;IAEA;;;;GAIC,GACD,OAAO5B,kBAAiC;QACtC,IAAI,OAAOzC,WAAW,aAAa;YACjC,OAAO;gBACL2C,MAAM;gBACN7C,OAAO,CAAC;YACV;QACF;QAEA,6BAA6B;QAC7B,MAAMsB,WAAWpB,OAAOC,QAAQ,CAACmB,QAAQ;QACzC,MAAMV,SAASV,OAAOC,QAAQ,CAACS,MAAM;QACrC,MAAMW,OAAOrB,OAAOC,QAAQ,CAACoB,IAAI;QAEjC,SAAS;QACT,MAAMvB,QAAiC,CAAC;QACxC,IAAIY,QAAQ;YACV,MAAMF,SAAS,IAAIC,gBAAgBC;YACnCF,OAAOI,OAAO,CAAC,CAACE,OAAOD;gBACrBf,KAAK,CAACe,IAAI,GAAGC;YACf;QACF;QAEA,OAAO;YACL6B,MAAMvB,WAAWC;YACjBvB;QACF;IACF;IAEA;;;;GAIC,GACD,aAAawE,OAAOC,QAAiB,EAAiB;QACpD,IAAIvE,OAAOwE,OAAO,CAACjE,MAAM,GAAG,GAAG;YAC7BP,OAAOwE,OAAO,CAACC,IAAI;QACrB,OAAO,IAAIF,UAAU;YACnB,MAAM,IAAI,CAACV,QAAQ,CAACU;QACtB,OAAO;YACLtB,cAAM,CAACyB,IAAI,CAAC;QACd;IACF;IAEA;;GAEC,GACD,OAAOC,YAAkB;QACvB3E,OAAOwE,OAAO,CAACI,OAAO;IACxB;IAEA;;;;;GAKC,GACD,aAAahB,QACX/D,EAAU,EACV0B,OAA0C,EAC3B;QACf,OAAO,IAAI,CAACsC,QAAQ,CAAChE,IAAI;YAAE,GAAG0B,OAAO;YAAEqC,SAAS;QAAK;IACvD;AACF;AA1NE,iBADWjE,kBACakC,iBAAgB"}
|
|
@@ -14,7 +14,7 @@ function _define_property(obj, key, value) {
|
|
|
14
14
|
/**
|
|
15
15
|
* 路由导航 API
|
|
16
16
|
* 提供框架级别的路由导航能力,封装 react-router-dom 的导航功能
|
|
17
|
-
*/ import { logger } from "
|
|
17
|
+
*/ import { logger } from "@vlian/logger";
|
|
18
18
|
import { getRouterLifecycleManager } from "../lifecycle";
|
|
19
19
|
import { getRouterMiddlewareManager } from "../middleware";
|
|
20
20
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/navigation/RouterNavigation.ts"],"sourcesContent":["/**\n * 路由导航 API\n * 提供框架级别的路由导航能力,封装 react-router-dom 的导航功能\n */\n\nimport { logger } from '../../../utils';\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
|
+
{"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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"}
|
|
@@ -19,7 +19,7 @@ _export(exports, {
|
|
|
19
19
|
return getRouteCache;
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
|
-
const
|
|
22
|
+
const _logger = require("@vlian/logger");
|
|
23
23
|
function _define_property(obj, key, value) {
|
|
24
24
|
if (key in obj) {
|
|
25
25
|
Object.defineProperty(obj, key, {
|
|
@@ -42,10 +42,10 @@ let RouteCache = class RouteCache {
|
|
|
42
42
|
if (typeof window !== 'undefined' && 'indexedDB' in window) {
|
|
43
43
|
this.persistenceEnabled = true;
|
|
44
44
|
await this.loadFromPersistence();
|
|
45
|
-
|
|
45
|
+
_logger.logger.debug('路由缓存持久化已启用');
|
|
46
46
|
}
|
|
47
47
|
} catch (error) {
|
|
48
|
-
|
|
48
|
+
_logger.logger.warn('路由缓存持久化初始化失败', error);
|
|
49
49
|
this.persistenceEnabled = false;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -57,7 +57,7 @@ let RouteCache = class RouteCache {
|
|
|
57
57
|
// 由于 IndexedDB 操作较复杂,这里先留空
|
|
58
58
|
// 实际实现可以使用 idb 库或原生 IndexedDB API
|
|
59
59
|
} catch (error) {
|
|
60
|
-
|
|
60
|
+
_logger.logger.warn('从持久化存储加载缓存失败', error);
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
@@ -70,7 +70,7 @@ let RouteCache = class RouteCache {
|
|
|
70
70
|
// 这里可以实现保存到 IndexedDB 的逻辑
|
|
71
71
|
// 实际实现可以使用 idb 库或原生 IndexedDB API
|
|
72
72
|
} catch (error) {
|
|
73
|
-
|
|
73
|
+
_logger.logger.warn('保存到持久化存储失败', error);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
/**
|
|
@@ -193,7 +193,7 @@ let RouteCache = class RouteCache {
|
|
|
193
193
|
// 保存到持久化存储
|
|
194
194
|
if (this.persistenceEnabled) {
|
|
195
195
|
this.saveToPersistence(key, value).catch((error)=>{
|
|
196
|
-
|
|
196
|
+
_logger.logger.warn('保存缓存到持久化存储失败', error);
|
|
197
197
|
});
|
|
198
198
|
}
|
|
199
199
|
// 检查是否需要淘汰
|
|
@@ -244,7 +244,7 @@ let RouteCache = class RouteCache {
|
|
|
244
244
|
matchHits: 0,
|
|
245
245
|
matchMisses: 0
|
|
246
246
|
};
|
|
247
|
-
|
|
247
|
+
_logger.logger.debug('路由缓存已清空');
|
|
248
248
|
}
|
|
249
249
|
/**
|
|
250
250
|
* 销毁缓存实例并释放资源
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/performance/RouteCache.ts"],"sourcesContent":["/**\n * 路由缓存管理器\n * 提供路由转换结果、匹配结果的缓存功能\n */\n\nimport { logger } from '../../../utils';\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
|
+
{"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":"AAAA;;;CAGC;;;;;;;;;;;QAgEYA;eAAAA;;QAqVGC;eAAAA;;;wBAnZO;;;;;;;;;;;;;;AA8DhB,IAAA,AAAMD,aAAN,MAAMA;IA8BX;;GAEC,GACD,MAAcE,kBAAiC;QAC7C,IAAI;YACF,oBAAoB;YACpB,IAAI,OAAOC,WAAW,eAAe,eAAeA,QAAQ;gBAC1D,IAAI,CAACC,kBAAkB,GAAG;gBAC1B,MAAM,IAAI,CAACC,mBAAmB;gBAC9BC,cAAM,CAACC,KAAK,CAAC;YACf;QACF,EAAE,OAAOC,OAAO;YACdF,cAAM,CAACG,IAAI,CAAC,gBAAgBD;YAC5B,IAAI,CAACJ,kBAAkB,GAAG;QAC5B;IACF;IAEA;;GAEC,GACD,MAAcC,sBAAqC;QACjD,IAAI;QACF,4BAA4B;QAC5B,2BAA2B;QAC3B,kCAAkC;QACpC,EAAE,OAAOG,OAAO;YACdF,cAAM,CAACG,IAAI,CAAC,gBAAgBD;QAC9B;IACF;IAEA;;GAEC,GACD,MAAcE,kBAAkBC,IAAY,EAAEC,MAA6B,EAAiB;QAC1F,IAAI,CAAC,IAAI,CAACR,kBAAkB,EAAE;YAC5B;QACF;QAEA,IAAI;QACF,0BAA0B;QAC1B,kCAAkC;QACpC,EAAE,OAAOI,OAAO;YACdF,cAAM,CAACG,IAAI,CAAC,cAAcD;QAC5B;IACF;IAEA;;GAEC,GACD,AAAQK,YAAYC,MAAsE,EAAU;QAClG,IAAI,OAAOA,WAAW,YAAY;YAChC,mBAAmB;YACnB,OAAO,CAAC,GAAG,EAAEA,OAAOC,IAAI,IAAIC,KAAKC,MAAM,GAAGC,QAAQ,CAAC,IAAIC,SAAS,CAAC,IAAI;QACvE;QAEA,wCAAwC;QACxC,sBAAsB;QACtB,IAAI;YACF,MAAMC,YAAYC,KAAKC,SAAS,CAACR,QAAQ,CAACH,MAAMY;gBAC9C,gBAAgB;gBAChB,IAAI,OAAOA,UAAU,YAAY;oBAC/B,OAAO;gBACT;gBACA,OAAOA;YACT;YACA,OAAO,CAAC,OAAO,EAAE,IAAI,CAACC,UAAU,CAACJ,YAAY;QAC/C,EAAE,OAAOZ,OAAO;YACd,gBAAgB;YAChB,OAAO,CAAC,OAAO,EAAEQ,KAAKC,MAAM,GAAGC,QAAQ,CAAC,IAAIC,SAAS,CAAC,IAAI;QAC5D;IACF;IAEA;;GAEC,GACD,AAAQK,WAAWC,GAAW,EAAU;QACtC,IAAIC,OAAO;QACX,IAAK,IAAIC,IAAI,GAAGA,IAAIF,IAAIG,MAAM,EAAED,IAAK;YACnC,MAAME,OAAOJ,IAAIK,UAAU,CAACH;YAC5BD,OAAO,AAACA,CAAAA,QAAQ,CAAA,IAAKA,OAAOG;YAC5BH,OAAOA,OAAOA,MAAM,aAAa;QACnC;QACA,OAAOV,KAAKe,GAAG,CAACL,MAAMR,QAAQ,CAAC;IACjC;IAEA;;GAEC,GACD,AAAQc,UAAUC,IAAwB,EAAW;QACnD,OAAOC,KAAKC,GAAG,KAAKF,KAAKG,SAAS;IACpC;IAEA;;GAEC,GACD,AAAQC,UAAgB;QAEtB,WAAW;QACX,KAAK,MAAM,CAACC,KAAKL,KAAK,IAAI,IAAI,CAACM,KAAK,CAACC,OAAO,GAAI;YAC9C,IAAI,IAAI,CAACR,SAAS,CAACC,OAAO;gBACxB,IAAI,CAACM,KAAK,CAACE,MAAM,CAACH;YACpB;QACF;QAEA,WAAW;QACX,KAAK,MAAM,CAACA,KAAKL,KAAK,IAAI,IAAI,CAACS,UAAU,CAACF,OAAO,GAAI;YACnD,IAAI,IAAI,CAACR,SAAS,CAACC,OAAO;gBACxB,IAAI,CAACS,UAAU,CAACD,MAAM,CAACH;YACzB;QACF;QAEA,4BAA4B;QAC5B,IAAI,CAACK,QAAQ;IACf;IAEA;;GAEC,GACD,AAAQA,WAAiB;QACvB,WAAW;QACX,IAAI,IAAI,CAACJ,KAAK,CAACK,IAAI,GAAG,IAAI,CAACC,MAAM,CAACC,OAAO,EAAE;YACzC,MAAMC,SAASC,MAAMC,IAAI,CAAC,IAAI,CAACV,KAAK,CAACC,OAAO,IAAIU,IAAI,CAClD,CAACC,GAAGC,IAAMD,CAAC,CAAC,EAAE,CAACE,cAAc,GAAGD,CAAC,CAAC,EAAE,CAACC,cAAc;YAErD,MAAMC,WAAWP,OAAOQ,KAAK,CAAC,GAAG,IAAI,CAAChB,KAAK,CAACK,IAAI,GAAG,IAAI,CAACC,MAAM,CAACC,OAAO;YACtEQ,SAASE,OAAO,CAAC,CAAC,CAAClB,IAAI,GAAK,IAAI,CAACC,KAAK,CAACE,MAAM,CAACH;QAChD;QAEA,WAAW;QACX,IAAI,IAAI,CAACI,UAAU,CAACE,IAAI,GAAG,IAAI,CAACC,MAAM,CAACC,OAAO,EAAE;YAC9C,MAAMC,SAASC,MAAMC,IAAI,CAAC,IAAI,CAACP,UAAU,CAACF,OAAO,IAAIU,IAAI,CACvD,CAACC,GAAGC,IAAMD,CAAC,CAAC,EAAE,CAACE,cAAc,GAAGD,CAAC,CAAC,EAAE,CAACC,cAAc;YAErD,MAAMC,WAAWP,OAAOQ,KAAK,CAAC,GAAG,IAAI,CAACb,UAAU,CAACE,IAAI,GAAG,IAAI,CAACC,MAAM,CAACC,OAAO;YAC3EQ,SAASE,OAAO,CAAC,CAAC,CAAClB,IAAI,GAAK,IAAI,CAACI,UAAU,CAACD,MAAM,CAACH;QACrD;IACF;IAEA;;GAEC,GACD,AAAQmB,uBAA6B;QACnC,IAAI,IAAI,CAACC,YAAY,EAAE;YACrBC,cAAc,IAAI,CAACD,YAAY;QACjC;QAEA,iBAAiB;QACjB,IAAI,CAACA,YAAY,GAAGE,YAAY;YAC9B,IAAI,CAACvB,OAAO;QACd,GAAG,KAAK;IACV;IAEA;;GAEC,GACDwB,IAAI/C,MAAsE,EAAgC;QACxG,MAAMwB,MAAM,IAAI,CAACzB,WAAW,CAACC;QAC7B,MAAMmB,OAAO,IAAI,CAACM,KAAK,CAACsB,GAAG,CAACvB;QAE5B,IAAI,CAACL,MAAM;YACT,IAAI,CAAC6B,KAAK,CAACC,eAAe;YAC1B,OAAO;QACT;QAEA,IAAI,IAAI,CAAC/B,SAAS,CAACC,OAAO;YACxB,IAAI,CAACM,KAAK,CAACE,MAAM,CAACH;YAClB,IAAI,CAACwB,KAAK,CAACC,eAAe;YAC1B,OAAO;QACT;QAEA,SAAS;QACT9B,KAAKoB,cAAc,GAAGnB,KAAKC,GAAG;QAC9BF,KAAK+B,WAAW;QAChB,IAAI,CAACF,KAAK,CAACG,aAAa;QAExB,OAAOhC,KAAKV,KAAK;IACnB;IAEA;;GAEC,GACD2C,IACEpD,MAAsE,EACtES,KAA4B,EACtB;QACN,MAAMe,MAAM,IAAI,CAACzB,WAAW,CAACC;QAC7B,MAAMqB,MAAMD,KAAKC,GAAG;QAEpB,MAAMF,OAAyC;YAC7CV;YACAa,WAAWD,MAAM,IAAI,CAACU,MAAM,CAACsB,GAAG;YAChCC,WAAWjC;YACX6B,aAAa;YACbX,gBAAgBlB;QAClB;QAEA,IAAI,CAACI,KAAK,CAAC2B,GAAG,CAAC5B,KAAKL;QAEpB,WAAW;QACX,IAAI,IAAI,CAAC7B,kBAAkB,EAAE;YAC3B,IAAI,CAACM,iBAAiB,CAAC4B,KAAKf,OAAO8C,KAAK,CAAC,CAAC7D;gBACxCF,cAAM,CAACG,IAAI,CAAC,gBAAgBD;YAC9B;QACF;QAEA,WAAW;QACX,IAAI,CAACmC,QAAQ;IACf;IAEA;;GAEC,GACD2B,SAASC,IAAY,EAAkC;QACrD,MAAMtC,OAAO,IAAI,CAACS,UAAU,CAACmB,GAAG,CAACU;QAEjC,IAAI,CAACtC,MAAM;YACT,IAAI,CAAC6B,KAAK,CAACU,WAAW;YACtB,OAAOC;QACT;QAEA,IAAI,IAAI,CAACzC,SAAS,CAACC,OAAO;YACxB,IAAI,CAACS,UAAU,CAACD,MAAM,CAAC8B;YACvB,IAAI,CAACT,KAAK,CAACU,WAAW;YACtB,OAAOC;QACT;QAEA,SAAS;QACTxC,KAAKoB,cAAc,GAAGnB,KAAKC,GAAG;QAC9BF,KAAK+B,WAAW;QAChB,IAAI,CAACF,KAAK,CAACY,SAAS;QAEpB,OAAOzC,KAAKV,KAAK;IACnB;IAEA;;GAEC,GACDoD,SAASJ,IAAY,EAAEK,KAAyB,EAAQ;QACtD,MAAMzC,MAAMD,KAAKC,GAAG;QAEpB,MAAMF,OAAsC;YAC1CV,OAAOqD;YACPxC,WAAWD,MAAM,IAAI,CAACU,MAAM,CAACsB,GAAG;YAChCC,WAAWjC;YACX6B,aAAa;YACbX,gBAAgBlB;QAClB;QAEA,IAAI,CAACO,UAAU,CAACwB,GAAG,CAACK,MAAMtC;QAE1B,WAAW;QACX,IAAI,CAACU,QAAQ;IACf;IAEA;;GAEC,GACDkC,QAAc;QACZ,IAAI,CAACtC,KAAK,CAACsC,KAAK;QAChB,IAAI,CAACnC,UAAU,CAACmC,KAAK;QACrB,IAAI,CAACf,KAAK,GAAG;YACXG,eAAe;YACfF,iBAAiB;YACjBW,WAAW;YACXF,aAAa;QACf;QACAlE,cAAM,CAACC,KAAK,CAAC;IACf;IAEA;;GAEC,GACDuE,UAAgB;QACd,IAAI,CAACD,KAAK;QACV,IAAI,IAAI,CAACnB,YAAY,EAAE;YACrBC,cAAc,IAAI,CAACD,YAAY;YAC/B,IAAI,CAACA,YAAY,GAAG;QACtB;IACF;IAEA;;GAEC,GACDqB,WAKE;QACA,MAAMC,YAAY,IAAI,CAAClB,KAAK,CAACG,aAAa,GAAG,IAAI,CAACH,KAAK,CAACY,SAAS;QACjE,MAAMO,cACJD,YACA,IAAI,CAAClB,KAAK,CAACC,eAAe,GAC1B,IAAI,CAACD,KAAK,CAACU,WAAW;QAExB,MAAMU,UAAUD,cAAc,IAAID,YAAYC,cAAc;QAE5D,OAAO;YACLE,oBAAoB,IAAI,CAAC5C,KAAK,CAACK,IAAI;YACnCwC,gBAAgB,IAAI,CAAC1C,UAAU,CAACE,IAAI;YACpCyC,WAAW,IAAI,CAAC9C,KAAK,CAACK,IAAI,GAAG,IAAI,CAACF,UAAU,CAACE,IAAI;YACjDsC;QACF;IACF;IAhUA,YAAYrC,SAA2B,CAAC,CAAC,CAAE;QAZ3C,uBAAQN,SAAuD,IAAI+C;QACnE,uBAAQ5C,cAAyD,IAAI4C;QACrE,uBAAQzC,UAAR,KAAA;QACA,uBAAQzC,sBAA8B;QACtC,uBAAQsD,gBAAsD;QAC9D,uBAAQI,SAAQ;YACdG,eAAe;YACfF,iBAAiB;YACjBW,WAAW;YACXF,aAAa;QACf;QAGE,IAAI,CAAC3B,MAAM,GAAG;YACZC,SAASD,OAAOC,OAAO,IAAI;YAC3BqB,KAAKtB,OAAOsB,GAAG,IAAI,IAAI,KAAK;YAC5BoB,mBAAmB1C,OAAO0C,iBAAiB,IAAI;YAC/CC,sBAAsB3C,OAAO2C,oBAAoB,IAAI;QACvD;QAEA,WAAW;QACX,IAAI,IAAI,CAAC3C,MAAM,CAAC0C,iBAAiB,IAAI,OAAOpF,WAAW,eAAe,eAAeA,QAAQ;YAC3F,IAAI,CAACD,eAAe;QACtB;QAEA,WAAW;QACX,IAAI,CAACuD,oBAAoB;IAC3B;AAkTF;AAEA;;CAEC,GACD,IAAIgC,qBAAwC;AAErC,SAASxF,cAAc4C,MAAyB;IACrD,IAAI,CAAC4C,oBAAoB;QACvBA,qBAAqB,IAAIzF,WAAW6C;IACtC;IACA,OAAO4C;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/router/performance/RouteCache.ts"],"sourcesContent":["/**\n * 路由缓存管理器\n * 提供路由转换结果、匹配结果的缓存功能\n */\n\nimport { logger } from '../../../utils';\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
|
+
{"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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"}
|
|
@@ -22,7 +22,7 @@ _export(exports, {
|
|
|
22
22
|
return getRoutePreloader;
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
|
-
const
|
|
25
|
+
const _logger = require("@vlian/logger");
|
|
26
26
|
function _define_property(obj, key, value) {
|
|
27
27
|
if (key in obj) {
|
|
28
28
|
Object.defineProperty(obj, key, {
|
|
@@ -172,10 +172,10 @@ let RoutePreloader = class RoutePreloader {
|
|
|
172
172
|
]);
|
|
173
173
|
task.status = 'loaded';
|
|
174
174
|
const duration = Date.now() - (task.startTime || 0);
|
|
175
|
-
|
|
175
|
+
_logger.logger.debug(`路由组件预加载成功: ${task.routeName} (${duration}ms)`);
|
|
176
176
|
} catch (error) {
|
|
177
177
|
task.status = 'failed';
|
|
178
|
-
|
|
178
|
+
_logger.logger.warn(`路由组件预加载失败: ${task.routeName}`, error);
|
|
179
179
|
} finally{
|
|
180
180
|
if (timeoutId) {
|
|
181
181
|
clearTimeout(timeoutId);
|
|
@@ -208,7 +208,7 @@ let RoutePreloader = class RoutePreloader {
|
|
|
208
208
|
if (tasks.length === 0) {
|
|
209
209
|
return;
|
|
210
210
|
}
|
|
211
|
-
|
|
211
|
+
_logger.logger.debug(`开始预加载 ${tasks.length} 个路由组件`);
|
|
212
212
|
// 根据策略决定预加载哪些任务
|
|
213
213
|
let tasksToPreload = [];
|
|
214
214
|
switch(this.config.strategy){
|
|
@@ -231,7 +231,7 @@ let RoutePreloader = class RoutePreloader {
|
|
|
231
231
|
const batch = tasksToPreload.slice(i, i + concurrency);
|
|
232
232
|
await Promise.all(batch.map((task)=>this.preloadTask(task)));
|
|
233
233
|
}
|
|
234
|
-
|
|
234
|
+
_logger.logger.debug('路由组件预加载完成');
|
|
235
235
|
}
|
|
236
236
|
/**
|
|
237
237
|
* 停止预加载
|
|
@@ -251,7 +251,7 @@ let RoutePreloader = class RoutePreloader {
|
|
|
251
251
|
*/ clear() {
|
|
252
252
|
this.tasks.clear();
|
|
253
253
|
this.stopPreload();
|
|
254
|
-
|
|
254
|
+
_logger.logger.debug('路由预加载任务已清空');
|
|
255
255
|
}
|
|
256
256
|
/**
|
|
257
257
|
* 获取预加载统计信息
|