Files
fullex f6c74a40d1 chore(data-classify): retire non-generate scripts and commands
The data-classification extract/validate/check workflow has completed its
staged mission; only the code-generation pipeline remains in use.

- package.json: replace extract/validate/validate:gen/check:duplicates/all
  with an echo notice; keep generate and generate:* intact
- rename the four retired scripts with a DO-NOT-USE- prefix (git mv)
- README: document the deprecation via a global notice, a status column on
  the command table, renamed file references, and historical-section markers
2026-06-16 05:15:47 -07:00

837 lines
33 KiB
Markdown
Raw Permalink 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.
# 数据分类与代码生成工具
Cherry Studio 数据重构项目的自动化工具集,用于管理数据分类和生成 TypeScript 代码。
**版本**: 2.0.0
**更新日期**: 2025-11-28
> ⚠️ **阶段性使命已完成(重要)**
>
> 本工具中仅 **代码生成generate** 流水线仍在使用。数据提取、一致性/生成校验、重复键检查等命令与脚本已完成阶段性使命,**不再支持,请勿再次运行**。
>
> | 仍可用 | 已弃用(不再支持) |
> | --- | --- |
> | `npm run generate`、`generate:preferences`、`generate:boot-config`、`generate:migration` | `npm run extract`、`validate`、`validate:gen`、`check:duplicates`、`all` |
>
> 对应脚本文件已加 `DO-NOT-USE-` 前缀(`DO-NOT-USE-extract-inventory.js`、`DO-NOT-USE-validate-consistency.js`、`DO-NOT-USE-validate-generation.js`、`DO-NOT-USE-check-duplicates.js`);运行已弃用的 npm 命令只会打印一行提示。下文中保留的相关章节仅作历史记录,如有疑问请询问作者。
## 概述
本工具集提供以下功能:
- **数据提取**: 扫描源代码,构建数据清单
- **分类管理**: 维护分类映射,支持增量更新
- **代码生成**: 生成 TypeScript 接口和迁移映射
- **验证检查**: 确保清单与分类之间的一致性
## 目录结构
```
v2-refactor-temp/tools/data-classify/
├── scripts/
│ ├── lib/
│ │ └── classificationUtils.js # 共享工具函数(仅被下方已弃用脚本使用)
│ ├── generate-all.js # 运行所有生成器
│ ├── generate-preferences.js # 生成 preferenceSchemas.ts
│ ├── generate-boot-config.js # 生成 bootConfigSchemas.ts
│ ├── generate-migration.js # 生成 PreferencesMappings.ts + BootConfigMappings.ts
│ ├── DO-NOT-USE-extract-inventory.js # [已弃用] 从源码提取数据清单
│ ├── DO-NOT-USE-validate-consistency.js # [已弃用] 验证数据一致性
│ ├── DO-NOT-USE-validate-generation.js # [已弃用] 验证生成代码质量
│ └── DO-NOT-USE-check-duplicates.js # [已弃用] 检查重复的目标键
├── data/
│ ├── classification.json # 分类映射(自动生成,人工维护)
│ ├── inventory.json # 数据清单(脚本生成)
│ └── target-key-definitions.json # 复杂映射的 target key 定义(人工维护)
├── package.json
└── README.md # 本文档
```
## 快速开始
```bash
# 进入工具目录
cd v2-refactor-temp/tools/data-classify
# 安装依赖
npm install
# 生成所有代码(当前唯一仍受支持的流程)
npm run generate
# 或仅生成单一目标
npm run generate:preferences # 仅生成 preferenceSchemas.ts
npm run generate:boot-config # 仅生成 bootConfigSchemas.ts
npm run generate:migration # 仅生成 PreferencesMappings.ts + BootConfigMappings.ts
```
> `extract` / `validate` / `validate:gen` / `check:duplicates` / `all` 已弃用,不再支持,详见顶部说明。
## 可用脚本
| 脚本 | 说明 | 状态 |
| ------------------------------ | ------------------------------------------------ | ----------- |
| `npm run generate` | 运行所有代码生成器 | ✅ 可用 |
| `npm run generate:preferences` | 仅生成 preferenceSchemas.ts | ✅ 可用 |
| `npm run generate:boot-config` | 仅生成 bootConfigSchemas.ts | ✅ 可用 |
| `npm run generate:migration` | 仅生成 PreferencesMappings.ts + BootConfigMappings.ts | ✅ 可用 |
| `npm run extract` | 从源文件提取数据清单 | ⛔ 已弃用 |
| `npm run validate` | 验证数据一致性 | ⛔ 已弃用 |
| `npm run validate:gen` | 验证生成代码质量 | ⛔ 已弃用 |
| `npm run check:duplicates` | 检查重复的目标键 | ⛔ 已弃用 |
| `npm run all` | 运行完整工作流 | ⛔ 已弃用 |
> ⛔ 标记的命令已完成阶段性使命,**不再支持**,运行只会打印提示。详见顶部说明。
## 脚本架构
> 注:下图与下表为原始完整工作流的历史记录;其中 `extract-inventory` / `validate-consistency` / `validate-generation` / `check-duplicates` 相关脚本已弃用(文件名已加 `DO-NOT-USE-` 前缀),仅 `generate-*` 仍在使用。
### 依赖关系图
```
┌─────────────────────────────────────────────────────────────┐
│ 共享模块 │
│ scripts/lib/classificationUtils.js │
│ - loadClassification() - traverseClassifications() │
│ - saveClassification() - calculateStats() │
│ - loadInventory() - normalizeType() │
│ - extractPreferencesData() - inferTypeFromValue() │
└─────────────────────────────────────────────────────────────┘
▲ ▲
│ │
┌───────────┘ └───────────┐
│ │
┌───────┴───────┐ ┌────────┴────────┐
│ extract- │ │ validate- │
│ inventory.js │ │ consistency.js │
│ │ │ │
│ 扫描源码 │ │ 检查数据 │
│ 构建清单 │ │ 一致性 │
└───────────────┘ └─────────────────┘
┌─────────────────────┐
│ generate-all.js │─────────────────────┬──────────────────────┐
│ │ │ │
│ 编排所有生成器 │ │ │
└─────────────────────┘ │ │
│ │ │
│ require() │ require() │ require()
▼ ▼ ▼
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ generate- │ │ generate- │ │ generate- │
│ preferences.js │ │ boot-config.js │ │ migration.js │
│ │ │ │ │ │
│ 生成 │ │ 生成 │ │ 生成 │
│ preferenceSchemas.ts│ │ bootConfigSchemas.ts│ │ PreferencesMappings │
└─────────────────────┘ └─────────────────────┘ │ BootConfigMappings │
└─────────────────────┘
┌─────────────────────┐ ┌─────────────────────┐
│ validate- │ │ check- │
│ generation.js │ │ duplicates.js │
│ │ │ │
│ 验证生成代码质量 │ │ 检查重复目标键 │
│ (独立运行) │ │ (独立运行) │
└─────────────────────┘ └─────────────────────┘
```
### 脚本详情
| 脚本 | 输入 | 输出 | 依赖 |
| ------------------------- | --------------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------ |
| `generate-preferences.js` | `classification.json` | `preferenceSchemas.ts` | 无 |
| `generate-boot-config.js` | `classification.json` | `bootConfigSchemas.ts` | 无 |
| `generate-migration.js` | `classification.json` | `PreferencesMappings.ts`, `BootConfigMappings.ts` | 无 |
| `generate-all.js` | - | 运行三个生成器 | `generate-preferences.js`, `generate-boot-config.js`, `generate-migration.js` |
| `DO-NOT-USE-extract-inventory.js` _(已弃用)_ | 源代码文件 | `data/inventory.json` | `classificationUtils.js` |
| `DO-NOT-USE-validate-consistency.js` _(已弃用)_ | `inventory.json`, `classification.json` | `validation-report.md` | `classificationUtils.js` |
| `DO-NOT-USE-validate-generation.js` _(已弃用)_ | 生成的 `.ts` 文件 | 控制台输出 | 无 |
| `DO-NOT-USE-check-duplicates.js` _(已弃用)_ | `classification.json` | 控制台输出 | 无 |
## 数据分类工作流
> ⚠️ 本节为历史记录:步骤 1提取与步骤 4验证所用命令已弃用、不再支持当前仅步骤 3生成仍受支持。
### 1. 提取数据清单
```bash
npm run extract
```
扫描源文件并提取以下数据源的信息:
- **Redux Store**: `src/renderer/store/*.ts`
- **Electron Store**: `src/main/services/ConfigManager.ts`
- **LocalStorage**: 所有使用 localStorage 的文件
- **Dexie 数据库**: `src/renderer/databases/index.ts`
> **注意**: `dexieSettings` 数据源中的字符串字面量 key 会被自动提取,但动态 key如模板字符串拼接的需要手动维护。详见下方 [dexieSettings 数据源](#dexiesettings-数据源) 章节。
### 2. 分类数据
编辑 `data/classification.json` 对每个数据项进行分类:
```json
{
"originalKey": "theme",
"type": "string",
"status": "classified",
"category": "preferences",
"targetKey": "ui.theme_mode"
}
```
### 3. 生成代码
```bash
npm run generate
```
生成以下 TypeScript 文件:
- `src/shared/data/preference/preferenceSchemas.ts` - 偏好配置类型定义与默认值
- `src/shared/data/bootConfig/bootConfigSchemas.ts` - 启动配置类型定义与默认值
- `src/main/data/migration/v2/migrators/mappings/PreferencesMappings.ts` - 偏好迁移映射
- `src/main/data/migration/v2/migrators/mappings/BootConfigMappings.ts` - 启动配置迁移映射
### 4. 验证
```bash
npm run validate
npm run validate:gen
```
验证内容:
- 所有清单项都已分类
- 没有孤立的分类条目
- 命名规范一致
- 没有重复的目标键
- 生成代码结构正确
---
## 数据分类标准
根据 Cherry Studio 数据重构架构,所有数据需要分类到以下 6 个类别之一:
### 1. 偏好配置 (preferences)
**判断标准**:
- ✅ 影响应用全局行为的配置
- ✅ 用户可以修改的设置项
- ✅ 简单的数据类型boolean/string/number/简单 array/object
- ✅ 结构相对稳定,不经常变化
- ✅ 数据量小,可以重建
- ✅ 需要在窗口间同步
**典型例子**:
- `showAssistants`: 是否显示助手面板
- `theme`: 主题设置light/dark/system
- `fontSize`: 字体大小
- `language`: 界面语言
**命名规范**:
- 使用点分隔的层级结构:`ui.fontSize``system.language`
- 分组前缀:`ui.*`(界面)、`system.*`(系统)、`app.*`(应用行为)等
### 2. 启动配置 (bootConfig)
**判断标准**:
- ✅ 必须在 Node.js 进程启动的最早阶段同步加载(早于 `app.whenReady`、早于 lifecycle 的 `BeforeReady` 阶段)
- ✅ 影响进程级别的行为,一旦进程启动就无法更改
- ✅ 不能存储在 SQLite 中(数据库由 lifecycle `BeforeReady` 阶段初始化,远晚于 boot config 的加载时机)
- ✅ 使用同步文件 I/O 读取(`~/.cherrystudio/boot-config.json`,刻意放在 userData 之外,避免鸡生蛋问题)
**时序关系**:
```
Boot Config 加载 → bootstrap初始化 appData 目录)→ app.whenReady → lifecycle BeforeReadyDB 初始化)→ lifecycle WhenReady
```
Boot config 在整个启动链的最前端,为后续所有阶段提供基础配置。
**典型例子**:
- `disableHardwareAcceleration`: 硬件加速开关(必须在任何 Electron API 调用前设置)
- 应用路径定义等需要在 bootstrap 阶段就确定的配置
**与 preferences 的区别**:
| | bootConfig | preferences |
| --- | --- | --- |
| 加载时机 | 进程启动最早阶段(同步) | lifecycle `BeforeReady` 阶段(异步) |
| 存储方式 | JSON 文件(`~/.cherrystudio/boot-config.json` | SQLite 数据库 |
| 访问方式Main | `bootConfigService.get()` 同步 | `application.get('PreferenceService').get()` |
| 访问方式Renderer | `usePreference('BootConfig.*')` 统一访问 | `usePreference('key')` |
### 3. 用户数据 (user_data)
**判断标准**:
- ✅ 用户创建或输入的内容
- ✅ 不可丢失的重要数据
- ✅ 数据量可能很大
- ✅ 需要完整备份和迁移机制
- ✅ 可能包含敏感信息
**典型例子**:
- `topics`: 对话历史
- `messages`: 消息内容
- `files`: 用户上传的文件
- `knowledge_notes`: 知识库笔记
**特殊处理**:
- 敏感数据需要加密存储
- 大数据表需要考虑分页和流式处理
### 4. 缓存数据 (cache)
**判断标准**:
- ✅ 可以重新生成的数据
- ✅ 主要用于性能优化
- ✅ 丢失后不影响核心功能
- ✅ 有过期时间或清理机制
**典型例子**:
- `failed_favicon_*`: 失败的 favicon 缓存
- 搜索结果缓存
- 图片预览缓存
- 模型响应缓存
### 5. 运行时数据 (runtime)
**判断标准**:
- ✅ 内存型数据,不需要持久化
- ✅ 生命周期 ≤ 应用进程
- ✅ 应用重启后可以丢失
- ✅ 临时状态信息
**典型例子**:
- 当前选中的对话
- 临时的输入状态
- UI 组件的展开/折叠状态
- 网络请求状态
### 6. 应用资源 (resources)
**判断标准**:
- ✅ 静态资源文件
- ✅ 随应用分发的内容
- ✅ 不需要用户修改
- ✅ 暂不考虑重构
**典型例子**:
- 图标文件
- 本地化翻译文件
- 默认配置文件
- 帮助文档
---
## 分类决策流程图
```
数据项
是否必须在进程启动最早阶段同步加载(早于 lifecycle
↓ 是 ↓ 否
启动配置 是否用户创建/输入的内容?
(bootConfig) ↓ 是 ↓ 否
用户数据 是否需要持久化?
↓ 否 ↓ 是
运行时数据 是否可重新生成?
↓ 是 ↓ 否
缓存数据 是否用户可修改?
↓ 是 ↓ 否
偏好配置 应用资源
```
---
## 分类示例
### 示例 1: Redux settings.showAssistants
```json
{
"classifications": {
"redux": {
"settings": [
{
"originalKey": "showAssistants",
"type": "boolean",
"defaultValue": true,
"status": "classified",
"category": "preferences",
"targetKey": "ui.show_assistants"
}
]
}
}
}
```
**分析过程**:
1. 数据用途:控制是否显示助手面板
2. 用户可修改:✅
3. 影响全局:✅
4. 数据简单:✅ boolean 类型
5. 结论:偏好配置
### 示例 2: 嵌套结构 (Redux settings with children)
```json
{
"originalKey": "codeEditor",
"type": "object",
"children": [
{
"originalKey": "enabled",
"type": "boolean",
"defaultValue": true,
"status": "classified",
"category": "preferences",
"targetKey": "code_editor.enabled"
},
{
"originalKey": "fontSize",
"type": "number",
"defaultValue": 14,
"status": "classified",
"category": "preferences",
"targetKey": "code_editor.font_size"
}
]
}
```
**注意**: 父级项不需要 `status`/`category`/`targetKey`,这些只在叶子节点设置。
### 示例 3: Dexie topics 表
```json
{
"originalKey": "topics",
"type": "table",
"status": "classified",
"category": "user_data",
"targetTable": "topic",
"notes": "用户对话历史,核心业务数据"
}
```
---
## 命名规范
偏好配置键必须遵循:`namespace.sub.key_name`
**规则**:
- 至少 2 个由点分隔的段
- 仅使用小写字母、数字、下划线
- 模式:`/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/`
**示例**:
- `app.theme` (有效)
- `chat.input.send_shortcut` (有效)
- `Theme` (无效 - 没有点分隔符)
- `App.User` (无效 - 大写字母)
---
## 增量更新策略
> ⚠️ 本节描述的提取(`npm run extract`)流程已弃用、不再支持,仅作历史记录。
### 核心特性
- **保留已分类数据**: 重新运行提取不会丢失已有分类
- **标记删除项**: 删除的数据项被标记但不移除
- **自动发现新项**: 新数据项自动添加到待处理列表
- **自动备份**: 每次运行前自动备份原分类文件
### 更新流程
1. 代码变更后运行 `npm run extract`
2. 脚本自动备份 `classification.json``classification.backup.json`
3. 脚本识别新增和删除的数据项
4. 新项添加到 `pending` 数组
5. 删除项标记为 `status: 'classified-deleted'`
6. 手动处理新的待处理项
---
## 文件格式说明
### inventory.json 结构
```json
{
"metadata": {
"generatedAt": "ISO 日期",
"version": "版本号"
},
"redux": {
"moduleName": {
"fieldName": {
"type": "数据类型",
"defaultValue": "默认值"
}
}
},
"electronStore": { ... },
"localStorage": { ... },
"dexie": { ... }
}
```
### classification.json 结构
```json
{
"metadata": {
"version": "版本号",
"lastUpdated": "ISO 日期"
},
"classifications": {
"redux": {
"moduleName": [
{
"originalKey": "字段名",
"type": "数据类型",
"status": "classified|pending|classified-deleted",
"category": "preferences|bootConfig|user_data|cache|runtime|resources",
"targetKey": "target.key.name"
}
]
},
"electronStore": { ... },
"localStorage": { ... },
"dexieSettings": {
"settings": [
{
"originalKey": "字段名",
"type": "数据类型",
"status": "classified|pending",
"category": "preferences",
"targetKey": "target.key.name"
}
]
},
"dexie": { ... }
}
}
```
### dexieSettings 数据源
`dexieSettings` 是 classification.json 中与 `redux``electronStore``localStorage``dexie` 并列的第五个顶级数据源,专门用于分类 Dexie IndexedDB 中 `settings` 表的 KV 配置项。
**与 `dexie` 数据源的区别**:
| 数据源 | 用途 | 数据结构 | 典型分类 |
| --- | --- | --- | --- |
| `dexie` | Dexie 的业务数据表files, topics 等) | 表级别,使用 `targetTable` | `user_data` |
| `dexieSettings` | Dexie 的 `settings`KV 配置) | 字段级别,使用 `targetKey` | `preferences`(目前仅支持此分类) |
**classification.json 中的结构**:
```json
{
"classifications": {
"dexieSettings": {
"settings": [
{
"originalKey": "settingKeyName",
"type": "string",
"defaultValue": "defaultValue",
"status": "classified",
"category": "preferences",
"targetKey": "namespace.key_name"
}
]
}
}
}
```
**在代码生成中的作用**:
1. **`generate-preferences.js`**: 作为四大偏好数据源之一(`electronStore``redux``localStorage``dexieSettings`),参与生成 `preferenceSchemas.ts`
2. **`generate-migration.js`**: 生成独立的 `DEXIE_SETTINGS_MAPPINGS` 映射数组,用于迁移器从 Dexie settings 表读取数据
**去重优先级**(当多个数据源映射到相同 targetKey 时):
```
redux (最高) > dexieSettings > localStorage > electronStore (最低)
```
**已知字段清单**(参考 [PR #10162 comment](https://github.com/CherryHQ/cherry-studio/pull/10162#issuecomment-4010796619):
Dexie `settings` 表是一个通用 KV 存储(`{ id: string, value: any }`),所有 `image://` 键由 `ImageStorage` 服务管理。
*固定键*:
| Key | Value Type | 迁移目标 |
| --- | --- | --- |
| `translate:model` | `string` (model id) | preference |
| `translate:target:language` | `string` (langCode) | preference |
| `translate:source:language` | `string` (langCode) | preference |
| `translate:bidirectional:enabled` | `boolean` | preference |
| `translate:bidirectional:pair` | `[string, string]` (langCode pair) | preference |
| `translate:scroll:sync` | `boolean` | preference |
| `translate:markdown:enabled` | `boolean` | preference |
| `translate:detect:method` | `string` ('franc'/'llm'/'auto') | preference |
| `pinned:models` | `Model[]` | preference |
| `image://avatar` | `string` (base64 data URL \| emoji) | preference / file manager |
*动态键(基于 pattern*:
| Key Pattern | Value Type | 迁移目标 |
| --- | --- | --- |
| `image://provider-${providerId}` | `string` (base64 data URL \| emoji \| `''`) | file manager |
| `mcp:provider:${provider.key}:servers` | `MCPServer[]` | new table |
*已知遗留键(代码中无引用,运行时 IndexedDB 中存在)*:
| Key | 说明 |
| --- | --- |
| `translate:model:prompt` | 已被 Redux `settings.translateModelPrompt` 取代,已迁移到 preference `feature.translate.model_prompt`,跳过 |
**注意事项**:
- `extract-inventory.js` 会自动提取 `db.settings.get/put/add()` 调用中的**字符串字面量** key动态 key模板字符串拼接无法自动提取需要**手动添加**
- 手动添加的条目在重新提取时会被保留(不会被覆盖或删除)
- `dexieSettings``category` 目前仅支持 `preferences`,代码生成脚本只处理该分类
- `validate-consistency.js` 不会检查 `dexieSettings` 与 inventory 的一致性
- 迁移时通过 `ctx.sources.dexieSettings.get(mapping.originalKey)` 读取数据
- 动态键(含 `${}` 模板的 pattern需要特殊的迁移逻辑不能用简单 1:1 映射处理
### 状态值说明
| Status | 说明 | 操作建议 |
| -------------------- | ---------------- | ---------------------------------------- |
| `pending` | 待分类 | 需要人工分析并设置 category 和 targetKey |
| `classified` | 已分类 | 分类完成,可用于代码生成 |
| `classified-deleted` | 已分类但源已删除 | 源代码中已不存在,保留历史记录 |
### targetKey 值说明
对于 `status: "classified"` 的项,`targetKey` 有两种情况:
| targetKey | 说明 | 生成行为 |
| --------- | ---- | -------- |
| 有效值(如 `"ui.theme"` | 需要迁移到新系统 | 会生成到 preferenceSchemas.ts |
| `null` | 已分类,但不需要迁移 | 不会生成到 preferenceSchemas.ts |
**使用场景**:当一个数据项经过分析后,确定在新系统中不需要该配置(如已废弃、被其他配置替代、或不再需要持久化),应设置 `status: "classified"``targetKey: null`。这表示"已完成分类决策,决策结果是不加载该项"。
---
## 复杂映射支持
### 概述
除了简单的一对一映射(`originalKey → targetKey`),系统还支持复杂的数据转换:
1. **对象拆分 (1→N)**: 一个源对象拆分为多个 target keys
2. **多源合并 (N→1)**: 多个源数据合并为一个或多个目标
3. **值计算/转换**: 值需要经过计算、格式转换或逻辑处理
4. **条件映射**: 根据源数据的值决定写入哪些目标
### 架构
```
┌─────────────────────────────────────────────────────────────┐
│ classification.json (status: classified) │
│ ───────────────────────────────────────── │
│ 基础数据源,包含所有简单映射的 target keys │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ target-key-definitions.json │
│ ───────────────────────────────────────── │
│ 用途1: 复杂迁移 - 定义需要特殊转换逻辑的 target keys │
│ 用途2: 纯新增 - 添加 v2 新功能的 preferences非迁移
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ preferenceSchemas.ts (最终输出) │
└─────────────────────────────────────────────────────────────┘
```
### target-key-definitions.json
用于定义无法通过 `classification.json` 简单映射处理的 preference keys。主要用于两个场景
1. **复杂迁移**: 定义需要特殊转换逻辑(对象拆分、多源合并、值计算等)产生的 target keys
2. **纯新增(非迁移)**: 添加 v2 新功能的 preferences这些配置不是从旧代码迁移的
**文件结构**:
```json
{
"metadata": {
"version": "1.0.0",
"description": "Target key definitions...",
"lastUpdated": "2025-01-18"
},
"definitions": [
{
"targetKey": "app.window.position.x",
"type": "number",
"defaultValue": 0,
"status": "classified",
"description": "Window X position (from complex mapping)"
}
]
}
```
**字段说明**:
| 字段 | 必填 | 说明 |
| -------------- | ---- | -------------------------------------------------------- |
| `targetKey` | ✓ | preference key必须符合命名规范 |
| `type` | ✓ | TypeScript 类型string, number, boolean, 或自定义类型) |
| `defaultValue` | ✓ | 默认值(支持 `VALUE: ...` 特殊格式) |
| `status` | ✓ | `classified` 启用,`pending` 禁用 |
| `description` | | 可选描述 |
#### 纯新增(非迁移)场景
当需要添加一个全新的 preference不是从旧代码迁移的 v2 新功能)时,直接在 `definitions` 数组中添加即可。
**示例**: 添加 v2 版本新增的功能配置
```json
{
"definitions": [
{
"targetKey": "feature.new_assistant.enabled",
"type": "boolean",
"defaultValue": false,
"status": "classified",
"description": "启用新助手功能v2 新增,非迁移)"
},
{
"targetKey": "feature.new_assistant.default_model",
"type": "string",
"defaultValue": "gpt-4",
"status": "classified",
"description": "新助手默认模型v2 新增,非迁移)"
}
]
}
```
运行 `npm run generate:preferences` 后,这些 keys 会出现在生成的 `preferenceSchemas.ts` 中。
**与复杂迁移的区别**:
- 复杂迁移需要在 `PreferenceTransformers.ts``ComplexPreferenceMappings.ts` 中实现转换逻辑
- 纯新增只需要在 `target-key-definitions.json` 中定义,无需额外代码
**建议**: 在 `description` 中注明是"复杂迁移"还是"v2 新增,非迁移",便于后续维护。
**defaultValue 特殊格式**:
与 classification.json 保持一致,支持 `VALUE: ...` 特殊格式:
```json
// 引用枚举值
{ "defaultValue": "VALUE: PreferenceTypes.ThemeMode.system" }
// 生成: PreferenceTypes.ThemeMode.system不加引号
// 引用常量
{ "defaultValue": "VALUE: TRANSLATE_PROMPT" }
// 生成: TRANSLATE_PROMPT不加引号
// 特殊 null 值
{ "defaultValue": "VALUE: null" }
// 生成: null
// 普通字符串(不使用 VALUE: 前缀)
{ "defaultValue": "light" }
// 生成: 'light'(带引号)
```
### 复杂映射实现
复杂映射的转换逻辑定义在以下文件中:
```
src/main/data/migration/v2/migrators/
├── mappings/
│ ├── PreferencesMappings.ts # 偏好简单映射(自动生成)
│ ├── BootConfigMappings.ts # 启动配置映射(自动生成)
│ └── ComplexPreferenceMappings.ts # 复杂映射配置
├── transformers/
│ └── PreferenceTransformers.ts # 转换函数实现
├── PreferencesMigrator.ts # 偏好迁移执行器
└── BootConfigMigrator.ts # 启动配置迁移执行器
```
**添加复杂映射的步骤**:
1.`target-key-definitions.json` 中定义 target keys`status: "classified"`
2.`PreferenceTransformers.ts` 中实现转换函数
3.`ComplexPreferenceMappings.ts` 中添加映射配置
4. 运行 `npm run generate:preferences` 重新生成 preferenceSchemas.ts
### 冲突处理
系统采用**严格模式**:如果简单映射和复杂映射的 target key 有冲突,迁移时会报错。
解决方法从简单映射classification.json中移除冲突的 key由复杂映射处理。
---
## 故障排除
### "Module not found" 错误
```bash
cd v2-refactor-temp/tools/data-classify
npm install
```
### 验证错误
1. 检查 `validation-report.md` 了解详情
2. 修复 `classification.json` 条目
3. 重新运行验证
### 生成代码问题
1. ~~运行 `npm run validate:gen` 识别问题~~(已弃用,不再支持)
2. 检查源分类数据
3. 使用 `npm run generate` 重新生成
### 数据项被错误标记为删除
检查提取脚本的模式是否正确匹配代码结构。
### 如何恢复意外删除的分类
从以下位置恢复 `classification.json`
- 自动备份文件:`classification.backup.json`
- Git 历史记录