prime-dev-cli 2.0.8 → 2.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/projects.json +80 -24
- package/dist/server/.next/BUILD_ID +1 -1
- package/dist/server/.next/app-build-manifest.json +3 -3
- package/dist/server/.next/build-manifest.json +2 -2
- package/dist/server/.next/cache/.rscinfo +1 -1
- package/dist/server/.next/cache/.tsbuildinfo +1 -1
- package/dist/server/.next/cache/eslint/.cache_1qa5vxt +1 -1
- package/dist/server/.next/fallback-build-manifest.json +2 -2
- package/dist/server/.next/next-minimal-server.js.nft.json +1 -1
- package/dist/server/.next/next-server.js.nft.json +1 -1
- package/dist/server/.next/prerender-manifest.json +9 -9
- package/dist/server/.next/server/app/_not-found.html +1 -1
- package/dist/server/.next/server/app/_not-found.rsc +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-create-branch/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-delete-branch/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-merge/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/admin-git-batch-probe-remote-branch/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/batch-switch-branch/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/batch-switch-submodule-branch/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/branch/switch/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/branches/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/check-workspace/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/gwh-git-flow/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/initialize-workspace/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/microapp-proxy-config/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/open-project/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/project-config/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/retry-project/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/submodule-info/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/uat-git-flow/route.js +1 -1
- package/dist/server/.next/server/app/api/uat-git-flow/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/api/uat-git-flow/step/route.js +1 -1
- package/dist/server/.next/server/app/api/uat-git-flow/step/route.js.nft.json +1 -1
- package/dist/server/.next/server/app/configuration/page/app-build-manifest.json +1 -1
- package/dist/server/.next/server/app/configuration/page_client-reference-manifest.js +1 -1
- package/dist/server/.next/server/app/configuration.html +1 -1
- package/dist/server/.next/server/app/configuration.rsc +2 -2
- package/dist/server/.next/server/app/index.html +1 -1
- package/dist/server/.next/server/app/index.rsc +1 -1
- package/dist/server/.next/server/app/initialization/page/app-build-manifest.json +2 -2
- package/dist/server/.next/server/app/initialization/page.js.nft.json +1 -1
- package/dist/server/.next/server/app/initialization/page_client-reference-manifest.js +1 -1
- package/dist/server/.next/server/app/initialization.html +1 -1
- package/dist/server/.next/server/app/initialization.rsc +2 -2
- package/dist/server/.next/server/chunks/_24087f66._.js +1 -1
- package/dist/server/.next/server/chunks/_24087f66._.js.map +1 -1
- package/dist/server/.next/server/chunks/_61c263b3._.js +1 -1
- package/dist/server/.next/server/chunks/_61c263b3._.js.map +1 -1
- package/dist/server/.next/server/chunks/packages_server_42b02aec._.js +3 -0
- package/dist/server/.next/server/chunks/packages_server_42b02aec._.js.map +1 -0
- package/dist/server/.next/server/chunks/packages_server_854cbe00._.js +3 -0
- package/dist/server/.next/server/chunks/packages_server_854cbe00._.js.map +1 -0
- package/dist/server/.next/server/chunks/ssr/_283bdc73._.js +1 -1
- package/dist/server/.next/server/chunks/ssr/_283bdc73._.js.map +1 -1
- package/dist/server/.next/server/chunks/ssr/_c7905e3c._.js +1 -1
- package/dist/server/.next/server/chunks/ssr/_c7905e3c._.js.map +1 -1
- package/dist/server/.next/server/chunks/ssr/packages_server_src_622c27d6._.js +3 -0
- package/dist/server/.next/server/chunks/ssr/packages_server_src_622c27d6._.js.map +1 -0
- package/dist/server/.next/server/pages/404.html +1 -1
- package/dist/server/.next/server/pages/500.html +1 -1
- package/dist/server/.next/server/server-reference-manifest.js +1 -1
- package/dist/server/.next/server/server-reference-manifest.json +1 -1
- package/dist/server/.next/static/chunks/2dfd52ecb63ce530.js.map +1 -0
- package/dist/server/.next/static/chunks/{45543bd9f83f509f.js → 4e8de43e1f6c5336.js} +2 -2
- package/dist/server/.next/static/chunks/51016cbb3e241c61.js +3 -0
- package/dist/server/.next/static/chunks/{8e1056102ab0be45.js.map → 84a2f16086c26ab1.js.map} +1 -1
- package/dist/server/.next/static/chunks/{4c54a6f1b63a5c72.js → f3137530db91c282.js} +2 -2
- package/dist/server/.next/static/chunks/{0e959ec3ce9fc799.js.map → fa09d2a29cc42906.js.map} +1 -1
- package/dist/server/.next/trace +2 -2
- package/package.json +2 -2
- package/plugin-marketplace/plugins/prime-dev-cli/skills/prime-workspace/SKILL.md +112 -22
- package/skills/prime-workspace/README.md +20 -2
- package/skills/prime-workspace/SKILL.md +510 -214
- package/skills/prime-workspace/references/api-contracts.md +125 -0
- package/skills/prime-workspace/references/microfrontend-proxy.md +155 -0
- package/dist/server/.next/server/chunks/packages_server_ccc16996._.js +0 -3
- package/dist/server/.next/server/chunks/packages_server_ccc16996._.js.map +0 -1
- package/dist/server/.next/server/chunks/packages_server_d1209331._.js +0 -3
- package/dist/server/.next/server/chunks/packages_server_d1209331._.js.map +0 -1
- package/dist/server/.next/server/chunks/ssr/packages_server_src_65e3de99._.js +0 -3
- package/dist/server/.next/server/chunks/ssr/packages_server_src_65e3de99._.js.map +0 -1
- package/dist/server/.next/static/chunks/4608598ca6cc0991.js.map +0 -1
- package/dist/server/.next/static/chunks/fce82d5fa17f0367.js +0 -3
- /package/dist/server/.next/static/{TtpaZZwrnzkXloBpwEr24 → HajrbQiEu_dEojCWqcu4x}/_buildManifest.js +0 -0
- /package/dist/server/.next/static/{TtpaZZwrnzkXloBpwEr24 → HajrbQiEu_dEojCWqcu4x}/_clientMiddlewareManifest.json +0 -0
- /package/dist/server/.next/static/{TtpaZZwrnzkXloBpwEr24 → HajrbQiEu_dEojCWqcu4x}/_ssgManifest.js +0 -0
|
@@ -1,258 +1,491 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: prime-workspace
|
|
3
|
-
description:
|
|
3
|
+
description: prime-dev-cli 与它的本地工作台(packages/server,http://localhost:52741)的使用与操作说明。当用户提到 prime、prime-dev-cli、工作台/项目管理页面,或想用自然语言启动或停止某个环境(如 icrc)、查看运行状态与日志、切换代理目标、管理 Mock 场景、调整微应用绑定、切换项目或子仓库分支时使用。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# prime-workspace
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
`prime-dev-cli` 用来管理「多个互相关联的前端项目 × 多个环境」。它由三部分组成:
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
| 组成 | 位置 | 作用 |
|
|
11
|
+
| --- | --- | --- |
|
|
12
|
+
| CLI | `bin/cli.mjs`,命令名 `prime` | 同步配置、启动本地工作台 |
|
|
13
|
+
| 本地工作台 | `packages/server`,端口 **52741** | 可视化初始化工作区、配置代理/Mock/微应用、启停环境、批量 Git 操作 |
|
|
14
|
+
| 浏览器插件 | `packages/prime-dev-browser-plugin` | 把页面里的 `<micro-app>` 指到本地 host;服务地址写死 `http://localhost:52741` |
|
|
15
|
+
|
|
16
|
+
两个核心概念,别混:
|
|
17
|
+
|
|
18
|
+
- **项目(project)**:`~/Documents/prime-workspace/` 下的一个前端仓库,如 `esource-fe`、`iqc-fe`、`isource-fe`。
|
|
19
|
+
- **环境(env)**:项目内的一种运行形态,如 `icrc`、`idea`、`ilink`,各自有启动命令、本地 host、代理配置。
|
|
20
|
+
|
|
21
|
+
用户口语里说的多半是**环境名**(「帮我启动 icrc」),而接口参数多数要的是**项目名 + 环境名**同时给出。
|
|
17
22
|
|
|
18
23
|
## Preconditions
|
|
19
24
|
|
|
20
|
-
###
|
|
21
|
-
|
|
25
|
+
### 默认本地服务与可达性
|
|
26
|
+
|
|
27
|
+
- 工作台地址:`http://localhost:52741`
|
|
28
|
+
- 动手前先确认可达,例如:
|
|
29
|
+
```bash
|
|
30
|
+
curl -s -o /dev/null -w '%{http_code}' http://localhost:52741/api/admin-status
|
|
31
|
+
```
|
|
32
|
+
- 不可达时**不要编造结果**:
|
|
33
|
+
- 包安装用户 → 提示执行 `prime ui`
|
|
34
|
+
- 仓库开发者 → `pnpm run dev:server` 也行(Turbopack,同样占 52741)
|
|
35
|
+
- 工作台只在本机运行,接口默认**没有鉴权**;`--admin` 只控制前端 UI 显隐,不是服务端权限(详见「工作台」一节)。
|
|
36
|
+
|
|
37
|
+
### 关键路径速查
|
|
38
|
+
|
|
39
|
+
| 用途 | 路径 |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| 运行时配置(服务端真正读取的那份) | `~/.prime-projects.json` |
|
|
42
|
+
| 配置同步的远端 commit | `~/.prime-projects-commit` |
|
|
43
|
+
| 项目工作区根目录(**硬编码,不可配置**) | `~/Documents/prime-workspace/<projectName>` |
|
|
44
|
+
| 进程表 | `~/.prime-processes.json` |
|
|
45
|
+
| 进程日志 | `~/.prime-process-logs/<projectName>-<envName>.log` |
|
|
46
|
+
| Mock 文件 | `~/Documents/prime-workspace/<projectName>/.mock/<apiName>/<method>/<siteName>.cjs` |
|
|
47
|
+
| 多项目编辑器工作区 | `~/.prime-workspaces/<项目名排序拼接>.code-workspace` |
|
|
48
|
+
| 仓库内配置模板 | `config/projects.json`(从 GitLab 同步)、`config/projects.example.json`(离线兜底,**旧结构**) |
|
|
49
|
+
|
|
50
|
+
### 配置来源
|
|
51
|
+
|
|
52
|
+
把运行时配置当作唯一事实来源,不要依赖示例配置或旧文档。真实的 `~/.prime-projects.json` 是**以项目名为 key 的对象**(既不是数组,也没有 `workspace` / `selectedProjects` / `projects` 这些顶层字段):
|
|
53
|
+
|
|
54
|
+
```jsonc
|
|
55
|
+
{
|
|
56
|
+
"esource-fe": { // key = 项目名 = 工作区目录名
|
|
57
|
+
"repo": "https://gitlab.../esource-fe.git",
|
|
58
|
+
"mockingIntercept": false, // 项目级「Mock拦截」开关
|
|
59
|
+
"mockOpen": true, // 项目级「Mock开启」总开关(服务端会读,见 Mock 一节)
|
|
60
|
+
"envs": {
|
|
61
|
+
"icrc": { // key = 环境名
|
|
62
|
+
"host": "http://localhost:8806", // 本地访问地址,端口由 URL 尾部解析
|
|
63
|
+
"envFileName": ".env.dev.c.local", // 代理变量写入哪个 env 文件
|
|
64
|
+
"subApps": ["360-icrc", "micro-components"], // 环境名字符串数组,见「微应用」
|
|
65
|
+
"microPath": "/micro/360-icrc", // 可选,共享宿主下用于识别身份
|
|
66
|
+
"startCommand": "npm run serve:c",
|
|
67
|
+
"apiProxies": [
|
|
68
|
+
{
|
|
69
|
+
"prefix": "/api", // 必须以 / 开头,同环境内不可重复
|
|
70
|
+
"proxyKey": "PROXY_URL", // 可选,缺省按 prefix 推导
|
|
71
|
+
"currentProxy": "sit", // 当前选中的 proxyEnv key
|
|
72
|
+
"proxyEnv": {
|
|
73
|
+
"dev": "http://icrc.dev.healthprime.cn",
|
|
74
|
+
"sit": "http://icrc.sit.healthprime.cn",
|
|
75
|
+
"uat": "https://icrc-uat.primelifescience.com.cn",
|
|
76
|
+
"custom": "http://localhost:8828" // 选 custom 时 URL 不能为空
|
|
77
|
+
},
|
|
78
|
+
"rewrite": { "mode": "none" } // none | remove | replace(+targetPrefix)
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`proxyKey` 推导规则:`/api` → `PROXY_URL`;其余 `/x-y` → `PROXY_X_Y_URL`(如 `/icrc-api` → `PROXY_ICRC_API_URL`)。
|
|
88
|
+
|
|
89
|
+
## CLI 用法
|
|
90
|
+
|
|
91
|
+
命令全集(全局参数只有 `--admin`,且**仅 `ui` 识别**):
|
|
92
|
+
|
|
93
|
+
| 命令 | 行为 |
|
|
94
|
+
| --- | --- |
|
|
95
|
+
| `prime init` | 从 GitLab 拉配置,**覆盖式**写入 `~/.prime-projects.json` |
|
|
96
|
+
| `prime ui [--admin]` | 增量更新配置 → 把 `.mock` 下的 `.js` 重命名为 `.cjs` → 在 52741 启动工作台,输出 `Ready` 后自动打开浏览器 |
|
|
97
|
+
| `prime update` | 与 `init` 完全相同(覆盖式更新) |
|
|
98
|
+
| `prime version` | 打印 `prime-cli <版本>` |
|
|
99
|
+
| `prime help` | 打印帮助;无参数或未知子命令也会落到这里 |
|
|
100
|
+
|
|
101
|
+
`--admin` 必须跟在 `ui` 后面:`prime ui --admin`。它给 Next 进程注入 `PRIME_ADMIN=1`,工作台据此显示管理员 Git 操作流。
|
|
22
102
|
|
|
23
|
-
###
|
|
24
|
-
Before using any action, first verify that the local server is reachable.
|
|
103
|
+
### 配置是怎么同步的
|
|
25
104
|
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
105
|
+
- 源仓库:`https://gitlab.primelifescience.com.cn/prime-direct/fe/dev-config-source.git`
|
|
106
|
+
- 源文件:仓库内 `prime-dev-cli/config/projects.json`
|
|
107
|
+
- 临时克隆目录:`<系统临时目录>/prime-dev-config-source`
|
|
108
|
+
- 流程:临时仓库不存在则 `clone`;存在则 `fetch` 比 `origin/master` 的 hash 与 `~/.prime-projects-commit`,不同则 `pull`。
|
|
109
|
+
- 写入 `~/.prime-projects.json` 的策略**两种命令不同**:
|
|
110
|
+
- `prime ui` → `lodash.defaultsDeep(本地, 远端)`,**本地已有值优先**,远端只补缺失的 key;
|
|
111
|
+
- `prime init` / `prime update` → **整体覆盖**成远端内容。想保留本地改动就别用这两个。
|
|
112
|
+
- 兜底:GitLab 拉取失败且本地配置不存在时,复制 `config/projects.example.json`。该文件是**旧结构**,不要拿它当字段参考。
|
|
30
113
|
|
|
31
|
-
###
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
114
|
+
### 相关 npm scripts(仓库开发者)
|
|
115
|
+
|
|
116
|
+
| 命令 | 作用 |
|
|
117
|
+
| --- | --- |
|
|
118
|
+
| `pnpm run dev:server` | Turbopack 开发模式启动工作台 |
|
|
119
|
+
| `pnpm run build:server` + `pnpm run postbuild:server` | 产出 `dist/server`,`prime ui` 依赖它 |
|
|
120
|
+
| `pnpm run refresh:config` | 等价 `prime init` |
|
|
121
|
+
| `pnpm run test:root` | 跑 skill 资产测试 |
|
|
122
|
+
|
|
123
|
+
## 工作台(packages/server)
|
|
124
|
+
|
|
125
|
+
启动后自动跳到 `/initialization`。**实际注册的页面只有三个**:
|
|
126
|
+
|
|
127
|
+
| 路由 | 页面 | 用途 |
|
|
128
|
+
| --- | --- | --- |
|
|
129
|
+
| `/` | 6 行,直接 `redirect('/initialization')` | — |
|
|
130
|
+
| `/initialization` | `ProjectInitializer` | 批量克隆/初始化工作区,admin 下有批量 Git 操作流 |
|
|
131
|
+
| `/configuration?project=<项目名>&tab=<tab>` | 配置主控台 | 环境代理、MicroApp、Mock、启停环境的日常操作 |
|
|
132
|
+
|
|
133
|
+
> `src/app/code-editor/` 目录存在但**里面没有 `page.tsx`**,该路由并没有注册。别把它当页面写进文档或指给用户。
|
|
134
|
+
|
|
135
|
+
### 典型操作流程
|
|
136
|
+
|
|
137
|
+
**一、初始化**
|
|
138
|
+
1. 页面标题「项目初始化」,右上按钮先是「检查中...」,之后变「创建项目空间」。
|
|
139
|
+
2. 点「创建项目空间」→ 按钮变「初始化中...」,出现全局进度条和「正在连接服务器...」。
|
|
140
|
+
3. 项目卡片逐个显示状态:`待克隆 / 克隆中 / 已存在 / 成功 / 失败 / 不完整 / 重试中`。
|
|
141
|
+
失败卡片可点「重试」,不完整可点「清理项目」,完成后可用「在 Cursor 中打开」(可下拉切 VSCode / WebStorm)。
|
|
142
|
+
4. 结束后出现汇总卡:「初始化完成 / 总项目数 / 成功 / 失败 / 耗时: Ns」。
|
|
143
|
+
|
|
144
|
+
**二、进配置**
|
|
145
|
+
5. 点项目名(`title="点击进入项目配置"`)→ 跳到 `/configuration?project=xxx`。
|
|
146
|
+
6. 配置页头部:「{项目名} - 项目配置」、`切换项目:` 下拉、`BranchInfo` 分支条、「创建工作区」「在 Cursor 中打开」「返回初始化页面」。
|
|
147
|
+
7. Tab 栏 = 各环境名 + 一个「Mock配置」。**运行中的环境名前有紫色脉冲点**。
|
|
148
|
+
|
|
149
|
+
**三、配代理与 Mock**
|
|
150
|
+
8. 环境 Tab 左侧「{envName} 环境配置」:设 `prefix`、选「代理环境」、切「路径重写」(none/remove/replace)、「新增前缀」、「保存配置」。
|
|
151
|
+
9. 环境 Tab 右侧「MicroApp代理配置」:勾选要指向本地环境,点「保存配置」或「清空选择」;右上角有「实时/离线」状态点。
|
|
152
|
+
10. Mock Tab:「Mock拦截」「Mock开启」两个开关;「Mock接口列表」支持「新建」「刷新」「一键关闭」「一键开启」、搜索框「搜索接口地址...」;表格列「接口地址/请求方法/当前场景/开启mock/操作」,行内可「编辑」「新增场景」「删除接口」。
|
|
153
|
+
|
|
154
|
+
**四、启停与看日志**
|
|
155
|
+
11. 环境 Tab 里的「开发服务器控制」:显示「启动命令:」、状态「运行中 (PID: xxx)」/「未运行」、按钮「启动」「停止」「查看日志」,有 host 时显示「访问地址:」。未配启动命令会提示「⚠️ 该环境未配置启动命令」。
|
|
156
|
+
12. 「查看日志」打开对话框「进程日志 - {项目} - {环境}」,日志经 SSE 实时追加,显示「共 N 条日志」,可「重新连接」。
|
|
157
|
+
|
|
158
|
+
### admin 模式
|
|
159
|
+
|
|
160
|
+
`prime ui --admin` 只做一件事:让 `/api/admin-status` 返回 `isAdmin: true`,前端据此显隐整块 UI。**这些接口本身没有服务端校验**——admin 是 UI 显隐,不是权限。
|
|
161
|
+
|
|
162
|
+
`--admin` 解锁(都在 `/initialization`):
|
|
163
|
+
|
|
164
|
+
- 「UAT上线前 Git 操作流」(基线固定 `main`)
|
|
165
|
+
- 「武汉协和版本上线前 Git 操作流」(基线固定 `GWH`)
|
|
166
|
+
- 「常用 Git 分支操作」下的批量**分支合并**、批量**新建分支**、批量**删除远端分支**、批量**探测远端分支**
|
|
167
|
+
|
|
168
|
+
**不需要 admin** 也能用的:「常用 Git 分支操作」下的批量**切换分支**、批量**切换子仓库(submodules/common)分支**——这两个对普通用户开放。
|
|
169
|
+
|
|
170
|
+
### 实时更新机制
|
|
171
|
+
|
|
172
|
+
三个 SSE 端点,外加两处轮询:
|
|
173
|
+
|
|
174
|
+
| 通道 | 端点 | 消费方 |
|
|
175
|
+
| --- | --- | --- |
|
|
176
|
+
| SSE | `GET /api/initialize-workspace` | 初始化页进度与日志(一次性流,完成发 `completion` 后关闭) |
|
|
177
|
+
| SSE | `GET /api/process/logs/stream?projectName=&envName=` | 日志对话框(先推最后 100 行,再每 2 秒增量) |
|
|
178
|
+
| SSE | `GET /api/microapp-proxy-change-stream?env=` | MicroApp 配置变更广播(断线 3 秒重连,每环境最多 10 连接) |
|
|
179
|
+
| 轮询 | `GET /api/process/status` | 配置页每 **5 秒**,驱动运行状态与 Tab 脉冲点 |
|
|
180
|
+
| 轮询 | `/api/current-branch` + `/api/submodule-info` | `BranchInfo` compact **15 秒** / 普通 **30 秒** |
|
|
35
181
|
|
|
36
182
|
## Intent-first action map
|
|
37
183
|
|
|
38
|
-
|
|
184
|
+
别从 endpoint 出发,先从用户意图出发。
|
|
39
185
|
|
|
40
|
-
### 1.
|
|
41
|
-
|
|
42
|
-
- 看下工作空间状态
|
|
43
|
-
- 哪些项目还没准备好
|
|
44
|
-
- 项目空间现在什么情况
|
|
45
|
-
|
|
46
|
-
Use:
|
|
47
|
-
- `GET /api/check-workspace`
|
|
48
|
-
- `GET /api/process/status`
|
|
49
|
-
|
|
50
|
-
Return:
|
|
51
|
-
- whether workspace exists
|
|
52
|
-
- project counts
|
|
53
|
-
- existing / pending / incomplete projects
|
|
54
|
-
- currently running envs
|
|
55
|
-
|
|
56
|
-
### 2. Project drill-down
|
|
57
|
-
Typical requests:
|
|
58
|
-
- 看下 esource-fe
|
|
59
|
-
- 看下 esource-fe 分支
|
|
60
|
-
- 打开 esource-fe
|
|
61
|
-
- 给我建个 ilink-fe 和 iqc-fe 的工作区
|
|
186
|
+
### 1. 工作区状态
|
|
187
|
+
> 看下工作空间状态 · 哪些项目还没准备好 · 项目空间现在什么情况
|
|
62
188
|
|
|
63
|
-
|
|
64
|
-
- `GET /api/
|
|
65
|
-
- `GET /api/current-branch?project=<projectName>`
|
|
66
|
-
- `POST /api/open-project`
|
|
67
|
-
- `POST /api/workspace/create`
|
|
189
|
+
- `GET /api/check-workspace` — 返回 `workspaceExists`、`projects[{name,status,message,needsCleanup}]`、`summary{total,existing,pending,incomplete}`
|
|
190
|
+
- `GET /api/process/status` — 不传参返回全部环境的运行状态
|
|
68
191
|
|
|
69
|
-
|
|
70
|
-
Typical requests:
|
|
71
|
-
- 帮我启动 icrc
|
|
72
|
-
- 停掉 ilink-icrc
|
|
73
|
-
- 看看 iqc 在不在跑
|
|
74
|
-
- 打开 isource 的日志
|
|
192
|
+
回报:工作区是否存在、项目总数、已存在/待处理/不完整各多少、当前有哪些环境在跑。
|
|
75
193
|
|
|
76
|
-
|
|
77
|
-
-
|
|
78
|
-
- `DELETE /api/process/start?projectName=<projectName>&envName=<envName>`
|
|
79
|
-
- `GET /api/process/status?projectName=<projectName>&envName=<envName>`
|
|
80
|
-
- `GET /api/process/logs?projectName=<projectName>&envName=<envName>&tail=100`
|
|
81
|
-
|
|
82
|
-
When starting one env:
|
|
83
|
-
- use that env's configured `startCommand`
|
|
84
|
-
- report the access URL from that env's configured `host`
|
|
85
|
-
- prefer output like:
|
|
86
|
-
- 已启动 icrc
|
|
87
|
-
- 访问地址:`http://localhost:8806`
|
|
88
|
-
|
|
89
|
-
### 4. Mock project-level control
|
|
90
|
-
Typical requests:
|
|
91
|
-
- 打开 iqc-fe 的 mock 功能
|
|
92
|
-
- 关闭 iqc-fe 的 mock 功能
|
|
93
|
-
- 打开 iqc-fe 的 mock 拦截
|
|
94
|
-
- 关闭 iqc-fe 的 mock 拦截
|
|
194
|
+
### 2. 项目下钻
|
|
195
|
+
> 看下 esource-fe · 看下 esource-fe 分支 · 打开 esource-fe · 给我建个 ilink-fe 和 iqc-fe 的工作区
|
|
95
196
|
|
|
96
|
-
|
|
97
|
-
- `GET /api/
|
|
98
|
-
- `
|
|
197
|
+
- `GET /api/project-config?project=<项目名>`
|
|
198
|
+
- `GET /api/current-branch?project=<项目名>`
|
|
199
|
+
- `GET /api/submodule-info?project=<项目名>&subPath=submodules/common`
|
|
200
|
+
- `POST /api/open-project` body `{projectName, editor?}`(`cursor` | `vscode` | `webstorm`,默认 cursor)
|
|
201
|
+
- `POST /api/workspace/create` body `{projects[], editor?}` — 生成 `.code-workspace` 并调起编辑器
|
|
202
|
+
- `POST /api/retry-project` / `POST /api/cleanup-project` body `{projectName}`
|
|
99
203
|
|
|
100
|
-
|
|
101
|
-
-
|
|
102
|
-
- `mockingIntercept`
|
|
204
|
+
### 3. 启动 / 停止 / 状态 / 日志
|
|
205
|
+
> 帮我启动 icrc · 停掉 ilink-icrc · 看看 iqc 在不在跑 · 打开 isource 的日志
|
|
103
206
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
- 新建一个超时场景
|
|
109
|
-
- 打开这个场景
|
|
110
|
-
- 关闭这个场景
|
|
111
|
-
- 预览 GET /api/user/info 现在返回什么
|
|
112
|
-
|
|
113
|
-
Use:
|
|
114
|
-
- `GET /api/mock-file?project=<projectName>`
|
|
115
|
-
- `POST /api/mock-file`
|
|
116
|
-
- `GET /api/mock-file-content?project=<projectName>&apiName=<apiName>&method=<method>&siteName=<siteName>`
|
|
117
|
-
- `PUT /api/mock-file-content`
|
|
118
|
-
- `PUT /api/mock-setting`
|
|
119
|
-
- `PUT /api/mock-open-status`
|
|
120
|
-
- `GET /api/get-mock-data?project=<projectName>&url=<url>&method=<method>`
|
|
121
|
-
|
|
122
|
-
### 6. Mock deletion and bulk toggles
|
|
123
|
-
Typical requests:
|
|
124
|
-
- 删除这个 mock 场景
|
|
125
|
-
- 删除整个 /api/user mock 接口
|
|
126
|
-
- 一键开启所有 mock
|
|
127
|
-
- 一键关闭所有 mock
|
|
207
|
+
- `POST /api/process/start` body `{projectName, envName, startCommand}`
|
|
208
|
+
- `DELETE /api/process/start?projectName=&envName=`
|
|
209
|
+
- `GET /api/process/status?projectName=&envName=`
|
|
210
|
+
- `GET /api/process/logs?projectName=&envName=&tail=100`
|
|
128
211
|
|
|
129
|
-
|
|
130
|
-
- `DELETE /api/mock-file?project=<projectName>&apiName=<apiName>&method=<method>&siteName=<siteName>`
|
|
131
|
-
- `DELETE /api/delete-mock-api?project=<projectName>&apiName=<apiName>`
|
|
132
|
-
- `POST /api/open-all-mock`
|
|
133
|
-
- `POST /api/cleanup-mock`
|
|
212
|
+
`startCommand` 来自该环境的配置。启动成功后按 `host` 报访问地址,输出形如:
|
|
134
213
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
- 把 ilink 的 /icrc-api 切到 uat
|
|
140
|
-
- 给 ispar 新增 /idea-api
|
|
214
|
+
```
|
|
215
|
+
已启动 icrc
|
|
216
|
+
访问地址:http://localhost:8806
|
|
217
|
+
```
|
|
141
218
|
|
|
142
|
-
|
|
143
|
-
- `GET /api/project-config?project=<projectName>`
|
|
144
|
-
- `PUT /api/project-config`
|
|
219
|
+
停止是「双保险」:先按 PID `SIGTERM`→`SIGKILL`,再用 `lsof -i :<端口>` 兜底杀掉占端口的进程。所以手工用 shell 起的服务,工作台也能关掉。
|
|
145
220
|
|
|
146
|
-
###
|
|
147
|
-
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
-
|
|
221
|
+
### 4. Mock 项目级开关
|
|
222
|
+
|
|
223
|
+
> 打开 iqc-fe 的 mock 功能 · 关闭 iqc-fe 的 mock 拦截
|
|
224
|
+
|
|
225
|
+
- `GET /api/check-mock-intercept?project=<项目名>` — 同时读回 `mockingIntercept` 与 `mockOpen`
|
|
226
|
+
- `PUT /api/project-config` body `{projectName, projectConfig: {mockOpen, mockingIntercept}}`
|
|
227
|
+
|
|
228
|
+
两个开关**方向相反,别混**(工作台 UI 也是两个独立开关):
|
|
229
|
+
|
|
230
|
+
| 开关 | UI 文案 | 实际做什么 |
|
|
231
|
+
| --- | --- | --- |
|
|
232
|
+
| `mockOpen` | 「Mock开启」 | **用 Mock 顶掉后端**:请求被拦下直接返回 Mock 数据,根本不打到真实后端 |
|
|
233
|
+
| `mockingIntercept` | 「Mock拦截」 | **把真实响应录下来**:放行请求,但把后端返回的 JSON 自动落盘成一个新 Mock 场景 |
|
|
234
|
+
|
|
235
|
+
一个是「拿 Mock 当后端」,一个是「拿后端造 Mock」。想联调接口用 `mockOpen`,想攒测试数据用 `mockingIntercept`。
|
|
236
|
+
|
|
237
|
+
两个开关的真实消费方都不在工作台里,而在目标项目 dev server 依赖的 `@prime-lifescience/dev-server`——它把 `http://localhost:52741` **硬编码**为服务地址,每次请求实时回查工作台。细节见下文「Mock 是怎么生效的」。
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
### 5. Mock 场景管理
|
|
241
|
+
> 看 mock 列表 · 把 /api/user/info 切到异常场景 · 新建一个超时场景 · 打开这个场景 · 预览 GET /api/user/info 现在返回什么
|
|
242
|
+
|
|
243
|
+
- `GET /api/mock-file?project=` — 列目录树
|
|
244
|
+
- `POST /api/mock-file` body `{projectName, apiName, method, siteName, content}` — 新建场景(自动建目录与 `setting.cjs`)
|
|
245
|
+
- `GET/PUT /api/mock-file-content?...&siteName=` — 读写单个场景的 `.cjs` 源码
|
|
246
|
+
- `PUT /api/mock-setting` body `{projectName, apiName, method, currentSite}` — 切换当前场景
|
|
247
|
+
- `PUT /api/mock-open-status` body `{projectName, apiName, method, siteName, isOpen}` — 开关某场景
|
|
248
|
+
- `GET /api/get-mock-data?project=&url=&method=` — 按当前场景执行并返回数据
|
|
249
|
+
|
|
250
|
+
### 6. Mock 删除与批量
|
|
251
|
+
> 删除这个 mock 场景 · 删除整个 /api/user mock 接口 · 一键开启所有 mock · 一键关闭所有 mock
|
|
252
|
+
|
|
253
|
+
- `DELETE /api/mock-file?project=&apiName=&method=&siteName=` — 删单个场景(**不允许删到只剩一个**)
|
|
254
|
+
- `DELETE /api/delete-mock-api?project=&apiName=` — 删掉整个接口目录
|
|
255
|
+
- `POST /api/open-all-mock` body `{projectName}` — 所有场景并入 `open`
|
|
256
|
+
- `POST /api/cleanup-mock` body `{projectName}` — 清空所有 `setting.cjs` 的 `open`
|
|
257
|
+
|
|
258
|
+
### 7. 代理查看与修改
|
|
259
|
+
> 看 icrc 现在走哪个代理 · 把 icrc 切到 sitnew · 把 ilink 的 /icrc-api 切到 uat · 给 ispar 新增 /idea-api
|
|
260
|
+
|
|
261
|
+
- `GET /api/project-config?project=` — 读 `envs[envName].apiProxies`
|
|
262
|
+
- `PUT /api/project-config` body `{projectName, envName, apiProxies[]}` — 整数组回写,同时重写 env 文件
|
|
263
|
+
|
|
264
|
+
改动是**按整个 `apiProxies` 数组**回写的,所以要改单项就先读出来、改好、再整体写回。服务端会校验:`prefix` 必须以 `/` 开头且不重复、`currentProxy` 必须存在于 `proxyEnv`、`currentProxy: "custom"` 时 `proxyEnv.custom` 不能为空、`rewrite.mode` 只能是 `none|remove|replace` 且 `replace` 必须带以 `/` 开头的 `targetPrefix`。校验失败返回 400 且**不落盘**。
|
|
265
|
+
|
|
266
|
+
### 8. 微应用绑定
|
|
267
|
+
> 看 icrc 挂了哪些微应用 · 给 isource 挂上 ilink-isource · 清空 iua 的微应用代理
|
|
268
|
+
|
|
269
|
+
- `GET /api/all-projects-envs` — 汇总所有项目×环境的 `{projectName, envName, host, repo, apiProxies, subApps, microPath}`
|
|
270
|
+
- `PUT /api/microapp-proxy-config` body `{projectName, envName, selectedItems[]}`
|
|
271
|
+
|
|
272
|
+
`selectedItems` 写进 `envs[envName].subApps`,语义是**当这个环境作为宿主运行时,把这些「环境」的微应用指向各自的本地 host**。数组元素是**环境名字符串**(如 `"ilink-isource"`),不是「项目/环境」复合标识。
|
|
273
|
+
|
|
274
|
+
副作用要知道:对每个被选中的环境名,会**遍历所有项目**找出同名 env,把它的 `/api` 前缀代理改成 `currentProxy: "custom"` 且 `proxyEnv.custom` = 当前宿主的 host,并重写它们的 env 文件;同时经 SSE 广播给浏览器插件。注意只改 `/api` 这一个前缀,但**同名 env 若存在于多个项目会全部被改**。
|
|
275
|
+
|
|
276
|
+
### 9. 分支操作
|
|
277
|
+
> 看下 esource-fe 分支 · 批量切到 xxx 分支 · 批量新建分支 · 跑 UAT 上线流
|
|
278
|
+
|
|
279
|
+
- 读:`GET /api/branches?project=&subPath=`、`GET /api/current-branch?project=`、`GET /api/submodule-info?project=&subPath=`
|
|
280
|
+
- 单个切换:`POST /api/branch/switch` body `{projectName, branchName, subPath?}`
|
|
281
|
+
- 批量:`POST /api/batch-list-branches`、`POST /api/batch-switch-branch`、`POST /api/batch-list-submodule-branches`、`POST /api/batch-switch-submodule-branch`
|
|
282
|
+
- admin 批量:`POST /api/admin-git-batch-create-branch|delete-branch|merge|probe-remote-branch`
|
|
283
|
+
- 流程:`POST /api/uat-git-flow`(基线锁 `main`)、`POST /api/gwh-git-flow`(基线锁 `GWH`),两者都有 `/abort`
|
|
284
|
+
|
|
285
|
+
批量 git 接口入参是 `{projects[], ..., dryRun?}`,返回统一为 `operationLogs[]` / `feedbacks[]` / `projectResults[{projectName, success, reason?, rollbackActions?}]`。所有 git 执行都在**临时仓库**里做,`finally` 清理,不动用户的工作区克隆。
|
|
286
|
+
|
|
287
|
+
分支名规则:不含空格、不以 `-` 开头。UAT 流的 `baseBranch` 必须是 `main`,GWH 流必须是 `GWH`,传错直接 400。
|
|
288
|
+
|
|
289
|
+
## 机制说明
|
|
290
|
+
|
|
291
|
+
理解了原理,很多问题就不用猜。
|
|
292
|
+
|
|
293
|
+
### 代理是怎么生效的
|
|
294
|
+
|
|
295
|
+
工作台**不转发任何流量**。改代理配置最终做的事是:把结果写进目标项目的 env 文件(`envFileName`),内容形如:
|
|
151
296
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
-
|
|
297
|
+
```
|
|
298
|
+
PRIME_PROXY_PREFIX_MAP={"/api":"PROXY_URL","/icrc-api":"PROXY_ICRC_API_URL"}
|
|
299
|
+
PRIME_PROXY_REWRITE_MAP={"/icrc-api":"/api"}
|
|
300
|
+
PROXY_URL=http://icrc.sit.healthprime.cn
|
|
301
|
+
PROXY_ICRC_API_URL=http://...
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
真正读这些变量、做转发的是**目标项目自己的 dev server**。所以「切了代理但没生效」通常意味着:目标项目的 dev server 需要重启,或者它的 `envFileName` 指错了文件。
|
|
305
|
+
|
|
306
|
+
`PRIME_PROXY_REWRITE_MAP` 只在存在非 `none` 的 rewrite 时才写入。
|
|
307
|
+
|
|
308
|
+
### 微前端代理是怎么生效的
|
|
309
|
+
|
|
310
|
+
微前端代理做的事:**把页面里 `<micro-app>` 元素指向的远端子应用,改成指向你本地的 dev server**。它和接口代理是两条独立链路——前者由浏览器插件改 DOM 属性,后者由 dev server 改请求去向。
|
|
311
|
+
|
|
312
|
+
整条链路要三个角色齐活:工作台存 `subApps` 配置 → 插件在主世界改写 `url` → 页面加载本地子应用。
|
|
313
|
+
|
|
314
|
+
**第一步:配置怎么存。** `PUT /api/microapp-proxy-config` body `{envName, projectName, selectedItems[]}`,`selectedItems` 是**环境名字符串数组**,写进 `envs[envName].subApps`。同时有个容易踩的副作用:对每个被选中的环境名,会**遍历所有项目**找出同名 env,把它的 `/api` 前缀代理改成 `proxyEnv.custom = <当前宿主 host>`——只改 `/api` 这一个前缀,但**同名 env 跨项目全改**。
|
|
315
|
+
|
|
316
|
+
**第二步:插件怎么拿到配置。** 插件把 `http://localhost:52741` 硬编码为服务地址,`fetch /api/all-projects-envs` 拿全量项目×环境,存进 `localStorage` 的 `microapp-subapps-details`。注入方式是 `runAt: 'document_start'` 的 content script 把脚本注入页面**主世界**——必须在 `micro-app` 被 `customElements.define` 之前运行,因为核心手段就是劫持 `customElements.define`。
|
|
317
|
+
|
|
318
|
+
**第三步:怎么决定改写到哪个 host。** 两级判定:
|
|
319
|
+
|
|
320
|
+
1. **`microPath` 优先**:共享宿主(`micro-app.*` 域名)下兄弟子应用 **hostname 相同**,靠域名分不开,所以用 `microPath` 认身份——看元素的 `default-page` 或 `url` 是否**包含**该值,多个命中取**最长最具体**的(避免 `/micro/360-icrc` 误吸 `/micro/360-icrc-site`)。
|
|
321
|
+
2. **hostname 兜底**:没有 microPath 命中时,用各环境 `proxyEnv`(新结构为 `apiProxies[].proxyEnv`)的 URL **只比域名**。
|
|
322
|
+
|
|
323
|
+
两级都遵守同一条铁律:**只有该 env 在 `subApps` 里才改写**。而且 microPath 一旦识别出身份,若不在 `subApps` 里就**保持远端并直接返回,绝不回落到 hostname 兜底**——否则只勾 `micro-components` 时,`360-icrc-site` 会被同宿主下已勾选的兄弟子应用错误吸附。
|
|
324
|
+
|
|
325
|
+
只处理三个标签:`micro-app` / `micro-app-ilink` / `micro-app-ijudge`。
|
|
326
|
+
|
|
327
|
+
**第四步:怎么刷新。** 插件订阅 `microapp-proxy-change-stream?env=`,收到变更后提示「MicroApp配置已更新,页面将在3秒后刷新」,3 秒后 **`window.location.reload()` 整页刷新**。断线重连最多 5 次、间隔 3 秒。
|
|
328
|
+
|
|
329
|
+
**排查顺序**(前两条是前提,别跳过):
|
|
330
|
+
|
|
331
|
+
1. 插件装了没 —— 没插件整条链路都不生效
|
|
332
|
+
2. 工作台起着没 —— 地址硬编码,没起来就拉不到配置,插件直接跳过(日志 `[MicroApp Hack] 跳过:无有效配置`)
|
|
333
|
+
3. 该环境在不在 `subApps` 里
|
|
334
|
+
4. 控制台日志会明说结论:`[MicroApp] URL已替换: ...`、`[MicroApp] microPath识别为「X」但未勾选,保持远端: ...`
|
|
335
|
+
|
|
336
|
+
完整的匹配算法、时序处理、`disable-patch-request` 规则和已知坑见 `references/microfrontend-proxy.md`。
|
|
337
|
+
|
|
338
|
+
### Mock 是怎么组织的
|
|
339
|
+
|
|
340
|
+
```
|
|
341
|
+
<workspace>/<项目>/.mock/<apiName>/<method>/<siteName>.cjs ← 一个场景
|
|
342
|
+
<workspace>/<项目>/.mock/<apiName>/<method>/setting.cjs ← 该接口的当前状态
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
- `apiName` = 接口 URL 去掉 query、去掉开头的 `/`、把 `/` 换成 `_`(`/api/user/info` → `api_user_info`,空则为 `root`)
|
|
346
|
+
- `method` 段小写(`get` / `post`)
|
|
347
|
+
- `siteName` 就是用户口语里的**「场景」**
|
|
348
|
+
|
|
349
|
+
`setting.cjs` 长这样:
|
|
350
|
+
|
|
351
|
+
```js
|
|
352
|
+
module.exports = {
|
|
353
|
+
currentSite: 'success', // 当前生效的场景(单选)
|
|
354
|
+
open: ['success', '异常场景'] // 允许生效的场景(多选)
|
|
355
|
+
};
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
`/api/get-mock-data` 要求 `currentSite ∈ open`,否则报「当前场景 "X" 未开启Mock功能」;项目级 `mockOpen` 为 false 时报「Mock功能未开启」。
|
|
359
|
+
|
|
360
|
+
场景文件里可以直接用 Mock.js,服务端已把 `mockjs` 注入 `Module.prototype.require`:
|
|
361
|
+
|
|
362
|
+
```js
|
|
363
|
+
const Mock = require('mockjs');
|
|
364
|
+
module.exports = Mock.mock({
|
|
365
|
+
code: 200,
|
|
366
|
+
message: '请求成功',
|
|
367
|
+
data: { 'id|1-100': 1, name: '@cname', 'status|1': ['a', 'b'] }
|
|
368
|
+
});
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
完整占位符规则见 prime-dev-cli 仓库的 `packages/server/MOCKJS_EXAMPLES.md`。
|
|
372
|
+
|
|
373
|
+
> 「mock 文件必须叫 `.cjs`」是有原因的:场景文件用 CommonJS 写,而不少项目 `package.json` 里是 `"type": "module"`,`.js` 会 `require` 不了。所以 `prime ui` 每次启动都会把 `.mock` 下的 `.js` 递归重命名为 `.cjs`(幂等,失败只告警不阻断启动)。
|
|
374
|
+
|
|
375
|
+
### Mock 是怎么生效的
|
|
376
|
+
|
|
377
|
+
**工作台本身不拦截任何请求**,它只提供配置与数据。真正做拦截的是目标项目 dev server 里的 `@prime-lifescience/dev-server`,它把 `http://localhost:52741` 硬编码为服务地址,在代理链路上实时回查工作台:
|
|
378
|
+
|
|
379
|
+
| 时机 | 读取 | 条件 | 行为 | 响应头信号 |
|
|
380
|
+
| --- | --- | --- | --- | --- |
|
|
381
|
+
| 请求发出前(`onProxyReq`) | `GET /api/check-mock-intercept?project=` | `mockOpen` 为真 | 再调 `/api/get-mock-data`,拿到数据就**直接返回并中断代理**,请求不会到真实后端 | `X-FROM-MOCK: true`、`Content-Type: application/json`、`X-Real-Origin: http://localhost:52741` |
|
|
382
|
+
| 响应回来时(`onProxyRes`) | 同上 | `mockingIntercept` 为真 | 放行真实响应,把响应体转成 `module.exports = <JSON>;` **落盘成新场景** | `X-MOCK-FILE-CREATED: true` / 失败 `X-MOCK-FILE-CREATE-FAIL: true` |
|
|
383
|
+
|
|
384
|
+
补充细节:
|
|
385
|
+
|
|
386
|
+
- `mockingIntercept` 录制时,`apiName` 按同样的规则从请求路径推导,场景名固定为 **「默认场景」**。也就是说:「Mock拦截」开着时,你每刷新一次页面,真实接口的返回就会被记成一个叫「默认场景」的 Mock 文件。重复请求会不断覆盖同一个场景。
|
|
387
|
+
- 只录制 JSON / text 类响应,带 `attachment` 的下载响应跳过。
|
|
388
|
+
- `text/event-stream`(SSE)两类拦截都跳过,原样透传。
|
|
389
|
+
- 代理环境也走这条链路:dev server 直接读 env 文件里的 `PRIME_PROXY_PREFIX_MAP` / `PRIME_PROXY_REWRITE_MAP` 自建代理,不经过工作台转发。
|
|
390
|
+
|
|
391
|
+
**由此推出三条排查结论:**
|
|
392
|
+
|
|
393
|
+
- 工作台没启动 → `check-mock-intercept` 请求失败 → 目标项目的 **Mock 和代理会一起静默失效**,且不报错。
|
|
394
|
+
- 「Mock 没生效」 → 先看 `mockOpen`,再看该接口 `setting.cjs` 里 `currentSite` 在不在 `open` 数组里(不满足时报「当前场景 "X" 未开启Mock功能」)。
|
|
395
|
+
- 想确认是不是 Mock 生效了 → 看响应头有没有 `X-FROM-MOCK: true`;想确认有没有被录制 → 看 `.mock` 下是不是多了「默认场景」,或响应头 `X-MOCK-FILE-CREATED`。
|
|
396
|
+
|
|
397
|
+
### 进程是怎么管的
|
|
398
|
+
|
|
399
|
+
- 进程表 `~/.prime-processes.json`,元素 `{key, projectName, envName, startTime, port, pid}`,`key` 为 `"<projectName>-<envName>"`。
|
|
400
|
+
- 启动在 `~/Documents/prime-workspace/<项目>` 下 `spawn(cmd, {shell: true, env: {...NODE_ENV: 'development'}})`,端口取自 `envs[envName].host` 的尾部。
|
|
401
|
+
- 启动后等 2 秒,若子进程已 `killed` 视为失败。
|
|
402
|
+
- 状态判断靠 `process.kill(pid, 0)` + `lsof` 探端口,**没有心跳**。查询全部时会顺带探测配置里所有环境的端口,把「手工起的」项目也标成 `running: true, pid: 0`。
|
|
403
|
+
- 日志 `~/.prime-process-logs/<项目>-<环境>.log`,单文件 5MB 轮转、保留 3 个历史、7 天过期。
|
|
155
404
|
|
|
156
405
|
## Natural-language routing rules
|
|
157
406
|
|
|
158
|
-
###
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
407
|
+
### 项目名 vs 环境名
|
|
408
|
+
|
|
409
|
+
两种形态都要能识别:`project` / `projectName` 与 `env` / `envName`。
|
|
410
|
+
|
|
411
|
+
解释优先级:
|
|
412
|
+
|
|
413
|
+
- 启动 / 停止 / 日志 / 代理 / 微应用 → 优先当**环境**
|
|
414
|
+
- 打开项目 / 看分支 / 创建工作区 → 优先当**项目**
|
|
415
|
+
|
|
416
|
+
例子:
|
|
417
|
+
|
|
418
|
+
- 「帮我启动 icrc」→ `icrc` 是环境
|
|
419
|
+
- 「打开 ilink-fe」→ `ilink-fe` 是项目
|
|
420
|
+
- 「打开 ilink」→ 有歧义,问一句是项目还是环境
|
|
421
|
+
|
|
422
|
+
对不上时先去 `~/.prime-projects.json` 里找这个 key:能当项目名命中,就是项目;只在某个项目的 `envs` 下命中,就是环境。一个环境名可能对应多个项目,那就问。
|
|
162
423
|
|
|
163
|
-
|
|
164
|
-
- start / stop / logs / proxy / microapp -> prefer **env**
|
|
165
|
-
- open project / branch / workspace creation -> prefer **project**
|
|
424
|
+
### 访问地址规则
|
|
166
425
|
|
|
167
|
-
|
|
168
|
-
- `帮我启动 icrc` -> treat `icrc` as an env
|
|
169
|
-
- `打开 ilink-fe` -> treat `ilink-fe` as a project
|
|
170
|
-
- `打开 ilink` -> ambiguous, ask whether the user means the project or the env
|
|
426
|
+
环境在跑或刚启动时,面向用户的 URL 取该环境的 `host`。进程接口即使也返回了 `port`,展示时仍以 `host` 为准。
|
|
171
427
|
|
|
172
|
-
###
|
|
173
|
-
When an env is running or has just been started:
|
|
174
|
-
- derive the user-facing URL from that env's configured `host`
|
|
175
|
-
- if process APIs also return a port, still prefer `host` as the primary display URL
|
|
428
|
+
### 「项目空间」vs「工作区」是两个意图
|
|
176
429
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
- “创建项目空间” -> initialize/repair local repos
|
|
180
|
-
- “创建工作区” -> create/open a multi-project editor workspace
|
|
430
|
+
- 「创建**项目空间**」→ `POST /api/initialize-workspace`,克隆/修复本地仓库
|
|
431
|
+
- 「创建**工作区**」→ `POST /api/workspace/create`,生成多项目编辑器工作区文件
|
|
181
432
|
|
|
182
|
-
|
|
433
|
+
别合并成一个动作。
|
|
183
434
|
|
|
184
435
|
## Confirmation matrix
|
|
185
436
|
|
|
186
|
-
|
|
187
|
-
- deleting one mock scene
|
|
188
|
-
- deleting a whole mock API
|
|
189
|
-
- opening all mock scenes
|
|
190
|
-
- closing all mock scenes
|
|
191
|
-
- changing microapp selections
|
|
192
|
-
- changing proxies when multiple prefixes may match
|
|
437
|
+
动手前必须先确认,并说清为什么:
|
|
193
438
|
|
|
194
|
-
|
|
439
|
+
| 操作 | 为什么 |
|
|
440
|
+
| --- | --- |
|
|
441
|
+
| 删除一个 Mock 场景 | 删了就没了,无法从工作台恢复 |
|
|
442
|
+
| 删除整个 Mock 接口 | 上一条 × N |
|
|
443
|
+
| 一键开启 / 一键关闭所有 Mock | 影响该项目全部接口的联调表现 |
|
|
444
|
+
| 修改微应用绑定 | 有连带副作用(会改被选中环境的 `/api` 代理并重写 env 文件) |
|
|
445
|
+
| 代理修改且存在多个可能匹配的 prefix | 改错前缀会让请求打到错误后端 |
|
|
446
|
+
| 批量 Git 操作(切分支、新建、删除、合并、UAT/GWH 流) | 影响多个仓库甚至推送远端 |
|
|
447
|
+
| 清理项目(`cleanup-project`) | 递归删除工作区内的项目目录 |
|
|
195
448
|
|
|
196
449
|
## Required input rules
|
|
197
450
|
|
|
198
|
-
###
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
- target proxy name or custom URL
|
|
214
|
-
- optional rewrite settings
|
|
215
|
-
|
|
216
|
-
If the env has multiple prefixes and the user did not specify which one, ask.
|
|
217
|
-
|
|
218
|
-
### Mock scene operations
|
|
219
|
-
For mock scene operations, determine:
|
|
220
|
-
- `projectName`
|
|
221
|
-
- `apiName`
|
|
222
|
-
- `method`
|
|
223
|
-
- `siteName`
|
|
224
|
-
|
|
225
|
-
Use “scene” as the user-facing term.
|
|
226
|
-
|
|
227
|
-
### MicroApp edits
|
|
228
|
-
For microapp operations, determine:
|
|
229
|
-
- `projectName`
|
|
230
|
-
- `envName`
|
|
231
|
-
- `selectedItems`
|
|
232
|
-
|
|
233
|
-
Important:
|
|
234
|
-
- `selectedItems` are env-name strings
|
|
235
|
-
- they are not full project/env identifiers
|
|
236
|
-
- explain this if the operation may affect expectations
|
|
451
|
+
### 启动一个环境
|
|
452
|
+
|
|
453
|
+
要凑齐:`projectName`、`envName`、该环境的 `startCommand`、该环境的 `host`。环境名能唯一对上一个配置就往下走,多个匹配就问。
|
|
454
|
+
|
|
455
|
+
### 代理修改
|
|
456
|
+
|
|
457
|
+
要凑齐:`projectName`、`envName`、目标 `prefix`、目标 proxy 名或自定义 URL、可选的 rewrite 设置。环境里有多个 prefix 而用户没说哪个,就问。
|
|
458
|
+
|
|
459
|
+
### Mock 场景操作
|
|
460
|
+
|
|
461
|
+
要凑齐:`projectName`、`apiName`、`method`、`siteName`。对用户统一用「场景」这个词。
|
|
462
|
+
|
|
463
|
+
### 微应用修改
|
|
464
|
+
|
|
465
|
+
要凑齐:`projectName`、`envName`、`selectedItems`。注意 `selectedItems` 是**环境名**而不是完整标识,且会连带改代理——必要时主动说明。
|
|
237
466
|
|
|
238
467
|
## Request examples
|
|
239
468
|
|
|
240
|
-
###
|
|
469
|
+
### 查工作区状态
|
|
470
|
+
|
|
241
471
|
```http
|
|
242
472
|
GET /api/check-workspace
|
|
243
473
|
```
|
|
244
474
|
|
|
245
|
-
###
|
|
475
|
+
### 查项目配置
|
|
476
|
+
|
|
246
477
|
```http
|
|
247
478
|
GET /api/project-config?project=esource-fe
|
|
248
479
|
```
|
|
249
480
|
|
|
250
|
-
###
|
|
481
|
+
### 查单个环境状态
|
|
482
|
+
|
|
251
483
|
```http
|
|
252
484
|
GET /api/process/status?projectName=esource-fe&envName=icrc
|
|
253
485
|
```
|
|
254
486
|
|
|
255
|
-
###
|
|
487
|
+
### 启动一个环境
|
|
488
|
+
|
|
256
489
|
```http
|
|
257
490
|
POST /api/process/start
|
|
258
491
|
Content-Type: application/json
|
|
@@ -264,7 +497,32 @@ Content-Type: application/json
|
|
|
264
497
|
}
|
|
265
498
|
```
|
|
266
499
|
|
|
267
|
-
###
|
|
500
|
+
### 切换代理目标
|
|
501
|
+
|
|
502
|
+
```http
|
|
503
|
+
PUT /api/project-config
|
|
504
|
+
Content-Type: application/json
|
|
505
|
+
|
|
506
|
+
{
|
|
507
|
+
"projectName": "esource-fe",
|
|
508
|
+
"envName": "icrc",
|
|
509
|
+
"apiProxies": [
|
|
510
|
+
{
|
|
511
|
+
"prefix": "/api",
|
|
512
|
+
"currentProxy": "sitnew",
|
|
513
|
+
"proxyEnv": {
|
|
514
|
+
"dev": "http://icrc.dev.healthprime.cn",
|
|
515
|
+
"sitnew": "http://icrc.sitnew.healthprime.cn",
|
|
516
|
+
"custom": "http://localhost:8828"
|
|
517
|
+
},
|
|
518
|
+
"rewrite": { "mode": "none" }
|
|
519
|
+
}
|
|
520
|
+
]
|
|
521
|
+
}
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### 切换当前 Mock 场景
|
|
525
|
+
|
|
268
526
|
```http
|
|
269
527
|
PUT /api/mock-setting
|
|
270
528
|
Content-Type: application/json
|
|
@@ -277,19 +535,23 @@ Content-Type: application/json
|
|
|
277
535
|
}
|
|
278
536
|
```
|
|
279
537
|
|
|
280
|
-
###
|
|
538
|
+
### 新建一个 Mock 场景
|
|
539
|
+
|
|
281
540
|
```http
|
|
282
|
-
|
|
541
|
+
POST /api/mock-file
|
|
283
542
|
Content-Type: application/json
|
|
284
543
|
|
|
285
544
|
{
|
|
286
|
-
"projectName": "
|
|
287
|
-
"
|
|
288
|
-
"
|
|
545
|
+
"projectName": "iqc-fe",
|
|
546
|
+
"apiName": "api_user_info",
|
|
547
|
+
"method": "get",
|
|
548
|
+
"siteName": "超时场景",
|
|
549
|
+
"content": "const Mock = require('mockjs');\nmodule.exports = Mock.mock({ code: 504, message: '超时' });"
|
|
289
550
|
}
|
|
290
551
|
```
|
|
291
552
|
|
|
292
|
-
###
|
|
553
|
+
### 更新微应用绑定
|
|
554
|
+
|
|
293
555
|
```http
|
|
294
556
|
PUT /api/microapp-proxy-config
|
|
295
557
|
Content-Type: application/json
|
|
@@ -301,21 +563,35 @@ Content-Type: application/json
|
|
|
301
563
|
}
|
|
302
564
|
```
|
|
303
565
|
|
|
566
|
+
### 创建多项目工作区
|
|
567
|
+
|
|
568
|
+
```http
|
|
569
|
+
POST /api/workspace/create
|
|
570
|
+
Content-Type: application/json
|
|
571
|
+
|
|
572
|
+
{
|
|
573
|
+
"projects": ["ilink-fe", "iqc-fe"],
|
|
574
|
+
"editor": "cursor"
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
完整路由契约(含 admin 批量 Git、UAT/GWH 流程、SSE 帧格式)见 `references/api-contracts.md`。
|
|
579
|
+
|
|
304
580
|
## Friendly usage examples
|
|
305
581
|
|
|
306
|
-
###
|
|
582
|
+
### 工作区 / 项目 / 分支
|
|
307
583
|
- 看下工作空间状态
|
|
308
584
|
- 打开 esource-fe
|
|
309
585
|
- 给我建个 ilink-fe 和 iqc-fe 的工作区
|
|
310
586
|
- 看下 esource-fe 分支
|
|
311
587
|
|
|
312
|
-
###
|
|
588
|
+
### 启动 / 停止 / 状态 / 日志
|
|
313
589
|
- 帮我启动 icrc
|
|
314
590
|
- 停掉 ilink-icrc
|
|
315
591
|
- 看看 iqc 在不在跑
|
|
316
592
|
- 打开 isource 的日志
|
|
317
593
|
|
|
318
|
-
###
|
|
594
|
+
### 代理
|
|
319
595
|
- 看 icrc 现在走哪个代理
|
|
320
596
|
- 把 icrc 切到 sitnew
|
|
321
597
|
- 把 ilink 的 /icrc-api 切到 uat
|
|
@@ -337,11 +613,31 @@ Content-Type: application/json
|
|
|
337
613
|
|
|
338
614
|
## Failure handling
|
|
339
615
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
-
|
|
343
|
-
-
|
|
616
|
+
接口失败时:
|
|
617
|
+
|
|
618
|
+
- 说清是哪个动作失败了
|
|
619
|
+
- 判断原因属于哪一类:项目不存在 / 环境不存在 / 本地工作区没克隆 / 参数不合法 / 工作台没启动 / 目标项目 dev server 需要重启
|
|
620
|
+
- **不要编造缺失的值**
|
|
621
|
+
|
|
622
|
+
请求有歧义时:只问一个窄问题,优先在动手前把项目/环境/prefix/场景的歧义澄清掉。
|
|
623
|
+
|
|
624
|
+
几个常见报错的含义:
|
|
625
|
+
|
|
626
|
+
| 报错 | 含义 |
|
|
627
|
+
| --- | --- |
|
|
628
|
+
| `该环境已经在运行中` | 该 `projectName-envName` 已在进程表里 |
|
|
629
|
+
| `项目目录不存在` | 工作区里还没克隆该项目,先去 `/initialization` 初始化 |
|
|
630
|
+
| `未找到运行中的进程(端口未被占用)` | 进程表和端口都没探到 |
|
|
631
|
+
| `Mock功能未开启` | 项目级 `mockOpen` 为 false |
|
|
632
|
+
| `当前场景 "X" 未开启Mock功能` | `currentSite` 不在 `setting.cjs` 的 `open` 里 |
|
|
633
|
+
| `不能删除最后一个场景,每个接口至少需要保留一个场景` | 每个接口至少保留一个场景 |
|
|
634
|
+
| `缺少必要参数,请填写完整后重试。` | 批量 git 接口入参不全 |
|
|
635
|
+
| `分支名称不合法,请避免空格或以 - 开头。` | 分支名校验失败 |
|
|
636
|
+
|
|
637
|
+
## 参考
|
|
344
638
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
-
|
|
639
|
+
| 文件 | 内容 |
|
|
640
|
+
| --- | --- |
|
|
641
|
+
| `references/api-contracts.md` | 全部 API 路由的方法、参数、响应契约,以及三个 SSE 端点的帧格式 |
|
|
642
|
+
| `references/microfrontend-proxy.md` | 微前端代理的完整实现:匹配算法、时序处理、`disable-patch-request` 规则、已知坑 |
|
|
643
|
+
| prime-dev-cli 仓库 `packages/server/MOCKJS_EXAMPLES.md` | Mock.js 占位符与规则示例 |
|