draftgo-cli 3.0.1 → 3.0.29
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 +67 -17
- package/package.json +13 -8
- package/resources/skill/SKILL.md +118 -22
- package/resources/skill/core/architecture.md +4 -24
- package/resources/skill/core/modules.md +14 -4
- package/resources/skill/init/SKILL.md +3 -4
- package/resources/skill/practices/anti-patterns.md +14 -4
- package/resources/skill/practices/best-practices.md +25 -6
- package/resources/skill/practices/dev-declaration.md +23 -3
- package/resources/skill/pull/SKILL.md +9 -1
- package/resources/skill/push/SKILL.md +103 -68
- package/resources/skill/quickref/api-endpoints.md +63 -41
- package/resources/skill/quickref/api.json +5084 -4975
- package/resources/skill/quickref/app-api.md +4 -14
- package/resources/skill/rules/dev-workflow.md +154 -57
- package/resources/skill/rules/frontend.md +569 -21
- package/resources/skill/rules/parallel.md +10 -10
- package/resources/skill/scripts/__pycache__/draftgo_pull.cpython-312.pyc +0 -0
- package/resources/skill/scripts/__pycache__/draftgo_push.cpython-312.pyc +0 -0
- package/resources/skill/scripts/draftgo_delete.py +0 -2
- package/resources/skill/scripts/draftgo_init.py +15 -3
- package/resources/skill/scripts/draftgo_pull.py +154 -87
- package/resources/skill/scripts/draftgo_push.py +363 -174
- package/resources/skill/specs/custom-services.md +199 -0
- package/resources/skill/specs/data.md +195 -5
- package/resources/skill/specs/db-relations.md +227 -0
- package/resources/skill/specs/runtime.md +30 -0
- package/resources/skill/specs/security.md +3 -3
- package/resources/skill/specs/ui-protocol.md +79 -48
- package/resources/skill/story/SKILL.md +2 -7
- package/src/cli.js +9 -0
- package/src/commands/api.js +59 -0
- package/src/commands/autoPush.js +41 -0
- package/src/commands/check.js +27 -17
- package/src/commands/delete.js +6 -4
- package/src/commands/deploy.js +31 -0
- package/src/commands/doctor.js +1 -1
- package/src/commands/help.js +27 -9
- package/src/commands/init.js +17 -2
- package/src/commands/map.js +18 -7
- package/src/commands/new.js +20 -17
- package/src/commands/sync.js +10 -3
- package/src/commands/update.js +15 -56
- package/src/commands/upgrade.js +52 -0
- package/src/commands/verifyUi.js +199 -0
- package/src/index.js +12 -1
- package/src/localdev/compose.js +8 -1
- package/src/platforms.js +3 -3
- package/src/projectConfig.js +11 -1
- package/src/projectMap.js +274 -39
- package/src/skill.js +113 -29
- package/src/updateCheck.js +37 -5
- package/resources/skill/quickref/dg-components.md +0 -198
|
@@ -89,10 +89,40 @@ const orderId = query.orderId; // "42"
|
|
|
89
89
|
|
|
90
90
|
| config_key | 用途 |
|
|
91
91
|
|---|---|
|
|
92
|
+
| `frontend_global_enabled` | 前端全局层总开关 |
|
|
93
|
+
| `frontend_global_safe_mode` | 全局层安全模式;开启后仅保留平台内置反馈能力,不执行自定义全局注入 |
|
|
92
94
|
| `frontend_global_head_html` | 注入壳层 head |
|
|
93
95
|
| `frontend_global_body_html` | 注入壳层 body 末尾 |
|
|
94
96
|
| `frontend_global_css` / `_js` | 壳层全局 CSS/JS |
|
|
95
97
|
| `frontend_global_iframe_head_html` | 注入每个业务页面 iframe head |
|
|
96
98
|
| `frontend_global_widget_html/css/js` | 全局挂件层 |
|
|
99
|
+
| `frontend_global_toast_position` | Toast 位置:`top-center` / `top-right` / `top-left` / `bottom-center` / `bottom-right` / `bottom-left` / `center` |
|
|
100
|
+
| `frontend_global_toast_scale` | Toast 大小比例,范围 `0.5-3`,文字、图标、间距、圆角等同比例缩放 |
|
|
101
|
+
| `frontend_global_toast_opacity` | Toast 背景透明度,范围 `0-100`,只影响背景,不影响文字和按钮 |
|
|
102
|
+
| `frontend_global_toast_duration_success` | 成功 Toast 默认停留时间,存储单位:毫秒 |
|
|
103
|
+
| `frontend_global_toast_duration_error` | 错误 Toast 默认停留时间,存储单位:毫秒 |
|
|
104
|
+
| `frontend_global_toast_duration_warning` | 警告 Toast 默认停留时间,存储单位:毫秒 |
|
|
105
|
+
| `frontend_global_toast_duration_info` | 信息 Toast 默认停留时间,存储单位:毫秒 |
|
|
106
|
+
| `frontend_global_toast_css` | Toast 自定义 CSS,只建议调整视觉,不要破坏 `.dg-toast` 基础结构 |
|
|
107
|
+
| `frontend_global_scrollbar_color_mode` | 滚动条颜色模式:`theme` 跟随系统主题 / `custom` 自定义颜色 |
|
|
108
|
+
| `frontend_global_scrollbar_color` | 自定义滚动条颜色,建议使用 `#RRGGBB` |
|
|
109
|
+
| `frontend_global_scrollbar_buttons` | 是否显示滚动条两端按钮;不支持的浏览器会自动退化 |
|
|
110
|
+
| `frontend_global_scrollbar_opacity` | 滚动条滑块透明度,范围 `0-100` |
|
|
111
|
+
| `frontend_global_scrollbar_radius` | 滚动条圆角,单位 px |
|
|
112
|
+
| `frontend_global_scrollbar_width` | 滚动条宽度,单位 px |
|
|
97
113
|
|
|
98
114
|
规则:**不能在业务页面内重复实现全局层能力;不允许新增槽位,只能编辑内置槽位。**
|
|
115
|
+
|
|
116
|
+
### 修改和推送方法
|
|
117
|
+
|
|
118
|
+
本地修改来自 `.draftgo/system_config/index.json`。修改前先执行 `/draftgo pull system_config` 获取最新值,改完后执行:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
python {{SKILL_SCRIPTS}}/draftgo_push.py system_config frontend_global_toast_opacity
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
也可以通过 skill 命令使用 `/draftgo push system_config frontend_global_toast_opacity`。
|
|
125
|
+
|
|
126
|
+
前端全局层是系统默认配置。通过 API 或脚本更新现有全局配置时,只发送 `config_value`;不要带 `description`、`category`、`value_type`、`status` 等元信息,否则旧基座或旧索引容易触发“系统默认字段不允许修改字段描述/分类/状态”。`draftgo_push.py system_config` 已对 `frontend_global_*` 自动只推值。
|
|
127
|
+
|
|
128
|
+
页面管理中 Toast 时长以秒输入,`sys_config` 中仍以毫秒存储。例如 UI 中 `错误 Toast 时长(s) = 4.5`,本地索引应写 `frontend_global_toast_duration_error.config_value = 4500`。
|
|
@@ -47,9 +47,7 @@ read_when: 开发前检查合规性时 · Code Review 时
|
|
|
47
47
|
|
|
48
48
|
| ❌ 禁止 | ✅ 替代 |
|
|
49
49
|
|---|---|
|
|
50
|
-
|
|
|
51
|
-
| 把 `dg-*` 当 daisyUI / Bootstrap / Ant Design | `dg-*` 只能是 shadcn 的 HTML 协议形态 |
|
|
52
|
-
| 硬编码 hex / rgb / rgba 颜色 | 用 `var(--dg-*)` 语义 token |
|
|
50
|
+
| 硬编码 hex / rgb / rgba 颜色 | 优先用系统主题 `var(--dg-*)` 语义 token;品牌/图表/用户指定配色必须同时适配浅色与深色 |
|
|
53
51
|
| 在页面内读 `localStorage.dg_theme` | `App.theme` |
|
|
54
52
|
|
|
55
53
|
---
|
|
@@ -66,6 +64,8 @@ read_when: 开发前检查合规性时 · Code Review 时
|
|
|
66
64
|
|
|
67
65
|
## 颜色 Token 参考
|
|
68
66
|
|
|
67
|
+
默认优先采用系统主题配色:页面直接引用 `var(--dg-*)`,跟随壳层当前浅色 / 深色模式。只有页面不搭配、品牌要求、用户明确指定或图表多系列等场景才允许自主配色;自主配色必须提供浅色与深色两套变量或 `[data-theme="light"]` / `[data-theme="dark"]` 覆盖,并满足 WCAG AA 对比度。
|
|
68
|
+
|
|
69
69
|
| Token | 用途 |
|
|
70
70
|
|---|---|
|
|
71
71
|
| `--dg-bg-base` / `--dg-bg-page` / `--dg-bg-surface` | 背景层级 |
|
|
@@ -1,68 +1,99 @@
|
|
|
1
1
|
---
|
|
2
|
-
read_when:
|
|
2
|
+
read_when: 开发数据库页面时需要真实 shadcn/Radix 组件能力 · 了解 data-ui bridge 协议时
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
#
|
|
5
|
+
# shadcn Page Runtime Bridge 协议
|
|
6
6
|
|
|
7
7
|
## 核心认知
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
dg-* ≠ 自研组件库
|
|
11
|
-
dg-* = shadcn/ui 在数据库 HTML 页面里的协议化表达
|
|
12
|
-
```
|
|
9
|
+
数据库页面不进入 Vite/React 编译链,不能写 TSX、React import 或 shadcn 组件源码。
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
DraftGo 页面默认写普通 HTML + Tailwind CSS + 页面级 CSS。只有显式带 `data-ui` 的节点会交给 shadcn page runtime bridge 接管,普通 `<table>`、`<button>`、自定义 HTML 不会被强制改造成 shadcn。
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
```
|
|
14
|
+
普通 HTML / Tailwind / CSS → 页面作者完全控制
|
|
15
|
+
data-ui 节点 → DraftGo bridge 挂载真实 shadcn/Radix
|
|
16
|
+
```
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## 当前稳定协议
|
|
19
19
|
|
|
20
|
-
|
|
|
20
|
+
| 能力 | HTML 写法 | 底层 |
|
|
21
21
|
|---|---|---|
|
|
22
|
-
| Button |
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
22
|
+
| Button | `<button data-ui="button">` | shadcn Button |
|
|
23
|
+
| Static Table | `<div data-ui="table"><table>...</table></div>` | shadcn Table 样式增强 |
|
|
24
|
+
| DropdownMenu | `data-ui="dropdown-menu-trigger/content/item/separator"` | Radix DropdownMenu |
|
|
25
|
+
| DataTable | `<div data-ui="data-table" data-source="pages">` | DraftGo 数据源 + shadcn Table |
|
|
26
|
+
|
|
27
|
+
## 示例
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<div data-ui="table">
|
|
31
|
+
<table>
|
|
32
|
+
<thead>
|
|
33
|
+
<tr>
|
|
34
|
+
<th>Product</th>
|
|
35
|
+
<th>Price</th>
|
|
36
|
+
<th data-align="right">Actions</th>
|
|
37
|
+
</tr>
|
|
38
|
+
</thead>
|
|
39
|
+
<tbody>
|
|
40
|
+
<tr>
|
|
41
|
+
<td data-weight="medium">Wireless Mouse</td>
|
|
42
|
+
<td>$29.99</td>
|
|
43
|
+
<td data-align="right">
|
|
44
|
+
<button data-ui="dropdown-menu-trigger" data-variant="ghost" data-size="icon">
|
|
45
|
+
<span data-icon="more-horizontal"></span>
|
|
46
|
+
<span class="sr-only">Open menu</span>
|
|
47
|
+
</button>
|
|
48
|
+
<div data-ui="dropdown-menu-content" data-align="end">
|
|
49
|
+
<button data-ui="dropdown-menu-item">Edit</button>
|
|
50
|
+
<button data-ui="dropdown-menu-item">Duplicate</button>
|
|
51
|
+
<div data-ui="dropdown-menu-separator"></div>
|
|
52
|
+
<button data-ui="dropdown-menu-item" data-variant="destructive">Delete</button>
|
|
53
|
+
</div>
|
|
54
|
+
</td>
|
|
55
|
+
</tr>
|
|
56
|
+
</tbody>
|
|
57
|
+
</table>
|
|
58
|
+
</div>
|
|
59
|
+
```
|
|
45
60
|
|
|
46
|
-
|
|
61
|
+
```html
|
|
62
|
+
<div
|
|
63
|
+
data-ui="data-table"
|
|
64
|
+
data-source="pages"
|
|
65
|
+
data-page-size="12"
|
|
66
|
+
data-columns='[
|
|
67
|
+
{"key":"id","title":"ID"},
|
|
68
|
+
{"key":"title","title":"标题"},
|
|
69
|
+
{"key":"route","title":"路由"},
|
|
70
|
+
{"key":"status","title":"状态","type":"badge"}
|
|
71
|
+
]'>
|
|
72
|
+
</div>
|
|
73
|
+
```
|
|
47
74
|
|
|
48
|
-
##
|
|
75
|
+
## Tailwind 规则
|
|
49
76
|
|
|
50
|
-
`
|
|
51
|
-
- `variant`、`size`、`disabled`、`default-value`、`data-state`、`aria-*` 保持原意
|
|
52
|
-
- 复杂组件使用 `data-dg-props='{"key":"value"}'` 传递结构化配置
|
|
77
|
+
Page 资产仍然以 Tailwind HTML 为主。完整页面需要任意 Tailwind 原子类时,继续使用本地 `/assets/tailwindcss.js` 或已有页面模板;禁止外部 CDN。
|
|
53
78
|
|
|
54
|
-
|
|
79
|
+
bridge 注入的 CSS 只保证 `data-ui` 组件需要的 shadcn/Tailwind 样式,不负责动态编译数据库 HTML 中任意 Tailwind class。
|
|
55
80
|
|
|
56
|
-
##
|
|
81
|
+
## 主题规则
|
|
57
82
|
|
|
58
|
-
|
|
59
|
-
- ❌ `dg-*` 不是 Bootstrap
|
|
60
|
-
- ❌ `dg-*` 不是 Ant Design / Element Plus
|
|
61
|
-
- ❌ `dg-*` 不是任意相似样式的泛称
|
|
62
|
-
- ✅ `dg-*` 只能是 shadcn 的 DraftGo HTML 协议形态
|
|
83
|
+
DraftGo 主题变量是唯一主题源头。bridge 组件只消费由 DraftGo token 映射出的 shadcn CSS variables:
|
|
63
84
|
|
|
64
|
-
|
|
85
|
+
- `--dg-bg-page` -> `--background`
|
|
86
|
+
- `--dg-text-primary` -> `--foreground`
|
|
87
|
+
- `--dg-bg-surface` -> `--card`
|
|
88
|
+
- `--dg-modal-bg` -> `--popover`
|
|
89
|
+
- `--dg-border` -> `--border`
|
|
90
|
+
- `--dg-action` / `--dg-brand` / `--dg-accent` -> `--primary`
|
|
91
|
+
- `--dg-action-fg` -> `--primary-foreground`
|
|
92
|
+
- `--dg-error` -> `--destructive`
|
|
93
|
+
- `--dg-radius` -> `--radius`
|
|
65
94
|
|
|
66
|
-
##
|
|
95
|
+
## 禁止
|
|
67
96
|
|
|
68
|
-
|
|
97
|
+
- 不要把 `data-ui` 当成 Bootstrap、daisyUI、Ant Design 或 Element Plus。
|
|
98
|
+
- 不要在数据库 HTML 里写 JSX/TSX/React import。
|
|
99
|
+
- 不要把普通 HTML 强制包成 shadcn;只有用户明确需要组件能力时才加 `data-ui`。
|
|
@@ -91,8 +91,6 @@ now:
|
|
|
91
91
|
3. 整个对话期间,Story 作为最高优先级上下文锚定
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
**Gate 不可妥协**:开发者说"加个页面",AI 必须先确保 Story 存在,再动手。
|
|
95
|
-
|
|
96
94
|
---
|
|
97
95
|
|
|
98
96
|
## 构建流程
|
|
@@ -102,7 +100,7 @@ now:
|
|
|
102
100
|
```
|
|
103
101
|
扫描 .draftgo/ 下的数据,判断走哪条路径:
|
|
104
102
|
|
|
105
|
-
├─ 存在用户自建内容(非 tag="系统" 的页面、db_meta、custom_scripts
|
|
103
|
+
├─ 存在用户自建内容(非 tag="系统" 的页面、db_meta、custom_scripts)→ 路径 A
|
|
106
104
|
├─ 用户提供了设计文档(PRD、原型图描述、需求文档等)→ 路径 A(以文档为分析素材)
|
|
107
105
|
└─ 只有内置系统页面,无用户自建内容,无设计文档 → 路径 B(对话采集)
|
|
108
106
|
```
|
|
@@ -117,7 +115,6 @@ now:
|
|
|
117
115
|
- .draftgo/navigations/index.json → 导航结构
|
|
118
116
|
- .draftgo/db_meta/index.json → 数据模型
|
|
119
117
|
- .draftgo/custom_scripts/index.json → 自定义脚本
|
|
120
|
-
- .draftgo/external_apis/index.json → 外部 API
|
|
121
118
|
- .draftgo/changelog.md → 更新日志
|
|
122
119
|
- .draftgo/lessons/ → 开发经验记录
|
|
123
120
|
- .draftgo/Task/ → 历史任务文档
|
|
@@ -242,15 +239,13 @@ AI 在开发过程中检测到"方向性决策"时,主动提议沉淀:
|
|
|
242
239
|
| `identity.*` | 极少 | 仅重大方向转向时(冲突检测中确认) |
|
|
243
240
|
| `design.overview` | 里程碑级 | 核心流转发生结构性变化时更新 |
|
|
244
241
|
| `design.modules` | 新增模块时 | 只增/改,不删已有模块(模块下线标注即可) |
|
|
245
|
-
| `decisions` | 只增不删 |
|
|
242
|
+
| `decisions` | 只增不删 | supersede 时不删旧的只标记 |
|
|
246
243
|
| `now.focus` | 周/里程碑 | 对话结束时 AI 提议更新 |
|
|
247
244
|
| `now.next` | 周 | 同上 |
|
|
248
245
|
| `now.open_questions` | 随时 | 出现新的悬而未决事项 |
|
|
249
246
|
| `meta.last_touched` | 每次更新 | 自动 |
|
|
250
247
|
| `meta.maturity` | 手动 | seed→growing: 首次确认后; growing→stable: 决策≥5条且identity不再变 |
|
|
251
248
|
|
|
252
|
-
**decisions ID 编号规则:** D001 起递增,永不复用,永不删除。
|
|
253
|
-
|
|
254
249
|
---
|
|
255
250
|
|
|
256
251
|
## 操作流程汇总
|
package/src/cli.js
CHANGED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const log = require('../logger');
|
|
6
|
+
|
|
7
|
+
const API_FILE = path.resolve(__dirname, '..', '..', 'resources', 'skill', 'quickref', 'api.json');
|
|
8
|
+
|
|
9
|
+
function apiCommand(positional, flags = {}) {
|
|
10
|
+
const keyword = String(positional.join(' ') || '').trim().toLowerCase();
|
|
11
|
+
if (!keyword) {
|
|
12
|
+
log.err('用法:draftgo api <keyword>');
|
|
13
|
+
log.dim(' 示例:draftgo api pages batch');
|
|
14
|
+
return 1;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let spec;
|
|
18
|
+
try {
|
|
19
|
+
spec = JSON.parse(fs.readFileSync(API_FILE, 'utf8'));
|
|
20
|
+
} catch (err) {
|
|
21
|
+
log.err(`无法读取 OpenAPI:${err.message}`);
|
|
22
|
+
return 1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const words = keyword.split(/\s+/).filter(Boolean);
|
|
26
|
+
const matches = [];
|
|
27
|
+
for (const [route, methods] of Object.entries(spec.paths || {})) {
|
|
28
|
+
for (const [method, operation] of Object.entries(methods || {})) {
|
|
29
|
+
if (!['get', 'post', 'put', 'patch', 'delete', 'head', 'options'].includes(method.toLowerCase())) continue;
|
|
30
|
+
const haystack = [route, method, operation.summary, operation.operationId, ...(operation.tags || [])]
|
|
31
|
+
.filter(Boolean).join(' ').toLowerCase();
|
|
32
|
+
if (!words.every((word) => haystack.includes(word))) continue;
|
|
33
|
+
matches.push({
|
|
34
|
+
method: method.toUpperCase(),
|
|
35
|
+
route,
|
|
36
|
+
summary: operation.summary || '',
|
|
37
|
+
operationId: operation.operationId || '',
|
|
38
|
+
tags: operation.tags || [],
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (flags.output === 'json') {
|
|
44
|
+
console.log(JSON.stringify(matches, null, 2));
|
|
45
|
+
return matches.length ? 0 : 1;
|
|
46
|
+
}
|
|
47
|
+
if (!matches.length) {
|
|
48
|
+
log.warn(`未找到包含“${keyword}”的 API。`);
|
|
49
|
+
return 1;
|
|
50
|
+
}
|
|
51
|
+
log.title(`draftgo api — ${keyword}`);
|
|
52
|
+
for (const item of matches.slice(0, 50)) {
|
|
53
|
+
console.log(` ${item.method.padEnd(7)} ${item.route}${item.summary ? ` ${item.summary}` : ''}`);
|
|
54
|
+
}
|
|
55
|
+
if (matches.length > 50) log.dim(` 仅显示前 50 条,共 ${matches.length} 条;使用 --output json 获取完整结果。`);
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = apiCommand;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const log = require('../logger');
|
|
6
|
+
const check = require('./check');
|
|
7
|
+
const sync = require('./sync');
|
|
8
|
+
|
|
9
|
+
function autoPush(projectDir, positional, flags = {}) {
|
|
10
|
+
const configPath = path.join(projectDir, '.draftgo', 'config.json');
|
|
11
|
+
if (!fs.existsSync(configPath)) {
|
|
12
|
+
log.dim('自动推送未执行:未连接 DraftGo 服务器(缺少 .draftgo/config.json)。');
|
|
13
|
+
return 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let config;
|
|
17
|
+
try {
|
|
18
|
+
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
19
|
+
} catch (err) {
|
|
20
|
+
log.err(`自动推送未执行:config.json 解析失败:${err.message}`);
|
|
21
|
+
return 1;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
log.step('auto-push: 先执行 check …');
|
|
25
|
+
const checkCode = check(projectDir, { strict: flags.strict });
|
|
26
|
+
if (checkCode !== 0) {
|
|
27
|
+
log.err('自动推送终止:check 未通过,请修复后重试。');
|
|
28
|
+
return checkCode;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (config.auto_push !== true) {
|
|
32
|
+
log.dim('自动推送已跳过:check 已通过,但 .draftgo/config.json 的 auto_push 不为 true。');
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
log.step('auto_push=true:开始 push …');
|
|
37
|
+
const pushArgs = flags.batch ? ['--batch', ...positional] : positional;
|
|
38
|
+
return sync(projectDir, 'push', pushArgs, flags);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = autoPush;
|
package/src/commands/check.js
CHANGED
|
@@ -14,39 +14,49 @@ function check(projectDir, flags = {}) {
|
|
|
14
14
|
log.title('draftgo check');
|
|
15
15
|
log.info(`项目目录:${projectDir}`);
|
|
16
16
|
|
|
17
|
+
const m = result.map;
|
|
17
18
|
console.log('');
|
|
18
|
-
|
|
19
|
+
const overview = [
|
|
20
|
+
['pages', m.pages.length],
|
|
21
|
+
['nav', m.navigations.length],
|
|
22
|
+
['db', m.db_meta.length],
|
|
23
|
+
['scripts', m.custom_scripts.length],
|
|
24
|
+
['aihub', m.aihub.length],
|
|
25
|
+
['docs', m.docs.length],
|
|
26
|
+
];
|
|
27
|
+
console.log(' ' + overview.map(([k, v]) => `${log.c.cyan(k)} ${v}`).join(' '));
|
|
28
|
+
const pageAreas = [
|
|
29
|
+
['home', m.pageGroups.home.length],
|
|
30
|
+
['admin', m.pageGroups.admin.length],
|
|
31
|
+
['business', m.pageGroups.business.length],
|
|
32
|
+
['system', m.pageGroups.system.length],
|
|
33
|
+
];
|
|
34
|
+
console.log(' ' + pageAreas.map(([k, v]) => `${log.c.cyan(k)} ${v}`).join(' '));
|
|
19
35
|
|
|
20
36
|
if (result.errors.length) {
|
|
21
37
|
console.log('');
|
|
22
|
-
console.log(
|
|
23
|
-
result.errors.forEach((msg) => console.log(` - ${msg}`));
|
|
38
|
+
result.errors.forEach((msg) => console.log(` ${log.c.red('x')} ${msg}`));
|
|
24
39
|
}
|
|
25
40
|
|
|
26
41
|
if (result.warnings.length) {
|
|
27
42
|
console.log('');
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
console.log('');
|
|
34
|
-
log.ok('未发现明显闭环问题。');
|
|
43
|
+
result.warnings.forEach((msg) => {
|
|
44
|
+
const detail = (result.warningDetails || []).find((item) => item.message === msg);
|
|
45
|
+
const prefix = detail ? `[${detail.code}/${detail.confidence}] ` : '';
|
|
46
|
+
console.log(` ${log.c.yellow('!')} ${prefix}${msg}`);
|
|
47
|
+
});
|
|
35
48
|
}
|
|
36
49
|
|
|
50
|
+
console.log('');
|
|
37
51
|
if (result.errors.length) {
|
|
38
|
-
|
|
39
|
-
console.log(`${log.c.red('x')} 检查未通过:请先修复错误。`);
|
|
52
|
+
log.err('检查未通过:请先修复错误。');
|
|
40
53
|
return 1;
|
|
41
54
|
}
|
|
42
55
|
if (flags.strict && result.warnings.length) {
|
|
43
|
-
|
|
44
|
-
console.log(`${log.c.red('x')} strict 模式:存在提醒项,检查未通过。`);
|
|
56
|
+
log.err('strict 模式:存在提醒项,检查未通过。');
|
|
45
57
|
return 1;
|
|
46
58
|
}
|
|
47
|
-
|
|
48
|
-
console.log('');
|
|
49
|
-
log.ok(result.warnings.length ? '检查完成:存在提醒项,建议开发代理处理后再 push。' : '检查通过。');
|
|
59
|
+
log.ok(result.warnings.length ? '检查完成(有提醒项)。' : '检查通过。');
|
|
50
60
|
return 0;
|
|
51
61
|
}
|
|
52
62
|
|
package/src/commands/delete.js
CHANGED
|
@@ -30,8 +30,6 @@ const TYPE_ALIASES = {
|
|
|
30
30
|
docs: 'docs',
|
|
31
31
|
doc_category: 'doc_categories',
|
|
32
32
|
doc_categories: 'doc_categories',
|
|
33
|
-
external_api: 'external_apis',
|
|
34
|
-
external_apis: 'external_apis',
|
|
35
33
|
aihub: 'aihub',
|
|
36
34
|
};
|
|
37
35
|
|
|
@@ -40,7 +38,7 @@ async function deleteResource(projectDir, positional, flags) {
|
|
|
40
38
|
|
|
41
39
|
if (!typeRaw || !id) {
|
|
42
40
|
log.err('用法:draftgo delete <type> <id>');
|
|
43
|
-
log.dim(' 支持类型:pages | nav | db_meta | custom_scripts | docs | doc_categories |
|
|
41
|
+
log.dim(' 支持类型:pages | nav | db_meta | custom_scripts | docs | doc_categories | aihub');
|
|
44
42
|
return 1;
|
|
45
43
|
}
|
|
46
44
|
|
|
@@ -80,7 +78,11 @@ async function deleteResource(projectDir, positional, flags) {
|
|
|
80
78
|
stdio: 'inherit',
|
|
81
79
|
shell: false,
|
|
82
80
|
});
|
|
83
|
-
|
|
81
|
+
if (r.error) {
|
|
82
|
+
log.err(`删除脚本启动失败:${r.error.message}`);
|
|
83
|
+
return 1;
|
|
84
|
+
}
|
|
85
|
+
return Number.isInteger(r.status) ? r.status : 1;
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
module.exports = deleteResource;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const log = require('../logger');
|
|
4
|
+
const check = require('./check');
|
|
5
|
+
const sync = require('./sync');
|
|
6
|
+
|
|
7
|
+
function deploy(projectDir, positional, flags = {}) {
|
|
8
|
+
const delivery = String(flags.delivery || 'deploy').toLowerCase();
|
|
9
|
+
if (!['local', 'preview', 'deploy'].includes(delivery)) {
|
|
10
|
+
log.err('--delivery 只支持 local、preview、deploy。');
|
|
11
|
+
return 1;
|
|
12
|
+
}
|
|
13
|
+
log.step('deploy: 先执行 check …');
|
|
14
|
+
const checkCode = check(projectDir, { strict: flags.strict });
|
|
15
|
+
if (checkCode !== 0) {
|
|
16
|
+
log.err('deploy 终止:check 未通过,请修复后重试。');
|
|
17
|
+
return checkCode;
|
|
18
|
+
}
|
|
19
|
+
if (delivery === 'local') {
|
|
20
|
+
log.ok('delivery=local:本地检查通过,未修改云端。');
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
if (delivery === 'preview') {
|
|
24
|
+
log.step('delivery=preview:执行 push dry-run …');
|
|
25
|
+
return sync(projectDir, 'push', positional, { ...flags, 'dry-run': true });
|
|
26
|
+
}
|
|
27
|
+
log.step('delivery=deploy:开始 push …');
|
|
28
|
+
return sync(projectDir, 'push', positional, flags);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = deploy;
|
package/src/commands/doctor.js
CHANGED
|
@@ -28,7 +28,7 @@ async function doctor(projectDir, flags = {}) {
|
|
|
28
28
|
log.dim('CLI 最新版查询失败(可能离线或 registry 不可达)');
|
|
29
29
|
} else if (cmpSemver(latest, current) > 0) {
|
|
30
30
|
log.warn(`CLI 有新版:${current} → ${latest}`);
|
|
31
|
-
log.dim('
|
|
31
|
+
log.dim(' 运行 `draftgo upgrade` 可显式升级。');
|
|
32
32
|
} else {
|
|
33
33
|
log.ok(`CLI 已是最新:${current}`);
|
|
34
34
|
}
|
package/src/commands/help.js
CHANGED
|
@@ -7,26 +7,31 @@ function help() {
|
|
|
7
7
|
const targets = all.map((i) => ` ${i.name.padEnd(12)} ${i.displayName}`).join('\n');
|
|
8
8
|
console.log(`draftgo v${getPackageVersion()} — DraftGo Next workbench CLI for AI coding agents
|
|
9
9
|
|
|
10
|
-
DraftGo Next frontend baseline: React + Vite
|
|
11
|
-
Database pages use
|
|
10
|
+
DraftGo Next frontend baseline: React + Vite.
|
|
11
|
+
Database pages use standard HTML + Tailwind CSS.
|
|
12
12
|
The CLI is the workbench layer for local runtime, resource sync, checks, and push/pull flows.
|
|
13
13
|
|
|
14
14
|
Usage:
|
|
15
15
|
draftgo init [<target>...] Install skill. No target = auto-detect.
|
|
16
16
|
Use "all" to install every target.
|
|
17
|
-
draftgo update [<target>...]
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
draftgo update [<target>...] Atomically update skill + entry files.
|
|
18
|
+
Reports newer CLI versions without
|
|
19
|
+
modifying the global installation.
|
|
20
20
|
draftgo uninstall <target|all> Remove entry files for target(s).
|
|
21
21
|
Use explicit "all" to remove every target.
|
|
22
22
|
--purge also removes .draftgo/ (runtime data).
|
|
23
23
|
draftgo status Show installed targets and skill version.
|
|
24
24
|
draftgo doctor Diagnose environment (python, targets,
|
|
25
25
|
CLI freshness).
|
|
26
|
+
draftgo upgrade Explicitly upgrade the global CLI, then
|
|
27
|
+
refresh installed skill files.
|
|
26
28
|
draftgo map Print a local DraftGo project resource map
|
|
27
29
|
for fast AI orientation.
|
|
28
30
|
draftgo check Check local resource closure: routes,
|
|
29
|
-
entry binding, files,
|
|
31
|
+
entry binding, files, mock/color risks.
|
|
32
|
+
draftgo verify-ui <url> Run a deterministic browser smoke check.
|
|
33
|
+
Uses one viewport and screenshots on failure.
|
|
34
|
+
draftgo api <keyword> Search the bundled OpenAPI specification.
|
|
30
35
|
draftgo dev Run this project's npm dev script.
|
|
31
36
|
draftgo build Run this project's npm build script.
|
|
32
37
|
draftgo new <type> <slug> Scaffold a new resource locally (no network).
|
|
@@ -34,12 +39,17 @@ Usage:
|
|
|
34
39
|
Types: page | nav | db_meta | script | doc
|
|
35
40
|
draftgo delete <type> <id> Delete resource from server + local index.
|
|
36
41
|
Types: pages | nav | db_meta | custom_scripts
|
|
37
|
-
| docs | doc_categories
|
|
42
|
+
| docs | doc_categories
|
|
38
43
|
Alias: del, rm. Flags: --yes / -y skip confirm.
|
|
39
44
|
draftgo pull [type] [id...] Pull DraftGo resources via the bundled
|
|
40
45
|
sync script. Defaults to --all.
|
|
41
46
|
draftgo push <type> [id...] Push DraftGo resources via the bundled
|
|
42
47
|
sync script.
|
|
48
|
+
draftgo deploy [type] [id...] Run check, then push explicitly.
|
|
49
|
+
--delivery local|preview|deploy
|
|
50
|
+
draftgo auto-push [type] [id...] Run check, then push only when
|
|
51
|
+
config.auto_push is true.
|
|
52
|
+
Supports --batch <type> <ids> ... too.
|
|
43
53
|
draftgo local up|down|logs|status
|
|
44
54
|
Manage .draftgo/docker/docker-compose.yaml
|
|
45
55
|
generated by draftgo local-dev.
|
|
@@ -73,9 +83,15 @@ Flags:
|
|
|
73
83
|
--token <sat> (connect) Provide the access token non-interactively.
|
|
74
84
|
--output <json> (map/check) Print machine-readable JSON.
|
|
75
85
|
--strict (check) Treat warnings as failures.
|
|
86
|
+
--mobile-check <mode> (verify-ui) auto | always | never. Default: auto.
|
|
87
|
+
--screenshot <mode> (verify-ui) on-failure | always | never.
|
|
88
|
+
--browser <name> (verify-ui) chromium | chrome | msedge.
|
|
89
|
+
--selector <css> (verify-ui) Require a key element to be visible.
|
|
90
|
+
--width/--height <px> (verify-ui) Override the default 390x844 viewport.
|
|
91
|
+
--delivery <mode> (deploy) local | preview | deploy.
|
|
76
92
|
|
|
77
93
|
Environment:
|
|
78
|
-
DRAFTGO_NO_UPDATE_CHECK=1 Disable the
|
|
94
|
+
DRAFTGO_NO_UPDATE_CHECK=1 Disable the cached CLI version check.
|
|
79
95
|
|
|
80
96
|
Targets:
|
|
81
97
|
${targets}
|
|
@@ -85,9 +101,11 @@ Examples:
|
|
|
85
101
|
draftgo init claudecode # install for Claude Code only
|
|
86
102
|
draftgo init claudecode kiro # install for both
|
|
87
103
|
draftgo init all # install for every supported target
|
|
88
|
-
draftgo update #
|
|
104
|
+
draftgo update # refresh skill and report newer CLI versions
|
|
105
|
+
draftgo upgrade # explicitly upgrade CLI and refresh skill
|
|
89
106
|
draftgo map # inspect pages/nav/db/scripts before development
|
|
90
107
|
draftgo check --strict # fail on closure warnings before push
|
|
108
|
+
draftgo verify-ui http://localhost:5173 --mobile-check auto
|
|
91
109
|
draftgo uninstall all --purge # full removal incl. runtime data
|
|
92
110
|
`);
|
|
93
111
|
}
|
package/src/commands/init.js
CHANGED
|
@@ -49,15 +49,30 @@ async function init(projectDir, positional, flags) {
|
|
|
49
49
|
// .draftgo/skill/ indirection anymore — each AI tool gets a real copy).
|
|
50
50
|
log.step('写入各 AI 工具 skill 目录(含 SKILL.md / 子技能 / rules / scripts)');
|
|
51
51
|
ensureRuntime(projectDir);
|
|
52
|
+
const failures = [];
|
|
53
|
+
let installedCount = 0;
|
|
54
|
+
let skippedCount = 0;
|
|
52
55
|
for (const t of resolved) {
|
|
53
56
|
try {
|
|
54
57
|
const r = t.install(projectDir, { force: !!flags.force });
|
|
55
|
-
|
|
58
|
+
if (r.skipped) {
|
|
59
|
+
skippedCount += 1;
|
|
60
|
+
log.warn(`${t.displayName.padEnd(16)} 已存在,未覆盖;使用 draftgo update 或 --force 更新。`);
|
|
61
|
+
} else {
|
|
62
|
+
installedCount += 1;
|
|
63
|
+
log.ok(`${t.displayName.padEnd(16)} → ${r.path}`);
|
|
64
|
+
}
|
|
56
65
|
} catch (e) {
|
|
57
66
|
log.err(`${t.displayName} 安装失败:${e.message}`);
|
|
67
|
+
failures.push(t.displayName);
|
|
58
68
|
}
|
|
59
69
|
}
|
|
60
|
-
|
|
70
|
+
if (failures.length) {
|
|
71
|
+
log.err(`安装未完成,失败目标:${failures.join(', ')}`);
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
if (installedCount > 0 && skippedCount === 0) writeInstalledVersion(projectDir);
|
|
75
|
+
if (skippedCount > 0) log.dim(' 存在未覆盖目标,未更新全局 skill 版本标记;运行 draftgo update 可统一刷新。');
|
|
61
76
|
log.dim(` CLI 版本:${getPackageVersion()}`);
|
|
62
77
|
|
|
63
78
|
// 3) Environment check (advisory).
|