npm package: @share-crm/sharedev-cli
Description: sharedev command line tool
Author: sharecrm-npm
Latest version: 0.0.1

# sharedev CLI 技术方案

## 项目概览

`sharedev` 是一个基于 Node.js 的命令行工具，用于 APL 函数、PWC 组件和开发元数据的本地开发工作流。

- 命令入口：`sharedev`
- 业务命名空间：`apl`、`pwc`
- 构建工具：webpack + TypeScript
- 运行时：Node.js 18+

---

## 命令设计

### 命令树

```
sharedev
├── init                           # 项目初始化，生成目录、git 仓库、.gitignore 和 .sharedev/settings.json
├── apl
│   ├── list                       # 列出远端 APL 函数摘要
│   ├── info <apiName>             # 查询 APL 函数详情
│   ├── pull [apiName]             # 拉取单个或全部 APL 函数到本地
│   ├── diff [apiName]             # 对比本地与快照/远端版本
│   ├── push [apiName]             # 提交单个或全部本地变更到远端
│   ├── reset [apiName]            # 回滚本地文件到远端最新或指定版本
│   ├── compile [apiName]          # 编译检测本地源码
│   ├── analyze [apiName]          # 静态分析本地源码
│   ├── debug [apiName]            # 运行函数调试
│   └── create                     # 创建函数/类并写入本地源码
├── pwc
│   ├── pull <apiName>             # 拉取组件/插件到本地
│   ├── push <apiName>             # 提交本地变更
│   ├── publish <apiName>          # 发布
│   ├── dev <apiName>              # 本地开发模式（待规划）
│   └── create                     # 创建组件（预留）
├── dev-metadata
│   ├── search [query]             # 搜索对象元数据
│   ├── info [apiName]             # 查询对象详情
│   ├── download [apiName]         # 下载单个对象元数据 markdown
│   ├── download --all             # 批量下载对象元数据 markdown
│   └── namespace                  # 下载运行时命名空间元数据
└── skill                          # 预留
    ├── init                       # 下载 skill 到平台目录
    ├── pull/push/list/unset       # 预留命令位
```

### 全局参数

- `--version` / `-v`：输出版本号
- `--help` / `-h`：显示帮助信息

---

## APL 功能方案

### 本地工作区模型

```text
<settingsParent>/
├── package/
│   ├── fx/custom/apl/script/           # package_name 为空时的默认目录
│   │   └── <apiName>.<type>.groovy
│   └── <package_name as path>/         # package_name 中的 . 会被替换为 /
│       └── <apiName>.<type>.groovy
└── .sharedev/
    └── apl/
        └── .sharedev/
            ├── snapshot.json           # 已拉取/已提交版本的源码快照
            ├── versions.json           # 版本信息
            └── metadata.json           # 绑定对象、参数等元信息
```

### 当前已实现命令

- `apl list`
  - 拉取远端函数列表
  - 仅保留 `lang === 0` 且 `is_control !== true` 的 Groovy 函数
  - 输出 `apiName/functionName/packageName/version`
- `apl info <apiName> [--bind <bindingObjectApiName>]`
  - 查询单个函数详情
  - 终端输出摘要和参数列表
- `apl pull <apiName>` / `apl pull --all`
  - 单个或批量拉取远端源码
  - 写入本地 `.groovy` 文件
  - 同步更新 snapshot / versions / metadata
- `apl diff <apiName> [--remote latest|<version>]`
  - 默认对比本地文件和 snapshot
  - 支持对比远端 latest 或指定版本
  - 输出 unified diff 和增删行统计
- `apl push [apiName] --remark <comment> [--force]`
  - `apiName` 存在时只提交单个函数；省略时提交所有已跟踪且有本地变更的函数
  - 提交前执行远端版本冲突检查、analyze、compile
  - 成功后回写本地源码和 snapshot
- `apl reset <apiName> [--remote latest|<version>]`
  - 使用远端 latest 或指定版本覆盖本地文件
  - 同步更新 snapshot
- `apl analyze <apiName>`
  - 基于本地源码和远端元信息执行静态分析
  - 输出 JSON 结果
- `apl compile <apiName>`
  - 基于本地源码和远端元信息执行编译检查
- `apl debug <apiName> [--data-id <id>] [--param <name=value>]...`
  - 读取本地源码进行调试
  - 绑定对象 data id 和函数参数支持 CLI 传参，也支持交互补齐
  - 输出调试摘要和原始结果
- `apl create`
  - 支持创建 `function` / `class`
  - 支持通过命令参数或交互输入补齐 apiName、functionName、namespace、package、returnType、bind、remark、templateId
  - 先在远端创建，再将生成后的源码写入本地并写入 snapshot

### 主要流程

**pull**：按单个或批量方式获取远端函数详情 → 写入本地 `.groovy` 文件 → 记录 snapshot / versions / metadata

**push**：读取本地 tracked 文件 → 与 snapshot 比较变更 → 校验远端版本冲突 → analyze / compile → 提交更新 → 更新本地源码和 snapshot

**diff**：按 `apiName` 定位本地 tracked 文件 → 基于 snapshot 或远端版本生成 unified diff

**reset**：获取远端 latest 或指定版本 → 覆盖本地源码并更新 snapshot

**compile / analyze**：读取本地 tracked 源码并拼接远端元信息 → 调用远端编译或分析接口

**debug**：CLI 参数优先，缺失时通过交互补齐绑定对象 data id 和函数参数 → 构造 payload 调用远端调试接口

**create**：先加载 namespace / returnType / binding object 元数据 → 构造模板 → 远端创建 → 本地写入源码和 snapshot

### 模块职责

| 模块 | 职责 |
|------|------|
| `apl.service.ts` | 远端接口封装：列表、详情、版本查询、create、push、compile、analyze、debug |
| `apl.workspace.ts` | 本地源码路径解析、tracked 文件发现、snapshot / metadata 管理 |
| `apl.command.ts` | CLI 参数校验、交互补齐、命令编排、diff 输出 |

---

## Dev Metadata 功能方案

### 本地输出模型

```text
<settingsDir>/docs/dev-metadata/
├── objects/
│   ├── objects.md                    # 全量对象索引（download --all 时生成）
│   └── <apiName>.md                  # 单个对象详情文档
└── namespaces/
    └── namespaces.json               # 运行时命名空间原始结果
```

说明：
- 未显式传 `--output` 时，输出目录默认位于 `.sharedev/docs/dev-metadata/`
- 传入 `--output` 时，相对路径基于命令执行时的 `workingDir/cwd` 解析

### 当前已实现命令

- `dev-metadata search [query]`
  - 调用对象列表接口
  - 本地按 `api_name / display_name / display_name_r` 过滤和排序
  - 输出标准化 JSON 摘要
- `dev-metadata info [apiName]`
  - 先按 apiName 直接查询详情
  - 直查失败时回退到列表搜索候选项
  - 候选项多于 1 个时，交互选择目标对象
  - 输出对象摘要、字段列表和 layout 摘要
- `dev-metadata download <apiName>`
  - 下载单个对象详情并写成 markdown
- `dev-metadata download --all`
  - 拉取对象列表并逐个下载详情
  - 输出每个对象的 markdown 文件
  - 同时生成 `objects.md` 索引
- `dev-metadata namespace [--output <dir>]`
  - 调用运行时 namespace 接口
  - 以原始 JSON 形式写入 `namespaces.json`

### 主要流程

**search**：拉取对象列表 → 本地过滤 / 排序 → 输出 JSON 摘要

**info**：优先直查对象详情 → 失败时回退候选搜索与交互选择 → 输出终端可读摘要

**download**：拉取对象详情 → 渲染 markdown → 写入对象文档目录

**download --all**：拉取对象列表 → 逐个请求详情并落盘 → 生成对象索引

**namespace**：调用运行时 namespace 元数据接口 → 原样写入 JSON 文件

### 模块职责

| 模块 | 职责 |
|------|------|
| `dev-metadata.service.ts` | 对象列表、对象详情、运行时 namespace 接口封装，以及搜索过滤 / 排序 |
| `dev-metadata.workspace.ts` | 输出目录解析、对象 markdown 渲染、索引和 namespace 文件写入 |
| `dev-metadata.command.ts` | search / info / download / namespace 命令编排与交互 |

---

## PWC 功能方案

### 本地目录模型

```
<workspace>/
├── pwc-components/<apiName>/           # type=component 时
│   ├── mateXml.xml
│   ├── source/
│   ├── static/
│   ├── fileTree/
│   └── .sharedev-meta.json
└── pwc-plugins/<apiName>/             # type=plugin 时
    ├── mateXml.xml
    ├── source/
    ├── static/
    ├── fileTree/
    └── .sharedev-meta.json
```

### 主要流程

**pull**：按 `apiName` 拉取完整数据 → 写入 `mateXml.xml`、source、static、fileTree → 生成 `.sharedev-meta.json`

**push**：扫描本地文件 → 排除 `mateXml.xml` → 按类型组装 sourceFiles/images/fileTree → 调用 `updateCodeSource`

**publish**：复用 push 逻辑

### 模块职责

| 模块 | 职责 |
|------|------|
| `pwc.service.ts` | 远端接口封装：fetchCode、downloadFile、uploadFile、updateCodeSource |
| `pwc.workspace.ts` | 本地目录初始化、mateXml 读写、entryFileName 解析 |
| `pwc.publish.ts` | 文件装配、类型归类、发布编排 |

---

## 配置方案

配置文件固定为 `.sharedev/settings.json`，内容：

```json
{
  "certificate": "<token>",
  "domain": "https://www.fxiaoke.com/"
}
```

`config.ts` 提供：

- `findSettings()`：从当前工作目录向上查找配置文件
- `loadSettings()`：读取并校验配置
- `getSettings()`：单例式配置访问

配置文件缺失时立即报错退出，不发请求。

---

## 公共基础服务

### loggerService (`src/core/logger.ts`)

统一管理所有终端输出，基于 `chalk`：

| 方法 | 用途 |
|------|------|
| `info/success/warn/error(message)` | 带 `[sharedev]` 前缀的可读日志 |
| `debug(message)` | 仅在 `--verbose` 下输出 |
| `printJson(data)` | 输出纯 JSON（供 list/analyze/debug 等命令） |
| `printRaw(text)` | 不加前缀原样输出（用于 diff） |
| `startLoading(message)` | 启动 loading |
| `updateLoading(message)` | 更新 loading 文案 |
| `stopLoading()` | 停止 loading |

退化策略：非 TTY 或 `--verbose` 下，loading 退化为稳定文本，避免控制字符污染日志。

### requestService (`src/core/request.ts`)

基于 `axios` 封装，统一注入 `domain` 和 `certificate`，提供 `get/post/request` 方法。

---

## 构建方案

- 源码入口：`src/cli.ts`
- webpack 配置：`build/webpack/webpack.{common,dev,prod}.cjs`
- 构建产物：`dist/sharedev.js`
- 发布入口：`bin/cli.mjs`（加载 `dist/sharedev.js`，含 shebang）

第三方依赖（axios、chalk、commander、ora、@clack/prompts 等）全部打入 bundle，不依赖外部 node_modules。

---

## 实施计划

### 第一期（最小可用）

1. 项目骨架：package.json、tsconfig、webpack 构建配置
2. CLI 入口：`sharedev apl`、`sharedev pwc` 命令注册
3. `.sharedev/settings.json` 查找与校验
4. loggerService 和 requestService 基础实现
5. APL pull / push 基础能力
6. PWC pull / push 基础能力

### 第二期

1. APL diff / reset / compile / analyze / debug
2. APL 批量 push
3. PWC publish
4. dev-metadata search / info / download / namespace

### 第三期

1. APL / PWC create 的更多模板与能力
2. watch 模式
3. 更完整的冲突处理

---

## 风险与注意事项

1. **VS Code 扩展能力不可直接迁移**：CLI 中用 Node 文件系统 API、终端交互、本地快照替代 VS Code API
2. **配置是前置条件**：`.sharedev/settings.json` 缺失时不能继续执行，不能带空配置发请求
3. **不要暴露 certificate**：`certificate` 字段不能明文打印到日志
4. **APL 和 PWC 抽象层次不同**：APL 是单文件函数，PWC 是多目录组件，工作区模型不共用