Files
esengine/packages/runtime-core/src/ImportMapGenerator.ts
YHH dbc6793dc4 refactor: 代码规范化与依赖清理 (#317)
* refactor(deps): 统一编辑器包依赖配置 & 优化分层架构

- 将 ecs-engine-bindgen 提升为 Layer 1 核心包
- 统一 9 个编辑器包的依赖声明模式
- 清理废弃的包目录 (ui, ui-editor, network-*)

* refactor(tokens): 修复 PrefabService 令牌冲突 & 补充 module.json

- 将 editor-core 的 PrefabServiceToken 改名为 EditorPrefabServiceToken
  避免与 asset-system 的 PrefabServiceToken 冲突 (Symbol.for 冲突)
- 为 mesh-3d 添加 module.json
- 为 world-streaming 添加 module.json

* refactor(editor-core): 整理导出结构 & 添加 blueprint tokens.ts

- 按功能分组整理 editor-core 的 65 行导出
- 添加清晰的分组注释 (中英双语)
- 为 blueprint 添加占位符 tokens.ts

* chore(editor): 为 14 个编辑器插件包添加 module.json

统一编辑器包的模块配置,包含:
- isEditorPlugin 标识
- runtimeModule 关联
- exports 导出清单 (inspectors, panels, gizmos)

* refactor(core): 改进类型安全 - 减少 as any 使用

- 添加 GlobalTypes.ts 定义小游戏平台和 Chrome API 类型
- SoAStorage 使用 IComponentTypeMetadata 替代 as any
- PlatformDetector 使用类型安全的平台检测
- 添加 ISoAStorageStats/ISoAFieldStats 接口

* feat(editor): 添加 EditorServicesContext 解决 prop drilling

- 新增 contexts/EditorServicesContext.tsx 提供统一服务访问
- App.tsx 包裹 EditorServicesProvider
- 提供 useEditorServices/useMessageHub 等便捷 hooks
- SceneHierarchy 添加迁移注释,后续可移除 props

* docs(editor): 澄清 inspector 目录架构关系

- inspector/ 标记为内部实现,添加 @deprecated 警告
- inspectors/ 标记为公共 API 入口点
- 添加架构说明文档

* refactor(editor): 添加全局类型声明消除 window as any

- 创建 editor-app/src/global.d.ts 声明 Window 接口扩展
- 创建 editor-core/src/global.d.ts 声明 Window 接口扩展
- 更新 App.tsx 使用类型安全的 window 属性访问
- 更新 PluginLoader.ts 使用 window.__ESENGINE_PLUGINS__
- 更新 PluginSDKRegistry.ts 使用 window.__ESENGINE_SDK__
- 更新 UserCodeService.ts 使用类型安全的全局变量访问

* refactor(editor): 提取项目和场景操作到独立 hooks

- 创建 useProjectActions hook 封装项目操作
- 创建 useSceneActions hook 封装场景操作
- 为渐进式重构 App.tsx 做准备

* refactor(editor): 清理冗余代码和未使用文件

删除的目录和文件:
- application/state/ - 重复的状态管理(与 stores/ 重复)
- 8 个孤立 CSS 文件(对应组件不存在)
- AssetBrowser.tsx - 仅为 ContentBrowser 的向后兼容包装
- AssetPicker.tsx - 未被使用
- AssetPickerDialog.tsx (顶级) - 已被 dialogs/ 版本取代
- EntityInspector.tsx (顶级) - 已被 inspectors/views/ 版本取代

修复:
- 移除 App.tsx 中未使用的导入
- 更新 application/index.ts 移除已删除模块
- 修复 useProjectActions.ts 的 MutableRefObject 类型

* refactor(editor): 统一 inspectors 模块导出结构

- 在 inspectors/index.ts 重新导出 PropertyInspector
- 创建 inspectors/fields/index.ts barrel export
- 导出 views、fields、common 子模块
- 更新 EntityInspector 使用统一入口导入

* refactor(editor): 删除废弃的 Profiler 组件

删除未使用的组件(共 1059 行):
- ProfilerPanel.tsx (229 行)
- ProfilerWindow.tsx (589 行)
- ProfilerDockPanel.tsx (241 行)
- ProfilerPanel.css
- ProfilerDockPanel.css

保留:AdvancedProfiler + AdvancedProfilerWindow(正在使用)

* refactor(runtime-core): 统一依赖处理与插件状态管理

- 新增 DependencyUtils 统一拓扑排序和依赖验证
- 新增 PluginState 定义插件生命周期状态机
- 合并 UnifiedPluginLoader 到 PluginLoader
- 清理 index.ts 移除不必要的 Token re-exports
- 新增 RuntimeMode/UserCodeRealm/ImportMapGenerator

* refactor(editor-core): 使用统一的 ImportMapGenerator

- WebBuildPipeline 使用 runtime-core 的 generateImportMap
- UserCodeService 添加 ImportMap 相关接口

* feat(compiler): 增强 esbuild 查找策略

- 支持本地 node_modules、pnpm exec、npx、全局多种来源
- EngineService 使用 RuntimeMode

* refactor(runtime-core): 简化 GameRuntime 代码

- 合并 _disableGameLogicSystems/_enableGameLogicSystems 为 _setGameLogicSystemsEnabled
- 精简本地 Token 定义的注释

* refactor(editor-core): 引入 BaseRegistry 基类消除代码重复

- 新增 BaseRegistry 和 PrioritizedRegistry 基类
- 重构 CompilerRegistry, InspectorRegistry, FieldEditorRegistry
- 统一注册表的日志记录和错误处理

* refactor(editor-core): 扩展 BaseRegistry 重构

- ComponentInspectorRegistry 继承 PrioritizedRegistry
- EditorComponentRegistry 继承 BaseRegistry
- EntityCreationRegistry 继承 BaseRegistry
- PropertyRendererRegistry 继承 PrioritizedRegistry
- 导出 BaseRegistry 基类供外部使用
- 统一双语注释格式

* refactor(editor-core): 代码优雅性优化

CommandManager:
- 提取 tryMergeWithLast() 和 pushToUndoStack() 消除重复代码
- 统一双语注释格式

FileActionRegistry:
- 提取 normalizeExtension() 消除扩展名规范化重复
- 统一私有属性命名风格(_前缀)
- 使用 createRegistryToken 统一 Token 创建

BaseRegistry:
- 添加 IOrdered 接口
- 添加 sortByOrder() 排序辅助方法

EntityCreationRegistry:
- 使用 sortByOrder() 简化排序逻辑

* refactor(editor-core): 统一日志系统 & 代码规范优化

- GizmoRegistry: 使用 createLogger 替代 console.warn
- VirtualNodeRegistry: 使用 createLogger 替代 console.warn
- WindowRegistry: 使用 logger、添加 _ 前缀、导出 IWindowRegistry token
- EditorViewportService: 使用 createLogger 替代 console.warn
- ComponentActionRegistry: 使用 logger、添加 _ 前缀、返回值改进
- SettingsRegistry: 使用 logger、提取 ensureCategory/ensureSection 方法
- 添加 WindowRegistry 到主导出

* refactor(editor-core): ModuleRegistry 使用 logger 替代 console

* refactor(editor-core): SerializerRegistry/UIRegistry 添加 token 和 _ 前缀

* refactor(editor-core): UIRegistry 代码优雅性 & Token 命名统一

- UIRegistry: 提取 _sortByOrder 消除 6 处重复排序逻辑
- UIRegistry: 添加分节注释和双语文档
- FieldEditorRegistry: Token 重命名为 FieldEditorRegistryToken
- PropertyRendererRegistry: Token 重命名为 PropertyRendererRegistryToken

* refactor(core): 统一日志系统 - console 替换为 logger

- ComponentSerializer: 使用 logger 替代 console.warn
- ComponentRegistry: console.warn → logger.warn (已有 logger)
- SceneSerializer: 添加 logger,替换 console.warn/error
- SystemScheduler: 添加 logger,替换 console.warn
- VersionMigration: 添加 logger,替换所有 console.warn
- RuntimeModeService: console.error → logger.error
- Core.ts: _logger 改为 readonly,双语错误消息
- SceneSerializer 修复:使用 getComponentTypeName 替代 constructor.name

* fix(core): 修复 constructor.name 压缩后失效问题

- Scene.ts: 使用 system.systemName 替代 system.constructor.name
- CommandBuffer.ts: 使用 getComponentTypeName() 替代 constructor.name

* refactor(editor-core): 代码规范优化 - 私有方法命名 & 日志统一

- BuildService: console → logger
- FileActionRegistry: 添加 logger, 私有方法 _ 前缀
- SettingsRegistry: 私有方法 _ 前缀 (ensureCategory → _ensureCategory)

* refactor(core): Scene.ts 私有变量命名规范化

- logger → _logger (遵循私有变量 _ 前缀规范)

* refactor(editor-core): 服务类私有成员命名规范化

- CommandManager: 私有变量/方法添加 _ 前缀
  - undoStack/redoStack/config/isExecuting
  - tryMergeWithLast/pushToUndoStack
- LocaleService: 私有变量/方法添加 _ 前缀
  - currentLocale/translations/changeListeners
  - deepMerge/getNestedValue/loadSavedLocale/saveLocale

* refactor(core): 私有成员命名规范化 & 单例模式优化

- Component.ts: _idGenerator 私有静态变量规范化
- PlatformManager.ts: _instance, _adapter, _logger 规范化
- AutoProfiler.ts: _instance, _config 及所有私有方法规范化
- ProfilerSDK.ts: _instance, _config 及所有私有方法规范化
- ComponentPoolManager: _instance, _pools, _usageTracker 规范化
- GlobalEventBus: _instance 规范化
- 添加中英双语 JSDoc 注释

* refactor(editor-app,behavior-tree-editor): 私有成员 & 单例模式命名规范化

editor-app:
- EngineService: private static instance → _instance
- EditorEngineSync: 所有私有成员添加 _ 前缀
- RuntimeResolver: 所有私有成员和方法添加 _ 前缀
- SettingsService: 所有私有成员和方法添加 _ 前缀

behavior-tree-editor:
- GlobalBlackboardService: 所有私有成员和方法添加 _ 前缀
- NotificationService: private static instance → _instance
- NodeRegistryService: 所有私有成员和方法添加 _ 前缀
- TreeStateAdapter: private static instance → _instance

* fix(editor-runtime): 添加 editor-core 到 external 避免传递依赖问题

将 @esengine/editor-core 添加到 vite external 配置,
避免 editor-core → runtime-core → ecs-engine-bindgen 的传递依赖
被错误地打包进 editor-runtime.js,导致 CI 构建失败。

* fix(core): 修复空接口 lint 错误

将 IByteDanceMiniGameAPI、IAlipayMiniGameAPI、IBaiduMiniGameAPI 从空接口改为类型别名,修复 no-empty-object-type 规则报错
2025-12-24 20:57:08 +08:00

248 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @zh ImportMap 生成器
* @en ImportMap Generator
*
* @zh 提供统一的 ImportMap 生成逻辑,供编辑器预览和构建共用
* @en Provides unified ImportMap generation logic for editor preview and build
*/
import type { ModuleManifest } from './PluginManager';
import {
extractShortId,
getPackageName as getPackageNameFromId,
topologicalSort,
type IDependable
} from './utils/DependencyUtils';
/**
* @zh ImportMap 生成模式
* @en ImportMap generation mode
*/
export type ImportMapMode =
| 'development' // 开发模式:每个模块单独文件
| 'production' // 生产模式:核心模块打包,插件分离
| 'single-bundle'; // 单文件模式:所有模块打包到一个文件
/**
* @zh ImportMap 生成配置
* @en ImportMap generation configuration
*/
export interface ImportMapConfig {
/**
* @zh 生成模式
* @en Generation mode
*/
mode: ImportMapMode;
/**
* @zh 基础路径(用于构造相对 URL
* @en Base path (for constructing relative URLs)
*/
basePath?: string;
/**
* @zh 核心模块列表
* @en List of core modules
*/
coreModules: ModuleManifest[];
/**
* @zh 插件模块列表
* @en List of plugin modules
*/
pluginModules?: ModuleManifest[];
/**
* @zh 自定义路径生成器(可选)
* @en Custom path generator (optional)
*/
pathGenerator?: (module: ModuleManifest, isCore: boolean) => string;
}
/**
* @zh ImportMap 条目
* @en ImportMap entry
*/
export interface ImportMapEntry {
/**
* @zh 包名(如 @esengine/ecs-framework
* @en Package name (e.g., @esengine/ecs-framework)
*/
packageName: string;
/**
* @zh 模块路径(相对 URL
* @en Module path (relative URL)
*/
path: string;
/**
* @zh 模块 ID如 core
* @en Module ID (e.g., core)
*/
moduleId: string;
/**
* @zh 是否为核心模块
* @en Whether it's a core module
*/
isCore: boolean;
}
/**
* @zh 生成 ImportMap
* @en Generate ImportMap
*/
export function generateImportMap(config: ImportMapConfig): Record<string, string> {
const imports: Record<string, string> = {};
const basePath = config.basePath || '.';
// 根据模式选择路径生成策略
const getModulePath = config.pathGenerator || ((module: ModuleManifest, isCore: boolean) => {
switch (config.mode) {
case 'development':
// 开发模式:每个模块单独文件
return `${basePath}/libs/${module.id}/${module.id}.js`;
case 'production':
// 生产模式:核心模块打包,插件分离
if (isCore) {
return `${basePath}/libs/esengine.core.js`;
}
return `${basePath}/libs/plugins/${module.id}.js`;
case 'single-bundle':
// 单文件模式:所有模块打包
return `${basePath}/libs/esengine.bundle.js`;
}
});
// 处理核心模块
for (const module of config.coreModules) {
if (module.name) {
imports[module.name] = getModulePath(module, true);
}
}
// 处理插件模块
if (config.pluginModules) {
for (const module of config.pluginModules) {
if (module.name) {
imports[module.name] = getModulePath(module, false);
}
// 处理外部依赖
if (module.externalDependencies) {
for (const dep of module.externalDependencies) {
if (!imports[dep]) {
const depId = extractModuleId(dep);
imports[dep] = `${basePath}/libs/${config.mode === 'development' ? `${depId}/${depId}` : `plugins/${depId}`}.js`;
}
}
}
}
}
return imports;
}
/**
* @zh 生成 ImportMap 条目列表
* @en Generate ImportMap entry list
*/
export function generateImportMapEntries(config: ImportMapConfig): ImportMapEntry[] {
const entries: ImportMapEntry[] = [];
const importMap = generateImportMap(config);
for (const [packageName, path] of Object.entries(importMap)) {
const moduleId = extractModuleId(packageName);
const isCore = config.coreModules.some(m => m.name === packageName);
entries.push({
packageName,
path,
moduleId,
isCore
});
}
return entries;
}
/**
* @zh 生成 ImportMap HTML 脚本标签
* @en Generate ImportMap HTML script tag
*
* @param imports - @zh ImportMap 对象 @en ImportMap object
* @param indent - @zh 缩进空格数 @en Number of indent spaces
*/
export function generateImportMapScript(imports: Record<string, string>, indent = 4): string {
const indentStr = ' '.repeat(indent);
const json = JSON.stringify({ imports }, null, 2)
.split('\n')
.map((line, i) => i === 0 ? line : indentStr + line)
.join('\n');
return `<script type="importmap">
${indentStr}${json}
${indentStr}</script>`;
}
/**
* @zh 从包名提取模块 ID
* @en Extract module ID from package name
*
* @zh 重新导出自 DependencyUtils保持向后兼容
* @en Re-exported from DependencyUtils (for backward compatibility)
*
* @example
* extractModuleId('@esengine/ecs-framework') // 'core'
* extractModuleId('@esengine/sprite') // 'sprite'
*/
export const extractModuleId = extractShortId;
/**
* @zh 从模块 ID 获取包名
* @en Get package name from module ID
*
* @zh 重新导出自 DependencyUtils保持向后兼容
* @en Re-exported from DependencyUtils (for backward compatibility)
*
* @example
* getPackageName('core') // '@esengine/ecs-framework'
* getPackageName('sprite') // '@esengine/sprite'
*/
export const getPackageName = getPackageNameFromId;
/**
* @zh 收集模块的外部依赖
* @en Collect external dependencies of modules
*/
export function collectExternalDependencies(modules: ModuleManifest[]): Set<string> {
const deps = new Set<string>();
for (const module of modules) {
if (module.externalDependencies) {
for (const dep of module.externalDependencies) {
deps.add(dep);
}
}
}
return deps;
}
/**
* @zh 按依赖排序模块(拓扑排序)
* @en Sort modules by dependencies (topological sort)
*
* @zh 使用统一的 DependencyUtils.topologicalSort
* @en Uses unified DependencyUtils.topologicalSort
*/
export function sortModulesByDependencies<T extends IDependable>(
modules: T[]
): T[] {
const result = topologicalSort(modules, { algorithm: 'dfs' });
return result.sorted;
}