zdashboard 1.6.2 → 2.1.0
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/README.md +225 -41
- package/dist/cli.js +1388 -804
- package/dist/cli.js.map +1 -1
- package/dist/web/assets/MdViewer-C8ZG_xn1.js +1 -0
- package/dist/web/assets/Workspace-Cz1A_IXM.js +1 -0
- package/dist/web/assets/file-text-DqCOBCjz.js +6 -0
- package/dist/web/assets/index-B9eiA0v2.js +29 -0
- package/dist/web/assets/index-D58_bWw5.css +1 -0
- package/dist/web/assets/index-DkOVCCZ3.js +90 -0
- package/dist/web/assets/katex-BTcE7LSd.css +10 -0
- package/dist/web/assets/katex.min-DAmb8ZJI.js +270 -0
- package/dist/web/assets/web-8ZBVzAEO.js +26 -0
- package/dist/web/assets/web-CEyEoz0i.js +30 -0
- package/dist/web/assets/web-CXHaDUKR.js +25 -0
- package/dist/web/assets/{Viewer-CvXxR4rr.js → web-CrX-i-rZ.js} +7 -2
- package/dist/web/assets/web-D_b3sVrp.js +31 -0
- package/dist/web/assets/web-M4KeFgZw.js +2 -0
- package/dist/web/assets/{Viewer-DgUxcwns.js → web-Y4h9oNHC.js} +3 -3
- package/dist/web/index.html +2 -2
- package/package.json +4 -1
- package/dist/web/assets/DesignViewer-DIFMIK04.js +0 -26
- package/dist/web/assets/ReviewViewer-CzphymDs.js +0 -31
- package/dist/web/assets/ViewViewer-2gv2jIkV.js +0 -11
- package/dist/web/assets/folder-open-YuFnfZTO.js +0 -6
- package/dist/web/assets/index-BJ8mveF-.js +0 -446
- package/dist/web/assets/index-BwdPhy39.css +0 -10
- package/dist/web/assets/index-CgsmLt7m.js +0 -2
- package/dist/web/assets/index-D5XUdKxi.js +0 -2
- package/dist/web/assets/index-LAcTTLE0.js +0 -2
- package/dist/web/assets/index-Nmrw-5B2.js +0 -2
- package/dist/web/assets/index-f9TDtJW5.js +0 -2
package/README.md
CHANGED
|
@@ -2,69 +2,252 @@
|
|
|
2
2
|
|
|
3
3
|
ZCode skill 的通用 dashboard 平台。核心不动,skill 自带 viewer,未来 N 个 dashboard 自然接入。
|
|
4
4
|
|
|
5
|
-
## 架构
|
|
5
|
+
## 架构 (v2.0)
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
zdashboard/ ← 一个核心包,永远不写业务逻辑
|
|
9
9
|
├── src/
|
|
10
|
-
│ ├──
|
|
11
|
-
│ │ ├──
|
|
12
|
-
│ │ ├──
|
|
13
|
-
│ │
|
|
14
|
-
│ └──
|
|
15
|
-
│
|
|
16
|
-
│
|
|
17
|
-
├──
|
|
18
|
-
│ ├── bugs/
|
|
19
|
-
│ ├──
|
|
20
|
-
│ ├──
|
|
21
|
-
│
|
|
22
|
-
└──
|
|
10
|
+
│ ├── core/
|
|
11
|
+
│ │ ├── server.ts ← HTTP server + route/SSE 注册表
|
|
12
|
+
│ │ ├── reload.ts ← fs.watch → SSE broadcast
|
|
13
|
+
│ │ ├── tree.ts ← /__files 文件树
|
|
14
|
+
│ │ └── manifest.ts ← /__plugins 插件清单
|
|
15
|
+
│ ├── plugins/ ← 内置 plugins(随核心发版)
|
|
16
|
+
│ │ ├── stats/ ← 项目统计(文件/目录/大小/扩展名 Top10)
|
|
17
|
+
│ │ ├── just/ ← Just Runner 任务执行
|
|
18
|
+
│ │ ├── bugs/ ← 禅道 Bugs 只读列表
|
|
19
|
+
│ │ ├── review/ ← 文档评审状态流转
|
|
20
|
+
│ │ ├── apply/ ← OpenSpec change 执行进度
|
|
21
|
+
│ │ ├── design/ ← 设计资产分类浏览
|
|
22
|
+
│ │ └── view/ ← 项目浏览(文件预览)
|
|
23
|
+
│ ├── web/ ← SPA 前端(Vite + React)
|
|
24
|
+
│ │ ├── App.tsx ← Shell:Topbar + IconRail + Workspace + StatusBar
|
|
25
|
+
│ │ ├── layout/ ← IconRail、StatusBar
|
|
26
|
+
│ │ ├── home/ ← HomeGrid 插件卡片
|
|
27
|
+
│ │ ├── components/ ← shared UI(button、card、tooltip...)
|
|
28
|
+
│ │ ├── viewers/ ← Markdown/Image/Code/Unsupported 预览器
|
|
29
|
+
│ │ └── hooks/ ← useSSE
|
|
30
|
+
│ └── server/ ← 后端 helpers(detect、scan、just-runner...)
|
|
31
|
+
├── package.json
|
|
32
|
+
└── README.md
|
|
23
33
|
```
|
|
24
34
|
|
|
35
|
+
## 设计原则
|
|
36
|
+
|
|
37
|
+
1. **核心不动**:`src/core/` 提供 HTTP server、SSE、文件树、插件清单,不写任何业务逻辑
|
|
38
|
+
2. **插件自包含**:每个 mode 在 `src/plugins/<mode>/` 内完成前后端(`index.ts` + `web.tsx` + `Workspace.tsx`)
|
|
39
|
+
3. **Cordis 生命周期**:用 `ctx.effect(() => () => dispose())` 管理清理,`ctx.server.route/sse` 注册路由
|
|
40
|
+
4. **SPA 首页**:`GET /` 直接返回 `index.html`,前端 hash 驱动 mode 切换(`#<mode>`)
|
|
41
|
+
|
|
25
42
|
## Plugin 约定
|
|
26
43
|
|
|
27
|
-
|
|
44
|
+
每个内置 plugin 提供:
|
|
28
45
|
|
|
29
46
|
```
|
|
30
|
-
|
|
31
|
-
├── index.ts ←
|
|
32
|
-
├──
|
|
33
|
-
└──
|
|
47
|
+
src/plugins/<mode>/
|
|
48
|
+
├── index.ts ← 后端:注册 /__<mode>* 路由
|
|
49
|
+
├── web.tsx ← 前端 manifest(mode、label、icon、Workspace)
|
|
50
|
+
└── Workspace.tsx ← 前端页面组件
|
|
34
51
|
```
|
|
35
52
|
|
|
36
53
|
```ts
|
|
37
|
-
//
|
|
54
|
+
// src/plugins/<mode>/web.tsx
|
|
55
|
+
import { lazy } from 'react';
|
|
56
|
+
import Workspace from './Workspace.js';
|
|
57
|
+
|
|
38
58
|
export default {
|
|
39
|
-
mode: '
|
|
40
|
-
label: '
|
|
59
|
+
mode: '<mode>',
|
|
60
|
+
label: '显示名',
|
|
41
61
|
icon: '🎯',
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
62
|
+
description: '简短描述',
|
|
63
|
+
Workspace: lazy(() => import('./Workspace.js')),
|
|
64
|
+
} as const;
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
可选 `Sidebar` 槽(如 view、design 提供侧栏):
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import Sidebar from './Sidebar.js';
|
|
71
|
+
|
|
72
|
+
export default {
|
|
73
|
+
mode: '<mode>',
|
|
74
|
+
label: '显示名',
|
|
75
|
+
icon: '🎯',
|
|
76
|
+
description: '简短描述',
|
|
77
|
+
Sidebar: lazy(() => import('./Sidebar.js')),
|
|
78
|
+
Workspace: lazy(() => import('./Workspace.js')),
|
|
79
|
+
} as const;
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
// src/plugins/<mode>/index.ts
|
|
84
|
+
export default {
|
|
85
|
+
inject: ['server'] as const,
|
|
86
|
+
apply(ctx: Context, config: { root: string }) {
|
|
87
|
+
const server = (ctx as any).server;
|
|
88
|
+
if (!server?.route) return;
|
|
89
|
+
|
|
90
|
+
server.route('/__<mode>', async (req, res) => {
|
|
91
|
+
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });
|
|
92
|
+
res.end(JSON.stringify({ /* ... */ }));
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
外部 plugin 放在 `--plugins <dir>` 下,结构同上,核心启动时自动扫描 `index.{ts,js,mjs}` 加载。
|
|
99
|
+
|
|
100
|
+
### 外部插件编写指南
|
|
101
|
+
|
|
102
|
+
外部插件允许自带静态 viewer 页面,通过 iframe 嵌入 dashboard。
|
|
103
|
+
|
|
104
|
+
**目录结构**
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
my-skill/
|
|
108
|
+
├── index.ts ← 必填:cordis 插件定义
|
|
109
|
+
└── web/ ← 可选:静态 viewer 目录
|
|
110
|
+
├── index.html
|
|
111
|
+
└── assets/...
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**index.ts 约定**
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import type { Context } from 'cordis';
|
|
118
|
+
|
|
119
|
+
export default {
|
|
120
|
+
inject: ['server', 'dashboard'] as const,
|
|
121
|
+
apply(ctx: Context, config: { root: string }) {
|
|
122
|
+
const server = (ctx as any).server;
|
|
123
|
+
const dashboard = (ctx as any).dashboard;
|
|
124
|
+
if (!server?.route || !dashboard?.register) return;
|
|
125
|
+
|
|
126
|
+
// 注册后端 API
|
|
127
|
+
server.route('/__my-api', (req, res) => {
|
|
128
|
+
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });
|
|
129
|
+
res.end(JSON.stringify({ ok: true }));
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// 注册 manifest(mode === 目录名时,若有 web/index.html 会自动填充 viewerUrl)
|
|
133
|
+
dashboard.register({
|
|
134
|
+
mode: 'my-skill', // 必须与目录名一致才能自动填充 viewerUrl
|
|
135
|
+
label: 'My Skill',
|
|
136
|
+
icon: '🧩',
|
|
137
|
+
description: '描述',
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
};
|
|
48
141
|
```
|
|
49
142
|
|
|
50
|
-
|
|
51
|
-
1. 加载内置 plugins(`src/plugins/`)
|
|
52
|
-
2. 扫描 `--plugins` 目录加载外部 plugins
|
|
53
|
-
3. 根据 `--mode` 激活对应 plugin
|
|
143
|
+
> 外部插件必须 `export default`(cordis `ctx.plugin()` 只接受函数或带 `apply` 的 default 对象)。
|
|
54
144
|
|
|
55
|
-
|
|
145
|
+
**web/ 约定**
|
|
146
|
+
|
|
147
|
+
- `web/index.html` 必须存在才会被自动服务
|
|
148
|
+
- 自动挂载在 `/__plugin/<目录名>/`,例如目录 `my-skill` 对应 `/__plugin/my-skill/`
|
|
149
|
+
- 页面内可通过相对路径引用同目录资源(js/css/图片)
|
|
150
|
+
- 页面内可调用插件注册的 API(如 `/__my-api`),与 dashboard 同源
|
|
151
|
+
|
|
152
|
+
**viewerUrl 覆盖**
|
|
153
|
+
|
|
154
|
+
如果需要在 manifest 中显式指定 viewerUrl,可直接写:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
dashboard.register({
|
|
158
|
+
mode: 'my-skill',
|
|
159
|
+
label: 'My Skill',
|
|
160
|
+
icon: '🧩',
|
|
161
|
+
description: '描述',
|
|
162
|
+
viewerUrl: '/custom-path/',
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
显式声明的 `viewerUrl` 优先于自动填充值。
|
|
167
|
+
|
|
168
|
+
**热刷新**
|
|
169
|
+
|
|
170
|
+
外部 viewer 的 HTML 文件会自动注入 reload 脚本(与 dashboard SPA 一致),修改 `web/index.html` 后浏览器会自动刷新。
|
|
171
|
+
|
|
172
|
+
**沙箱说明**
|
|
173
|
+
|
|
174
|
+
前端以 iframe 渲染 viewer,sandbox 属性设置为:
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
allow-scripts allow-same-origin allow-forms allow-popups
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
保留同源能力(可访问 dashboard 的 `/__*` API);允许表单与弹窗(viewer 内 `window.open` 外链场景)。
|
|
181
|
+
|
|
182
|
+
**无 web 目录的插件**
|
|
183
|
+
|
|
184
|
+
若插件目录没有 `web/index.html`,前端仍会显示插件卡片,但进入时展示占位页(不报错)。
|
|
185
|
+
|
|
186
|
+
## CLI 用法
|
|
56
187
|
|
|
57
188
|
```bash
|
|
58
|
-
#
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
189
|
+
# 基本用法
|
|
190
|
+
pnpm build
|
|
191
|
+
node dist/cli.js --dir <项目根> --port 4190
|
|
192
|
+
|
|
193
|
+
# 打开浏览器
|
|
194
|
+
node dist/cli.js --dir <项目根> --port 4190 --open
|
|
195
|
+
|
|
196
|
+
# 启动后直达某个 mode(拼 #<mode>)
|
|
197
|
+
node dist/cli.js --dir <项目根> --port 4190 --page design
|
|
198
|
+
|
|
199
|
+
# 加载外部 plugins
|
|
200
|
+
node dist/cli.js --dir <项目根> --port 4190 --plugins ./my-plugins
|
|
66
201
|
```
|
|
67
202
|
|
|
203
|
+
### 环境变量
|
|
204
|
+
|
|
205
|
+
- `PORT`:默认 4190(未被 `--port` 覆盖时)
|
|
206
|
+
|
|
207
|
+
### 内置路由
|
|
208
|
+
|
|
209
|
+
| 路由 | 方法 | 说明 |
|
|
210
|
+
|------|------|------|
|
|
211
|
+
| `/` | GET | SPA 首页 |
|
|
212
|
+
| `/__config` | GET | `{ stopToken, version, root }` |
|
|
213
|
+
| `/__stop` | POST | `x-stop-token` 鉴权,干净退出 |
|
|
214
|
+
| `/__plugins` | GET | 内置 + 外部插件清单 |
|
|
215
|
+
| `/__files` | GET | 文件树(openspec/docs 过滤) |
|
|
216
|
+
| `/__reload` | SSE | `reload` + `files` 事件 |
|
|
217
|
+
| `/__just/recipes` | GET | just 任务列表 |
|
|
218
|
+
| `/__just/logs` | SSE | just 实时日志 |
|
|
219
|
+
| `/__just/{start,stop,restart}` | POST | just 任务控制 |
|
|
220
|
+
| `/__bugs` | GET | 禅道 bug 列表 |
|
|
221
|
+
| `/__review` | GET | 评审项列表 |
|
|
222
|
+
| `/__review/item` | POST | 更新评审项 |
|
|
223
|
+
| `/__review/status` | POST | 更新评审状态 |
|
|
224
|
+
| `/__docs` | GET | 项目文档列表 |
|
|
225
|
+
| `/__apply` | GET | OpenSpec changes 列表 |
|
|
226
|
+
| `/__apply/change` | GET | `?name=<change>` 详情 |
|
|
227
|
+
| `/__design/assets` | GET | 设计资产扫描 |
|
|
228
|
+
| `/__stats/data` | GET | 项目统计(内置 stats 插件) |
|
|
229
|
+
| `/__notes/data` | GET | 便签列表(examples/notes 示例) |
|
|
230
|
+
| `/__notes/save` | POST | 保存便签(`x-stop-token` 鉴权) |
|
|
231
|
+
|
|
232
|
+
## 前端路由
|
|
233
|
+
|
|
234
|
+
前端用 hash 驱动 mode:
|
|
235
|
+
|
|
236
|
+
- `/#<mode>` 激活对应 plugin Workspace
|
|
237
|
+
- `/#` 或空 hash 回到 HomeGrid
|
|
238
|
+
- IconRail 点击自动写 hash
|
|
239
|
+
- 浏览器前进/后退由 `hashchange` 事件处理
|
|
240
|
+
|
|
241
|
+
## 技术栈
|
|
242
|
+
|
|
243
|
+
- **运行时**:Node.js 20+,ESM,`node:` 前缀
|
|
244
|
+
- **核心框架**:Cordis 4.0.0-rc.8(Context + Service + inject)
|
|
245
|
+
- **前端**:React 18 + Vite 5 + Tailwind 3
|
|
246
|
+
- **组件库**:Radix UI(tooltip、separator、scroll-area、slot)
|
|
247
|
+
- **HTTP**:Node `http` 模块(无 express 依赖)
|
|
248
|
+
- **构建**:tsup(CLI) + Vite(SPA)
|
|
249
|
+
- **包管理**:pnpm
|
|
250
|
+
|
|
68
251
|
## 迁移状态
|
|
69
252
|
|
|
70
253
|
- [x] zview-dashboard → zdashboard(v1.0.0)
|
|
@@ -72,3 +255,4 @@ npx zdashboard --mode bugs --dir /path/to/project --port 4190
|
|
|
72
255
|
- [x] zdesign-dashboard → zdashboard plugin(v1.2.0)
|
|
73
256
|
- [x] zapply execution progress → zdashboard plugin(v1.3.3)
|
|
74
257
|
- [x] zskills skill SKILL.md 统一调用 zdashboard
|
|
258
|
+
- [x] v2.0 cordis 重写:core 不动,插件自包含,SPA 首页
|