💄 style(rn): Update rn

This commit is contained in:
Tsuki
2025-10-13 19:43:17 +08:00
parent 3f86bce340
commit d2968b2a1a
7 changed files with 445 additions and 25 deletions
@@ -42,9 +42,11 @@ import Inflection from '../icons/Inflection';
import InternLM from '../icons/InternLM';
import Jina from '../icons/Jina';
import Kolors from '../icons/Kolors';
import Kwaipilot from '../icons/Kwaipilot';
import LG from '../icons/LG';
import LLaVA from '../icons/LLaVA';
import Liquid from '../icons/Liquid';
import LongCat from '../icons/LongCat';
import Menlo from '../icons/Menlo';
import Meta from '../icons/Meta';
import Microsoft from '../icons/Microsoft';
@@ -53,7 +55,6 @@ import Mistral from '../icons/Mistral';
import Moonshot from '../icons/Moonshot';
import NousResearch from '../icons/NousResearch';
import Nvidia from '../icons/Nvidia';
// Import React Native icon components
import OpenAI from '../icons/OpenAI';
import OpenChat from '../icons/OpenChat';
import OpenRouter from '../icons/OpenRouter';
@@ -65,6 +66,7 @@ import Qwen from '../icons/Qwen';
import Rwkv from '../icons/Rwkv';
import SenseNova from '../icons/SenseNova';
import Skywork from '../icons/Skywork';
import Sora from '../icons/Sora';
import Spark from '../icons/Spark';
import Stability from '../icons/Stability';
import Stepfun from '../icons/Stepfun';
@@ -101,6 +103,7 @@ export const rnModelMappings: RNModelMapping[] = [
{ Icon: OpenAI, keywords: ['gpt-3'], props: { type: 'gpt3' } },
{ Icon: OpenAI, keywords: ['gpt-4'], props: { type: 'gpt4' } },
{ Icon: OpenAI, keywords: ['gpt-5'], props: { type: 'gpt5' } },
{ Icon: Sora, keywords: ['sora'] },
{ Icon: OpenAI, keywords: ['gpt-oss'], props: { type: 'oss' } },
{
Icon: OpenAI,
@@ -147,7 +150,7 @@ export const rnModelMappings: RNModelMapping[] = [
{ Icon: Gemma, keywords: ['gemma'] },
{ Icon: Moonshot, keywords: ['kimi', 'moonshot'] },
{ Icon: Qiniu, keywords: ['qiniu'] },
{ Icon: Qwen, keywords: ['qwen', 'qwq', 'qvq', 'wanx', 'wan\\d/', 'wan\\d\\.\\d-'] },
{ Icon: Qwen, keywords: ['qwen', 'qwq', 'qvq', 'wanx', 'wan\\d/', 'wan\\d\\.\\d-', 'tongyi'] },
{ Icon: Minimax, keywords: ['minimax', 'abab', '^image-'] },
{
Icon: Mistral,
@@ -181,7 +184,7 @@ export const rnModelMappings: RNModelMapping[] = [
{ Icon: Doubao, keywords: ['^ep-', 'doubao-', 'seedream', 'seededit'] },
{ Icon: Hunyuan, keywords: ['hunyuan'] },
{ Icon: FishAudio, keywords: ['^d_', '^g_', '^wd_'] },
{ Icon: ByteDance, keywords: ['skylark'] },
{ Icon: ByteDance, keywords: ['skylark', 'seed-', 'bytedance'] },
{ Icon: BurnCloud, keywords: ['burncloud'] },
{
Icon: Stability,
@@ -199,7 +202,7 @@ export const rnModelMappings: RNModelMapping[] = [
},
{ Icon: Flux, keywords: ['flux'] },
{ Icon: Suno, keywords: ['suno'] },
{ Icon: Microsoft, keywords: ['wizardlm', '/phi-', '^phi-', '-phi-'] },
{ Icon: Microsoft, keywords: ['wizardlm', '/phi-', '^phi-', '-phi-', 'mai-', 'microsoft'] },
{ Icon: Adobe, keywords: ['firefly'] },
{ Icon: Ai21, keywords: ['jamba', '^j2-', 'ai21'] },
{ Icon: Upstage, keywords: ['^solar-', '/solar'] },
@@ -244,4 +247,6 @@ export const rnModelMappings: RNModelMapping[] = [
{ Icon: LG, keywords: ['kmmlu', 'exaone', 'lgai'] },
{ Icon: TII, keywords: ['falcon'] },
{ Icon: Menlo, keywords: ['menlo', 'lucy', 'jan-nano'] },
{ Icon: LongCat, keywords: ['longcat'] },
{ Icon: Kwaipilot, keywords: ['kat-'] },
];
@@ -1,6 +1,5 @@
import { FC, memo } from 'react';
// Import React Native icon components
import Ai21 from '../icons/Ai21';
import Ai302 from '../icons/Ai302';
import Ai360 from '../icons/Ai360';
@@ -17,6 +16,7 @@ import BaiduCloud from '../icons/BaiduCloud';
import Bedrock from '../icons/Bedrock';
import Bfl from '../icons/Bfl';
import BurnCloud from '../icons/BurnCloud';
import Cerebras from '../icons/Cerebras';
import Claude from '../icons/Claude';
import Cloudflare from '../icons/Cloudflare';
import Cohere from '../icons/Cohere';
@@ -39,6 +39,7 @@ import InternLM from '../icons/InternLM';
import Jina from '../icons/Jina';
import LmStudio from '../icons/LmStudio';
import LobeHub from '../icons/LobeHub';
import LongCat from '../icons/LongCat';
import Minimax from '../icons/Minimax';
import Mistral from '../icons/Mistral';
import ModelScope from '../icons/ModelScope';
@@ -62,6 +63,7 @@ import SiliconCloud from '../icons/SiliconCloud';
import SophNet from '../icons/SophNet';
import Spark from '../icons/Spark';
import Stepfun from '../icons/Stepfun';
import Straico from '../icons/Straico';
import TencentCloud from '../icons/TencentCloud';
import Together from '../icons/Together';
import Upstage from '../icons/Upstage';
@@ -98,7 +100,7 @@ export interface RNProviderMapping {
}
export const rnProviderMappings: RNProviderMapping[] = [
{ Icon: LobeHub, keywords: [RNModelProvider.LobeHub] },
{ Icon: LobeHub, combineMultiple: 1.1, keywords: [RNModelProvider.LobeHub] },
{ Icon: Zhipu, combineMultiple: 1.25, keywords: [RNModelProvider.ZhiPu] },
{
Combine: memo(({ size = 24, type = 'color', ...props }) => (
@@ -261,9 +263,31 @@ export const rnProviderMappings: RNProviderMapping[] = [
Icon: Vercel,
keywords: [RNModelProvider.V0],
},
{ Icon: Vercel, combineMultiple: 0.9, keywords: [RNModelProvider.Vercel] },
{ Icon: Bfl, keywords: [RNModelProvider.Bfl] },
{ Icon: Nebius, combineMultiple: 0.75, keywords: [RNModelProvider.Nebius] },
{ Icon: NewAPI, combineMultiple: 0.85, keywords: [RNModelProvider.NewAPI] },
{ Icon: AkashChat, combineMultiple: 0.8, keywords: [RNModelProvider.AkashChat] },
{ Icon: SophNet, combineMultiple: 0.85, keywords: [RNModelProvider.SophNet] },
{
Combine: memo(({ size = 24, ...props }) => (
<Combine
left={
<Ollama.Combine
extra={'Cloud'}
extraStyle={{ fontSize: 21, fontWeight: 500, marginLeft: 3 }}
size={size * 1.16}
/>
}
right={<Ollama.Combine size={0} />}
size={size}
{...props}
/>
)),
Icon: Ollama,
keywords: [RNModelProvider.OllamaCloud],
},
{ Icon: LongCat, combineMultiple: 1, keywords: [RNModelProvider.LongCat] },
{ Icon: Cerebras, combineMultiple: 1, keywords: [RNModelProvider.Cerebras] },
{ Icon: Straico, combineMultiple: 1, keywords: [RNModelProvider.Straico] },
];
@@ -11,6 +11,7 @@ export enum RNModelProvider {
Bedrock = 'bedrock',
Bfl = 'bfl',
BurnCloud = 'burncloud',
Cerebras = 'cerebras',
Cloudflare = 'cloudflare',
Cohere = 'cohere',
CometAPI = 'cometapi',
@@ -31,6 +32,7 @@ export enum RNModelProvider {
Jina = 'jina',
LmStudio = 'lmstudio',
LobeHub = 'lobehub',
LongCat = 'longcat',
Minimax = 'minimax',
Mistral = 'mistral',
ModelScope = 'modelscope',
@@ -40,6 +42,7 @@ export enum RNModelProvider {
Novita = 'novita',
Nvidia = 'nvidia',
Ollama = 'ollama',
OllamaCloud = 'ollamacloud',
OpenAI = 'openai',
OpenRouter = 'openrouter',
PPIO = 'ppio',
@@ -54,12 +57,14 @@ export enum RNModelProvider {
SophNet = 'sophnet',
Spark = 'spark',
Stepfun = 'stepfun',
Straico = 'straico',
Taichu = 'taichu',
TencentCloud = 'tencentcloud',
TogetherAI = 'togetherai',
Upstage = 'upstage',
V0 = 'v0',
VLLM = 'vllm',
Vercel = 'vercelaigateway',
VertexAI = 'vertexai',
Volcengine = 'volcengine',
Wenxin = 'wenxin',
+2 -2
View File
@@ -1,5 +1,5 @@
import type { ComponentType } from 'react';
import type { ViewStyle } from 'react-native';
import type { TextStyle, ViewStyle } from 'react-native';
export interface RNIconProps {
color?: string;
@@ -28,7 +28,7 @@ export interface RNIconCombineProps extends RNIconProps {
Text?: ComponentType<RNIconProps>;
color?: string;
extra?: string;
extraStyle?: ViewStyle;
extraStyle?: ViewStyle & TextStyle;
iconProps?: Partial<RNIconAvatarProps>;
inverse?: boolean;
showLogo?: boolean;
+77 -17
View File
@@ -7,8 +7,9 @@
1. 🔍 **智能检测** - 自动对比 `/src` 和 `/packages/react-native/src/icons` 目录,识别未转换的 Web 图标
2. 🚀 **批量转换** - 调用 `batch-converter.ts` 完成图标转换
3. 📦 **更新导出** - 调用 `export-updater.ts` 更新主导出文件
4. 🔧 **代码检查** - 可选的运行 lint 检查验证代码质量
5. 🧪 **构建测试** - 可选的运行构建测试验证转换结果
4. 🔄 **同步配置** - 调用 `feature-config-syncer.ts` 同步特性配置文件(modelConfig、providerEnum、providerConfig)
5. 🔧 **代码检查** - 可选的运行 lint 检查验证代码质量
6. 🧪 **构建测试** - 可选的运行构建测试验证转换结果
这个脚本整合了现有的转换工具,提供一站式的转换解决方案。
@@ -84,20 +85,23 @@ graph TD
F --> G{转换成功?}
G -->|否| H[显示失败统计]
G -->|是| I[更新导出文件]
I --> J{启用代码检查?}
J -->|否| K{启用构建测试?}
J -->|是| L[运行代码检查]
L --> M{代码检查通过?}
M -->|否| H
M -->|是| K
K -->|否| N[显示成功统计]
K -->|是| O[运行构建测试]
O --> P{构建测试通过?}
P -->|否| H
P -->|是| N
H --> Q[结束]
N --> Q
D --> Q
I --> J[同步特性配置文件]
J --> K{同步成功?}
K -->|否| H
K -->|是| L{启用代码检查?}
L -->|否| M{启用构建测试?}
L -->|是| N[运行代码检查]
N --> O{代码检查通过?}
O -->|否| H
O -->|是| M
M -->|否| P[显示成功统计]
M -->|是| Q[运行构建测试]
Q --> R{构建测试通过?}
R -->|否| H
R -->|是| P
H --> S[结束]
P --> S
D --> S
```
## 输出说明
@@ -108,6 +112,7 @@ graph TD
- 📝 **待转换列表** - 显示所有需要转换的图标名称
- 🚀 **转换进度** - 实时显示转换过程
- 📦 **导出更新** - 更新主导出文件状态
- 🔄 **配置同步** - 同步特性配置文件(modelConfig、providerEnum、providerConfig)
- 🔧 **代码检查** - 代码质量检查结果(如果启用)
- 🧪 **构建测试** - 构建测试结果(如果启用)
- 📊 **最终统计** - 成功 / 失败 / 跳过的详细数量
@@ -118,14 +123,16 @@ graph TD
auto-converter.ts (主脚本)
├── batch-converter.ts (批量转换)
├── export-updater.ts (导出更新)
├── feature-config-syncer.ts (配置同步)
├── test-runner.ts (测试运行器)
└── utils/file-converter.ts (文件转换器)
```
- **auto-converter.ts** - 主要的一站式脚本
- **batch-converter.ts** - 专门的批量转换工具
- **test-runner.ts** - 专门的测试运行器
- **export-updater.ts** - 专门的导出更新工具
- **feature-config-syncer.ts** - 专门的特性配置文件同步工具
- **test-runner.ts** - 专门的测试运行器
## 错误处理
@@ -143,9 +150,62 @@ auto-converter.ts (主脚本)
- 🚀 预演模式快速预览转换计划
- 🚀 详细的进度显示和时间统计
## 配置文件同步
### 同步的配置文件
脚本会自动同步以下三个特性配置文件:
1. **modelConfig.ts** - 模型图标映射配置
2. **providerEnum.ts** - 提供商枚举定义
3. **providerConfig.tsx** - 提供商图标映射配置
### 转换规则
配置文件从 Web 版本转换到 React Native 版本时,会自动应用以下转换:
#### 1. 导入路径转换
- `@/IconName` → `../icons/IconName`
- `@/features/IconAvatar` → `./IconAvatar`
- `@/types` → `./types`
#### 2. 类型名称转换
- `ModelProvider` → `RNModelProvider`
- `ModelMapping` → `RNModelMapping`
- `ProviderMapping` → `RNProviderMapping`
- `ModelProviderKey` → `RNModelProviderKey`
#### 3. 类型导入转换
- `IconType` → `RNIconProps`
- `IconAvatarProps` → `RNIconAvatarProps`
- `IconCombineProps` → `RNIconCombineProps`
#### 4. 导出变量名转换
- `modelMappings` → `rnModelMappings`
- `providerMappings` → `rnProviderMappings`
#### 5. 特殊处理
- 移除 `@lobehub/ui` 的 `DivProps` 导入
- 移除 `DivProps` 类型引用
### 独立使用
配置同步器也可以独立运行:
```bash
# 独立运行配置同步
npx tsx feature-config-syncer.ts
```
## 注意事项
1. **权限** - 确保对项目目录有读写权限
2. **依赖** - 需要安装所有相关的 npm 依赖
3. **备份** - 建议在大规模转换前备份项目
4. **测试** - 使用 `--dry-run` 和 `--max` 选项进行小规模测试
5. **配置同步** - 配置文件会在每次运行时自动同步,确保 Web 和 RN 版本保持一致
+23
View File
@@ -4,6 +4,8 @@ import { existsSync, readdirSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import FeatureConfigSyncer from './feature-config-syncer';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
@@ -196,6 +198,23 @@ class AutoConverter {
}
}
// 同步特性配置文件
private async syncFeatureConfigs(options: ConversionOptions): Promise<boolean> {
if (options.dryRun) {
console.log('\n🔄 预演模式:不会实际同步配置文件');
return true;
}
try {
const syncer = new FeatureConfigSyncer();
const success = await syncer.syncAll();
return success;
} catch (error) {
console.error('❌ 配置文件同步失败:', error);
return false;
}
}
// 运行构建测试
private async runBuildTest(options: ConversionOptions): Promise<boolean> {
if (!options.buildTest) {
@@ -305,6 +324,10 @@ class AutoConverter {
success = await this.updateExports(options);
}
if (success) {
success = await this.syncFeatureConfigs(options);
}
if (success && options.lintCheck) {
success = await this.runLintCheck(options);
}
@@ -0,0 +1,303 @@
#!/usr/bin/env npx tsx
import { execSync } from 'node:child_process';
import { promises as fs } from 'node:fs';
import path from 'node:path';
/**
* 特性配置文件同步器
* 将 web 版本的配置文件转换为 React Native 版本
*/
interface ConfigFile {
name: string;
sourceFile: string;
targetFile: string;
}
class FeatureConfigSyncer {
private projectRoot: string;
private configFiles: ConfigFile[];
constructor() {
this.projectRoot = path.resolve(__dirname, '../../');
this.configFiles = [
{
name: 'modelConfig.ts',
sourceFile: path.join(this.projectRoot, 'src/features/modelConfig.ts'),
targetFile: path.join(
this.projectRoot,
'packages/react-native/src/features/modelConfig.ts',
),
},
{
name: 'providerEnum.ts',
sourceFile: path.join(this.projectRoot, 'src/features/providerEnum.ts'),
targetFile: path.join(
this.projectRoot,
'packages/react-native/src/features/providerEnum.ts',
),
},
{
name: 'providerConfig.tsx',
sourceFile: path.join(this.projectRoot, 'src/features/providerConfig.tsx'),
targetFile: path.join(
this.projectRoot,
'packages/react-native/src/features/providerConfig.tsx',
),
},
];
}
/**
* 转换配置文件内容
*/
private transformContent(content: string, fileName: string): string {
let transformed = content;
// 1. 转换导入路径:@/IconName → ../icons/IconName
transformed = transformed.replaceAll(/from '@\/([A-Z][\dA-Za-z]*)'/g, "from '../icons/$1'");
// 2. 转换类型名称
// ModelProvider → RNModelProvider (枚举定义)
transformed = transformed.replaceAll(
/export enum ModelProvider\s*{/g,
'export enum RNModelProvider {',
);
// ModelProviderKey → RNModelProviderKey (类型定义)
transformed = transformed.replaceAll(
/export type ModelProviderKey\s*=/g,
'export type RNModelProviderKey =',
);
// ModelMapping → RNModelMapping (接口和类型)
transformed = transformed.replaceAll(/\bModelMapping\b/g, 'RNModelMapping');
// ProviderMapping → RNProviderMapping (接口和类型)
transformed = transformed.replaceAll(/\bProviderMapping\b/g, 'RNProviderMapping');
// ModelProvider 引用 → RNModelProvider (在使用的地方)
// 处理 typeof ModelProvider 的情况
transformed = transformed.replaceAll('typeof ModelProvider', 'typeof RNModelProvider');
// 处理 ModelProvider. 的情况
transformed = transformed.replaceAll(/\bModelProvider\./g, 'RNModelProvider.');
// 处理导入的情况
transformed = transformed.replaceAll('{ ModelProvider }', '{ RNModelProvider }');
transformed = transformed.replaceAll("from './providerEnum'", "from './providerEnum'");
// 3. 转换类型导入和使用
// IconType → RNIconProps
transformed = transformed.replaceAll(/\bIconType\b/g, 'RNIconProps');
// IconAvatarProps → RNIconAvatarProps
transformed = transformed.replaceAll(/\bIconAvatarProps\b/g, 'RNIconAvatarProps');
// IconCombineProps → RNIconCombineProps
transformed = transformed.replaceAll(/\bIconCombineProps\b/g, 'RNIconCombineProps');
// 确保类型名称带有 RN 前缀
if (fileName === 'modelConfig.ts') {
// ModelIconType → RNModelIconType
transformed = transformed.replaceAll('type ModelIconType = ', 'type RNModelIconType = ');
transformed = transformed.replaceAll('Icon: ModelIconType;', 'Icon: RNModelIconType;');
}
if (fileName === 'providerConfig.tsx') {
// ProviderIconType → RNProviderIconType
transformed = transformed.replaceAll(
'type ProviderIconType = ',
'type RNProviderIconType = ',
);
transformed = transformed.replaceAll('Icon: ProviderIconType;', 'Icon: RNProviderIconType;');
}
// 4. 转换导出变量名
transformed = transformed.replaceAll(
'export const modelMappings:',
'export const rnModelMappings:',
);
transformed = transformed.replaceAll(
'export const providerMappings:',
'export const rnProviderMappings:',
);
// 5. 特殊导入处理
// 移除 @lobehub/ui 的 DivProps 导入
transformed = transformed.replaceAll(
/import\s*{\s*DivProps\s*}\s*from\s*'@lobehub\/ui';\s*\n/g,
'',
);
// 移除 DivProps 类型引用
transformed = transformed.replaceAll(/\bDivProps\s*&\s*/g, '');
// 调整类型导入路径
transformed = transformed.replaceAll("from '@/features/IconAvatar'", "from './IconAvatar'");
transformed = transformed.replaceAll("from '@/features/IconCombine'", "from './IconCombine'");
transformed = transformed.replaceAll("from '@/types'", "from './types'");
// 处理特殊的导入语句
if (fileName === 'modelConfig.ts') {
// 添加 React Native 特有的注释
transformed = transformed.replaceAll(
"import { FC } from 'react';",
"import { FC } from 'react';\n",
);
} else if (fileName === 'providerConfig.tsx') {
// 移除 memo 导入中的多余部分
transformed = transformed.replaceAll(
/import\s*{\s*FC,\s*memo\s*}\s*from\s*'react';/g,
"import { FC, memo } from 'react';",
);
}
// 6. 修复特定的导入语句格式
// 处理 Kwaipilot 的特殊导入 - 从 @/icons 改为直接导入
transformed = transformed.replaceAll(
"import { Kwaipilot } from '@/icons';",
"import Kwaipilot from '../icons/Kwaipilot';",
);
// 移除转换后多余的类型导入行
// 这些在步骤5的路径转换后会变成 './IconAvatar' 和 './IconCombine'
transformed = transformed.replaceAll(
"import type { RNIconAvatarProps } from './IconAvatar';\n",
'',
);
transformed = transformed.replaceAll(
"import type { RNIconCombineProps } from './IconCombine';\n",
'',
);
transformed = transformed.replaceAll("import type { RNIconProps } from './types';\n", '');
// 7. 统一添加类型导入
if (fileName === 'modelConfig.ts') {
// 在 Kwaipilot 导入后添加统一的类型导入
transformed = transformed.replaceAll(
"import Kwaipilot from '../icons/Kwaipilot';",
"import Kwaipilot from '../icons/Kwaipilot';\nimport type { RNIconAvatarProps, RNIconCombineProps, RNIconProps } from './types';",
);
} else if (fileName === 'providerConfig.tsx') {
// 在 Combine 导入之前添加统一的类型导入
transformed = transformed.replaceAll(
"import Combine from './ProviderCombine/Combine';",
"import type { RNIconAvatarProps, RNIconCombineProps, RNIconProps } from './types';\nimport Combine from './ProviderCombine/Combine';",
);
}
return transformed;
}
/**
* 同步单个配置文件
*/
private async syncFile(config: ConfigFile): Promise<boolean> {
try {
console.log(`📝 同步 ${config.name}...`);
// 读取源文件
const content = await fs.readFile(config.sourceFile, 'utf8');
// 转换内容
const transformed = this.transformContent(content, config.name);
// 写入目标文件
await fs.writeFile(config.targetFile, transformed, 'utf8');
console.log(`✅ ${config.name} 同步完成`);
return true;
} catch (error) {
console.error(`❌ ${config.name} 同步失败:`, error);
return false;
}
}
/**
* 格式化生成的文件
*/
private async formatFiles(): Promise<boolean> {
try {
console.log('\n🎨 格式化生成的文件...');
const targetFiles = this.configFiles.map((config) => config.targetFile);
// 使用 prettier 格式化
try {
execSync(`npx prettier --write ${targetFiles.join(' ')}`, {
cwd: this.projectRoot,
encoding: 'utf8',
stdio: 'pipe',
});
console.log('✅ Prettier 格式化完成');
} catch {
console.log('⚠️ Prettier 格式化失败,尝试使用 ESLint...');
}
// 使用 eslint 修复
try {
const featuresDir = path.join(this.projectRoot, 'packages/react-native/src/features');
execSync(`npx eslint "${featuresDir}/*.{ts,tsx}" --fix`, {
cwd: this.projectRoot,
encoding: 'utf8',
stdio: 'pipe',
});
console.log('✅ ESLint 修复完成');
} catch {
console.log('⚠️ ESLint 修复跳过');
}
return true;
} catch (error) {
console.error('❌ 格式化失败:', error);
return false;
}
}
/**
* 同步所有配置文件
*/
async syncAll(options: { format?: boolean } = {}): Promise<boolean> {
console.log('\n🔄 开始同步特性配置文件...\n');
const results = await Promise.all(this.configFiles.map((config) => this.syncFile(config)));
const allSuccess = results.every(Boolean);
if (allSuccess) {
console.log('\n✅ 所有配置文件同步完成');
// 格式化生成的文件
if (options.format !== false) {
await this.formatFiles();
}
} else {
console.log('\n❌ 部分配置文件同步失败');
}
return allSuccess;
}
}
// 主函数
async function main() {
try {
const syncer = new FeatureConfigSyncer();
const success = await syncer.syncAll();
process.exit(success ? 0 : 1);
} catch (error) {
console.error('💥 执行失败:', error);
process.exit(1);
}
}
// 如果直接运行此脚本
if (require.main === module) {
// eslint-disable-next-line unicorn/prefer-top-level-await
main().catch((error) => {
console.error('❌ 主函数执行失败:', error);
process.exit(1);
});
}
// 导出类供其他脚本使用
export default FeatureConfigSyncer;