Files
esengine/packages/tools/worker-generator/src/cli.ts
YHH 155411e743 refactor: reorganize package structure and decouple framework packages (#338)
* refactor: reorganize package structure and decouple framework packages

## Package Structure Reorganization
- Reorganized 55 packages into categorized subdirectories:
  - packages/framework/ - Generic framework (Laya/Cocos compatible)
  - packages/engine/ - ESEngine core modules
  - packages/rendering/ - Rendering modules (WASM dependent)
  - packages/physics/ - Physics modules
  - packages/streaming/ - World streaming
  - packages/network-ext/ - Network extensions
  - packages/editor/ - Editor framework and plugins
  - packages/rust/ - Rust WASM engine
  - packages/tools/ - Build tools and SDK

## Framework Package Decoupling
- Decoupled behavior-tree and blueprint packages from ESEngine dependencies
- Created abstracted interfaces (IBTAssetManager, IBehaviorTreeAssetContent)
- ESEngine-specific code moved to esengine/ subpath exports
- Framework packages now usable with Cocos/Laya without ESEngine

## CI Configuration
- Updated CI to only type-check and lint framework packages
- Added type-check:framework and lint:framework scripts

## Breaking Changes
- Package import paths changed due to directory reorganization
- ESEngine integrations now use subpath imports (e.g., '@esengine/behavior-tree/esengine')

* fix: update es-engine file path after directory reorganization

* docs: update README to focus on framework over engine

* ci: only build framework packages, remove Rust/WASM dependencies

* fix: remove esengine subpath from behavior-tree and blueprint builds

ESEngine integration code will only be available in full engine builds.
Framework packages are now purely engine-agnostic.

* fix: move network-protocols to framework, build both in CI

* fix: update workflow paths from packages/core to packages/framework/core

* fix: exclude esengine folder from type-check in behavior-tree and blueprint

* fix: update network tsconfig references to new paths

* fix: add test:ci:framework to only test framework packages in CI

* fix: only build core and math npm packages in CI

* fix: exclude test files from CodeQL and fix string escaping security issue
2025-12-26 14:50:35 +08:00

173 lines
6.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
#!/usr/bin/env node
/**
* Worker Generator CLI
* 从 WorkerEntitySystem 子类生成 Worker 文件
* Generate Worker files from WorkerEntitySystem subclasses
*/
import { Command } from 'commander';
import chalk from 'chalk';
import * as path from 'path';
import * as fs from 'fs';
import { parseWorkerSystems } from './parser';
import { generateWorkerFiles } from './generator';
import type { GeneratorConfig } from './types';
const packageJson = require('../package.json');
const program = new Command();
program
.name('esengine-worker-gen')
.description('Generate Worker files from WorkerEntitySystem classes for WeChat Mini Game and other platforms')
.version(packageJson.version);
program
.option('-s, --src <dir>', 'Source directory to scan', './src')
.option('-o, --out <dir>', 'Output directory for Worker files', './workers')
.option('-w, --wechat', 'Generate WeChat Mini Game compatible code', false)
.option('-m, --mapping', 'Generate worker-mapping.json file', true)
.option('-t, --tsconfig <path>', 'Path to tsconfig.json')
.option('-v, --verbose', 'Verbose output', false)
.action((options) => {
run(options);
});
function run(options: {
src: string;
out: string;
wechat: boolean;
mapping: boolean;
tsconfig?: string;
verbose: boolean;
}) {
console.log(chalk.cyan('\n🔧 ESEngine Worker Generator\n'));
// 解析路径
// Resolve paths
const srcDir = path.resolve(process.cwd(), options.src);
const outDir = path.resolve(process.cwd(), options.out);
// 检查源目录是否存在
// Check if source directory exists
if (!fs.existsSync(srcDir)) {
console.error(chalk.red(`Error: Source directory not found: ${srcDir}`));
process.exit(1);
}
// 查找 tsconfig.json
// Find tsconfig.json
let tsConfigPath = options.tsconfig;
if (!tsConfigPath) {
const defaultTsConfig = path.join(process.cwd(), 'tsconfig.json');
if (fs.existsSync(defaultTsConfig)) {
tsConfigPath = defaultTsConfig;
}
}
const config: GeneratorConfig = {
srcDir,
outDir,
wechat: options.wechat,
generateMapping: options.mapping,
tsConfigPath,
verbose: options.verbose,
};
console.log(chalk.gray(`Source directory: ${srcDir}`));
console.log(chalk.gray(`Output directory: ${outDir}`));
console.log(chalk.gray(`WeChat mode: ${options.wechat ? 'Yes' : 'No'}`));
if (tsConfigPath) {
console.log(chalk.gray(`TypeScript config: ${tsConfigPath}`));
}
console.log();
// 解析源文件
// Parse source files
console.log(chalk.yellow('Scanning for WorkerEntitySystem classes...'));
const systems = parseWorkerSystems(config);
if (systems.length === 0) {
console.log(chalk.yellow('\n⚠ No WorkerEntitySystem subclasses found.'));
console.log(chalk.gray('Make sure your classes:'));
console.log(chalk.gray(' - Extend WorkerEntitySystem'));
console.log(chalk.gray(' - Have a workerProcess method'));
console.log(chalk.gray(' - Are in .ts files under the source directory'));
return;
}
console.log(chalk.green(`\n✓ Found ${systems.length} WorkerEntitySystem class(es):`));
for (const system of systems) {
const configStatus = system.workerScriptPath
? chalk.green(`✓ workerScriptPath: '${system.workerScriptPath}'`)
: chalk.yellow('⚠ No workerScriptPath configured');
console.log(chalk.gray(` - ${system.className}`));
console.log(chalk.gray(` ${path.relative(process.cwd(), system.filePath)}`));
console.log(` ${configStatus}`);
}
console.log();
// 生成 Worker 文件
// Generate Worker files
console.log(chalk.yellow('Generating Worker files...'));
const result = generateWorkerFiles(systems, config);
// 输出结果
// Output results
console.log();
if (result.success.length > 0) {
console.log(chalk.green(`✓ Successfully generated ${result.success.length} Worker file(s):`));
for (const item of result.success) {
const relativePath = path.relative(process.cwd(), item.outputPath).replace(/\\/g, '/');
if (item.configuredPath) {
console.log(chalk.green(`${item.className} -> ${relativePath}`));
} else {
console.log(chalk.yellow(`${item.className} -> ${relativePath} (需要配置 workerScriptPath)`));
}
}
}
if (result.errors.length > 0) {
console.log(chalk.red(`\n✗ Failed to generate ${result.errors.length} Worker file(s):`));
for (const item of result.errors) {
console.log(chalk.red(` - ${item.className}: ${item.error}`));
}
}
// 提示未配置 workerScriptPath 的类
// Remind about classes without workerScriptPath
if (result.skipped.length > 0) {
console.log(chalk.yellow('\n⚠ 以下类未配置 workerScriptPath请在构造函数中添加配置:'));
console.log(chalk.yellow(' The following classes need workerScriptPath configuration:\n'));
for (const item of result.skipped) {
console.log(chalk.white(` // ${item.className}`));
console.log(chalk.cyan(` super(matcher, {`));
console.log(chalk.cyan(` workerScriptPath: '${item.suggestedPath}',`));
console.log(chalk.cyan(` // ... 其他配置`));
console.log(chalk.cyan(` });`));
console.log();
}
}
// 使用提示(只有当有已配置路径的成功项时)
// Usage tips (only when there are success items with configured path)
const configuredSuccess = result.success.filter(item => item.configuredPath);
if (configuredSuccess.length > 0) {
console.log(chalk.green('\n✅ 已按照代码中的 workerScriptPath 配置生成 Worker 文件!'));
console.log(chalk.gray(' Worker files generated according to workerScriptPath in your code!'));
console.log(chalk.gray('\n 下一步 | Next steps:'));
console.log(chalk.gray(' 1. 确保 game.json 配置了 workers 目录'));
console.log(chalk.gray(' Ensure game.json has workers directory configured'));
if (options.mapping) {
console.log(chalk.gray('\n 已生成映射文件 | Mapping file generated:'));
console.log(chalk.white(` import mapping from '${path.relative(process.cwd(), outDir)}/worker-mapping.json'`));
}
}
console.log();
}
program.parse();