dbx-plugin-skill 0.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/skill/SKILL.md ADDED
@@ -0,0 +1,268 @@
1
+ ---
2
+ name: dbx-plugin
3
+ description: DBX 插件开发全流程。Use when 创建、开发、调试、打包、签名、发布或上架 DBX 插件;处理 manifest.json、dbx-plugin.toml、.dbxp 包、贡献点(connection-provider / workbench / filesystem-provider / context-menu / result-view)、Host API(window.dbxPlugin 桥接)、Rust/Go Sidecar 协议、dbx-plugin CLI(create / dev / package / keygen)、dbx-store 候选 PR 与 catalog 校验时使用。
4
+ ---
5
+
6
+ # DBX 插件开发
7
+
8
+ 本 skill 覆盖 DBX 插件的**创建 → 开发 → 调试 → 打包 → 发布 → 官方商店上架**全链路。
9
+ 所有契约以 Manifest v1 + Host API 1.x + Sidecar Protocol v1 + `.dbxp` 包格式为准。
10
+
11
+ ## 0. 先建立正确的心智模型(读之前必看)
12
+
13
+ ### 0.1 四个契约各自管什么
14
+
15
+ | 契约 | 载体 | 作用 |
16
+ | --- | --- | --- |
17
+ | Manifest v1 | `manifest.json` | 插件身份、权限、入口、贡献点、国际化。运行时契约,**拒绝未声明字段** |
18
+ | 构建配置 | `dbx-plugin.toml` | 打包包含哪些目录、是否有原生后端、dev 构建命令。**不进入插件包** |
19
+ | Host API 1.x | `window.dbxPlugin` | 沙箱 UI 与 DBX 宿主通信 |
20
+ | Sidecar Protocol v1 | stdin/stdout JSON-RPC | 可选原生后端与 DBX 通信 |
21
+ | 包格式 | `.dbxp`(ZIP 容器) | DBX 实际安装的东西 |
22
+
23
+ SDK **不需要启动**:没有常驻 SDK Server。开发时只用三类工具——`dbx-plugin` CLI、Rust/Go SDK(仅原生后端链接用)、DBX 注入的 `window.dbxPlugin`。
24
+
25
+ ### 0.2 三个仓库的分工(最常见的错误来源)
26
+
27
+ | 你要改的东西 | 提交到哪里 |
28
+ | --- | --- |
29
+ | 你的插件前端、Rust/Go 后端、测试、发布脚本 | **你自己的插件源码仓库** |
30
+ | 新插件上架、版本更新、商店图标/介绍 | `t8y2/dbx-store`,目标分支 `main` |
31
+ | DBX Host、Manifest/Marketplace Schema、SDK、CLI、Packager、官方示例、插件开发文档 | `t8y2/dbx` |
32
+ | 某个第三方插件自身的 Bug | 该插件自己的源码仓库(**不要**提到 `dbx-store`) |
33
+ | 数据库厂商 JDBC Driver JAR | 不提交到任何 Git 仓库,用户本机导入 |
34
+
35
+ > 上架 PR 提到 `t8y2/dbx-store`,**不是** `t8y2/dbx`。普通插件源码也不要复制进 `t8y2/dbx`。
36
+
37
+ ### 0.3 包与签名模型
38
+
39
+ ```
40
+ 插件源码仓库 DBX Store(t8y2/dbx-store)
41
+ dbx-plugin package . 人工审核
42
+ │ │
43
+ ├─ dist/<id>-<ver>-<target>.dbxp │ 受保护 Workflow 用仓库 Ed25519 密钥签名
44
+ ├─ dist/<id>-<ver>-<target>.artifact.json│ │
45
+ └─ release-candidates.json ─────────────┘ ▼
46
+ (未签名候选) 最终签名 .dbxp + artifact metadata + signing receipt
47
+
48
+
49
+ catalog/index.json(DBX 客户端读取)
50
+ ```
51
+
52
+ - 开发者**永远不接触官方私钥**,也**不自行填写 `signingKeyId`**。
53
+ - 未签名包只能本地开发测试:插件中心 → 设置 → 第三方与开发者选项 → 允许安装未签名开发包。
54
+ - 签名保证「装到的字节 = 审核过的字节」,**不是** OS 沙箱,也不代表插件安全。
55
+
56
+ ---
57
+
58
+ ## 1. 我要做什么 → 读哪个 reference
59
+
60
+ | 任务 | 读 |
61
+ | --- | --- |
62
+ | 写/改 `manifest.json`、权限、入口、`localizations` | `references/manifest.md` |
63
+ | 加连接表单、工作台、文件系统、右键菜单、结果视图 | `references/contributions.md` |
64
+ | 写沙箱 UI、调 `window.dbxPlugin`、主题适配、CSP/网络 | `references/host-api.md` |
65
+ | 写 Rust/Go Sidecar、连接生命周期、二进制帧 | `references/sidecar-protocol.md` |
66
+ | 用 `dbx-plugin` 命令、装 CLI、模板选择 | `references/cli.md` |
67
+ | 起 dev host 调试、看日志、诊断接口 | `references/debugging.md` |
68
+ | 打包、`dbx-plugin.toml`、target、包体积限制 | `references/packaging.md` |
69
+ | 发布 Release、候选 PR、审核签名、上架/更新版本 | `references/publishing.md` |
70
+ | 报错信息 → 原因 → 修法 | `references/troubleshooting.md` |
71
+
72
+ ---
73
+
74
+ ## 2. 标准工作流
75
+
76
+ ### 步骤 1:装 CLI 并创建项目
77
+
78
+ ```bash
79
+ npm install --global @dbx-app/plugin-cli # 或 npx @dbx-app/plugin-cli
80
+ dbx-plugin --help # 验证安装与版本
81
+
82
+ dbx-plugin create my-plugin \
83
+ --template svelte \
84
+ --id com.example.my-plugin \
85
+ --name "My Plugin" \
86
+ --publisher example \
87
+ --description "A DBX plugin." \
88
+ --version 0.1.0 \
89
+ --yes
90
+ ```
91
+
92
+ 模板选择(不要为了「像完整插件」而强行加 Sidecar):
93
+
94
+ | 模板 | 组成 | 产物 | 适用 |
95
+ | --- | --- | --- | --- |
96
+ | `frontend` | 沙箱前端 | 一个 `universal` 包 | 纯 UI / 调 Host API |
97
+ | `svelte` | Svelte 5 + Vite 前端 | 一个 `universal` 包 | 自定义工作台 |
98
+ | `rust` | 前端 + Rust Sidecar | 每平台一个包 | 终端、SSH、复杂协议、高性能 |
99
+ | `go` | 前端 + Go Sidecar | 每平台一个包 | Go 生态、网络服务 |
100
+
101
+ ### 步骤 2:开发
102
+
103
+ - 前端入口由 `entrypoints.ui.entry` 指定,必须落在 `ui.root` 内(root 为 `ui` 时写 `ui/index.html`)。
104
+ - 所有 UI 必须构建为包内静态资源;**不要把 Vite dev server 或 CDN 地址写进发行包**。
105
+ - 需要原生能力(S3/SSH/系统凭据/长连接/高性能)才写 Sidecar。Sidecar 不是 OS 沙箱,以当前用户权限运行。
106
+
107
+ ### 步骤 3:本地调试
108
+
109
+ ```bash
110
+ dbx-plugin dev --path . --port 5190 # 不启动 DBX,浏览器开发宿主,需 Node.js 22+
111
+ curl -sS 'http://127.0.0.1:5190/api/diagnostics?after=0&limit=100&level=error' # 脚本/Agent 读脱敏日志
112
+ ```
113
+
114
+ 细节(自动重载、`DBX_UI_BUILD_SUCCESS` 约定、数据目录、能力边界)见 `references/debugging.md`。
115
+
116
+ ### 步骤 4:打包未签名候选
117
+
118
+ ```bash
119
+ dbx-plugin package .
120
+ # 前端:dist/<id>-<ver>-universal.dbxp + .artifact.json
121
+ # 原生:dist/<id>-<ver>-<os>-<arch>.dbxp + .artifact.json(必须在对应平台构建)
122
+ ```
123
+
124
+ 打包前先跑随附预检脚本(见 §5),它能提前发现 manifest/toml/include/资源不一致。
125
+
126
+ ### 步骤 5:发布 Release(在自己的插件仓库)
127
+
128
+ 生成的 `.github/workflows/plugin-release.yml` 会在发布 GitHub Release 时产出各平台候选包、`.artifact.json` 和合并的 `release-candidates.json`。**不要把 `.dbxp` 提交进 Git**。
129
+
130
+ ### 步骤 6:进入官方商店
131
+
132
+ - 已登记 `autoUpdate: true`:Store 的定时 Workflow 自动读取最新 Release 的 `release-candidates.json`,创建/更新 `candidates/<id>.json` 候选 PR(分支 `automation/plugin-release/<id>/<version>`)。作者不需要手工建 Issue/PR。
133
+ - 未登记:Fork `t8y2/dbx-store`,向 `main` 提**一个** PR,包含 `publishers/<publisher-id>.json`(仅首次)和 `candidates/<plugin-id>.json`。
134
+ - 之后由维护者审核 → 运行受保护签名 Workflow(PR 下评论 `/sign`)→ 回写 `plugins/<id>.json` + `catalog/index.json` → 合并。
135
+ - CI 在签名前**故意保持红色**(`open candidate(s) awaiting DBX Store signing`),这是设计如此。
136
+
137
+ 完整字段、`.dbx-store.json`、校验规则与常见坑见 `references/publishing.md`。
138
+
139
+ ### 步骤 7:发新版本
140
+
141
+ ```bash
142
+ # 1. 改代码,递增 manifest.json 的 version(不要复用旧版本号)
143
+ # 2. 打新 Tag、发新 Release(旧 Release 资产不可覆盖)
144
+ # 3. 等同步 Workflow 建候选 PR → 审核 → 签名 → 合并
145
+ ```
146
+
147
+ **已发布的字节不可覆盖**:任何字节变化都必须递增版本并重新审核。
148
+
149
+ ---
150
+
151
+ ## 3. 硬性约束(违反必然失败)
152
+
153
+ **Manifest**
154
+ - `manifest.json` 必须在包根目录;Manifest v1 **拒绝任何未声明字段**(顶层白名单只有 `$schema`、`manifest_version`、`id`、`name`、`icon`、`version`、`publisher`、`description`、`source`、`homepage`、`engines`、`permissions`、`entrypoints`、`contributions`、`localizations`)。
155
+ - `id` 只能小写字母/数字/`.`/`_`/`-`,首字符为字母或数字;发布后不可更改。`version` 必须是合法 SemVer。
156
+ - 包内路径相对包根,**不能**以 `/` 开头、不能含 `..`、反斜杠或重复斜杠。
157
+ - `entrypoints.ui.entry` 必须位于 `ui.root` 内。
158
+ - 已废弃字段会被 CLI 拒绝:`entrypoints.ui.kind`、`entrypoints.backend.binaries`、`entrypoints.backend.protocol`。
159
+
160
+ **权限**
161
+ - 只声明真正用到的权限,取最小集合:`host.workbench`、`host.events`、`host.filesystem`、`host.binary`、`host.network:https://host[:port]`(HTTPS、无路径/通配符/Token,最多 8 个)。
162
+ - `host.network` 只影响浏览器 CSP 的 `connect-src`,**不是** Sidecar 的网络防火墙,也仍受目标服务 CORS 约束。
163
+
164
+ **安全**
165
+ - 密码、Token、私钥**绝不**放进 `config`、Workbench context、事件或日志;需要持久化的敏感值用 `binding: "secret"`。
166
+ - `.dbx-dev/` 可能含明文凭据,必须加入 `.gitignore`,不得提交、不得打包(打包会直接报错)。
167
+ - 不要导入 DBX 的 Vue/Tauri 模块;不要假设页面能直接访问 Node.js、文件系统或网络。
168
+
169
+ **打包/发布**
170
+ - `.dbxp` 是安装包不是源码;不要把 `dist/` 当输入目录再次打包。
171
+ - 打包会拒绝:符号链接、越界路径、`..`、`.dbx-dev`、超限文件、不安全输出位置。
172
+ - 候选包**必须未签名**且 `.artifact.json` 里**不含 `signingKeyId`**;候选 URL 必须 HTTPS,且不能指向 `t8y2/dbx-store` 的 Release。
173
+ - 候选的 `id`/`version`/`publisher` 必须与包内 `manifest.json` 完全一致(签名时逐一比对)。
174
+ - `plugins/*.json` 和 `catalog/index.json` **永远不要手工编辑**(由签名 Workflow 生成)。
175
+
176
+ ---
177
+
178
+ ## 4. 命令速查
179
+
180
+ ```bash
181
+ # 安装
182
+ npm install --global @dbx-app/plugin-cli
183
+ npx @dbx-app/plugin-cli create my-plugin
184
+
185
+ # 创建(--template frontend|svelte|rust|go;--backend 为别名;--language rust|go 兼容别名)
186
+ dbx-plugin create my-plugin --template rust --sdk-root /path/to/dbx
187
+
188
+ # 调试(Node.js 22+)
189
+ dbx-plugin dev [--path DIR] [--port 5190] [--data-dir DIR]
190
+
191
+ # 打包(始终产出未签名候选)
192
+ dbx-plugin package . [--target universal] [--output-dir dist] [--artifact-url https://...]
193
+
194
+ # 仅私有/自定义仓库运营方需要
195
+ dbx-plugin keygen company.plugins.release # 生成 0600 权限的私钥 env 文件
196
+
197
+ # 其他
198
+ dbx-plugin version
199
+ NO_COLOR=1 dbx-plugin --help
200
+ ```
201
+
202
+ 相关环境变量:`DBX_PLUGIN_TARGET`(打包 target)、`DBX_PLUGIN_SDK_ROOT`(改用本地/自带 SDK 源码)、`DBX_PLUGIN_DEV_RUNTIME`、`DBX_PLUGIN_NODE`(dev 运行时)、`DBX_PLUGIN_CLI_BINARY`(npm launcher 覆盖二进制)、`NO_COLOR` / `CLICOLOR` / `CLICOLOR_FORCE`。
203
+
204
+ ---
205
+
206
+ ## 5. 随附脚本(零依赖,Node.js 18+)
207
+
208
+ 脚本位于本 skill 的 `scripts/` 目录(下文记为 `<skill-root>/scripts`)。
209
+
210
+ ```bash
211
+ # 1) 打包前预检:manifest / dbx-plugin.toml / include 覆盖 / 资源存在 / 前后端一致 / 权限语法
212
+ node <skill-root>/scripts/check-project.mjs [项目目录] [--json]
213
+
214
+ # 2) 解包检查 .dbxp:条目清单、manifest、checksums 校验、签名状态、bin 目标一致性
215
+ node <skill-root>/scripts/inspect-dbxp.mjs dist/my-plugin-0.1.0-universal.dbxp [--json] [--extract DIR]
216
+
217
+ # 3) 从 dist/*.artifact.json 生成 candidates/<id>.json 与 release-candidates.json
218
+ node <skill-root>/scripts/make-candidate.mjs [项目目录] [--release-notes "..."] [--out dist]
219
+ # 会自动校验每个 .artifact.json 的 sha256/size 与 .dbxp 实际字节一致
220
+
221
+ # 4) 读取 dev host 脱敏日志(轮询/api/diagnostics,自动沿用 nextAfter+instanceId)
222
+ node <skill-root>/scripts/dev-logs.mjs --port 5190 [--level error] [--follow] [--json]
223
+ ```
224
+
225
+ ---
226
+
227
+ ## 6. 排错入口
228
+
229
+ 先跑预检,再对症查表:
230
+
231
+ 1. `node <skill-root>/scripts/check-project.mjs` —— 覆盖绝大多数 manifest/toml/include 类错误。
232
+ 2. 打包/签名/上架报错 → `references/troubleshooting.md` 的错误信息对照表。
233
+ 3. dev host 起不来或 UI 不刷新 → `references/debugging.md` 的「能力边界」与「自动重载」两节。
234
+
235
+ 高频真相(避免误判):
236
+
237
+ - `Sidecar identity or protocol does not match manifest`:初始化响应里的 `plugin.id`/`version` 与 `manifest.json` 不一致,或协议版本不在双方支持范围内。
238
+ - 改完 UI 页面不刷新:编译型前端需要 `[dev].ui_watch`,且构建成功必须打印**独立一行** `DBX_UI_BUILD_SUCCESS`。
239
+ - `manifest.json contains unknown top-level field(s): ...`:写进了 Manifest v1 不接受的字段(常见于手写 `signingKeyId`、`verified`、自定义键)。
240
+ - `... is not covered by [package].include`:`icon` / `ui.entry` 所指文件不在 `[package].include` 声明的目录内。
241
+ - 原生插件 `target 'X' does not match build host 'Y'`:原生包必须在目标平台构建,用 CI 矩阵而不是本机交叉打包。
242
+ - 商店校验 `candidate URLs must not reference DBX Store releases`:候选只能指向你自己仓库的**未签名**包。
243
+
244
+ ---
245
+
246
+ ## 7. 事实来源
247
+
248
+ - 官方文档:<https://dbxio.com/cn/docs/plugin-development>
249
+ - 上游权威源码与 Schema(`t8y2/dbx`,`main` 分支):
250
+ - `plugins/manifest.schema.json`、`plugins/marketplace.schema.json`
251
+ - `plugins/README.md`(完整贡献点与协议)、`plugins/RELEASING.md`、`plugins/SIGNING.md`
252
+ - `plugins/sdk/cli`、`plugins/sdk/packager`、`plugins/sdk/dev-host`、`plugins/sdk/{rust,go}`
253
+ - 官方商店仓库:<https://github.com/t8y2/dbx-store>(`CONTRIBUTING.md`、`schemas/plugin-candidate.schema.json`、`scripts/validate.mjs`)
254
+
255
+ 注意:模板中 `manifest.json` 的 `$schema` 默认指向 `.../t8y2/dbx/plugin-sdk-v1/plugins/manifest.schema.json`,该 ref 目前**不存在(404)**。若你依赖编辑器校验,请改为 `main` 或具体版本 tag。以 CLI 与运行时校验为准,Schema 只是编辑期辅助,不是安全边界。
256
+
257
+ ---
258
+
259
+ ## 8. 分析/审查插件时的输出要求
260
+
261
+ 被要求 review 一个 DBX 插件或候选包时,按以下顺序给结论,并标注证据(文件:行 或命令输出):
262
+
263
+ 1. **身份一致性**:`id` / `version` / `publisher` 在 `manifest.json`、`.dbx-store.json`、`candidates/*.json`、`artifact.json` 中是否一致。
264
+ 2. **权限最小化**:声明的每个权限是否都有实际调用点;`host.network` origin 是否精确。
265
+ 3. **Secret 处理**:有无把凭据写入 `config`、context、事件或日志。
266
+ 4. **包内容**:`inspect-dbxp.mjs` 输出中是否有 `.dbx-dev`、多余文件、错误 target 的 `bin/`。
267
+ 5. **可复现性**:`sha256`/`size` 是否与实际字节一致;是否覆盖了已发布版本。
268
+ 6. **上架合规**:候选未签名、URL 为 HTTPS 且非 dbx-store Release、未手工改 `plugins/` 或 `catalog/`。
@@ -0,0 +1,225 @@
1
+ # `dbx-plugin` CLI 参考
2
+
3
+ CLI 有四个命令:`create`、`dev`、`package`、`keygen`。npm 包会把当前平台的**预编译二进制**、匹配版本的 Rust/Go SDK 源码和 dev host 运行时一起装好 —— **不需要 Rust,也不需要克隆 DBX 源码**。
4
+
5
+ ## 1. 安装
6
+
7
+ ```bash
8
+ # 全局安装(推荐)
9
+ npm install --global @dbx-app/plugin-cli
10
+ dbx-plugin --help
11
+
12
+ # 不安装,直接用
13
+ npx @dbx-app/plugin-cli create my-plugin
14
+
15
+ # 验证版本
16
+ dbx-plugin version
17
+ ```
18
+
19
+ - npm 包要求 **Node.js >= 18.18**;`dev` 子命令要求 **Node.js >= 22**。
20
+ - 平台二进制通过 `optionalDependencies` 分发(`darwin-arm64`、`darwin-x64`、`linux-arm64-gnu`、`linux-x64-gnu`、`win32-arm64`、`win32-x64`)。**不要用 `--no-optional` 安装**,否则 launcher 会报缺少平台包。
21
+ - launcher(`bin/dbx-plugin.js`)行为:
22
+ - 按 `process.platform` + `process.arch` 选择平台二进制;
23
+ - `DBX_PLUGIN_CLI_BINARY` 可覆盖二进制路径(用于本地源码构建的二进制);
24
+ - `dev` 子命令会设置 `DBX_PLUGIN_NODE` 与 `DBX_PLUGIN_DEV_RUNTIME`,并在 Node < 22 时直接报错;
25
+ - **总是**把 `DBX_PLUGIN_SDK_ROOT` 指向包内自带的 `sdk-root`(除非你自己已设置)—— 这就是「不用克隆 DBX 也能构建原生后端」的原因;
26
+ - `dbx-plugin --verify-platform` 只校验平台包存在,不执行命令。
27
+
28
+ **仅当开发 CLI 本身**时才从源码安装:
29
+
30
+ ```bash
31
+ cd /path/to/dbx
32
+ CARGO_TARGET_DIR=/tmp/dbx-plugin-cli-target cargo install --locked --path plugins/sdk/cli --force
33
+ ```
34
+
35
+ ## 2. `dbx-plugin create`
36
+
37
+ ```bash
38
+ dbx-plugin create [directory] [options]
39
+ ```
40
+
41
+ | 选项 | 说明 |
42
+ | --- | --- |
43
+ | `-t, --template TYPE` | `frontend`(默认)、`svelte`、`rust`、`go`;别名:`frontend-only`/`ui`/`none` → `frontend`,`golang` → `go` |
44
+ | `--backend TYPE` | `--template` 的别名,同样接受 `none`/`svelte`/`rust`/`go` |
45
+ | `-l, --language LANG` | 兼容别名,只接受 `rust` / `go` / `golang` |
46
+ | `--id ID` | 反域名插件 ID(如 `com.example.my-plugin`) |
47
+ | `--name NAME` | 显示名 |
48
+ | `--publisher NAME` | 发布者标识 |
49
+ | `--description TEXT` | 插件说明 |
50
+ | `--version VERSION` | 严格 SemVer,默认 `0.1.0` |
51
+ | `--sdk-root PATH` | 使用本地 DBX 工作区的 SDK 源码(**仅 Rust/Go 模板**) |
52
+ | `--force` | 覆盖已生成的文件 |
53
+ | `-y, --yes` | 跳过交互向导,使用默认值 |
54
+ | `-h, --help` | 帮助 |
55
+
56
+ - 交互模式条件:**未传 `--yes` 且 stdin/stdout 都是 TTY**。会彩色向导、逐项校验、显示汇总并在写文件前确认。
57
+ - 未 `--yes` 且非 TTY 时按非交互处理(缺值报错)。
58
+ - `--signing-key-id` 已移除:官方包由 DBX Store 审核后签名,CLI 会直接报错。
59
+
60
+ **完整参数示例(CI/脚本用)**:
61
+
62
+ ```bash
63
+ dbx-plugin create my-plugin \
64
+ --template svelte \
65
+ --id com.example.my-plugin \
66
+ --name "My Plugin" \
67
+ --publisher example \
68
+ --description "A DBX plugin." \
69
+ --version 0.1.0 \
70
+ --yes
71
+ ```
72
+
73
+ ### 目录名决定的东西
74
+
75
+ `directory` 的 basename 会被规范化为 slug(非字母数字 → `-`,折叠连续 `-`,转小写),然后:
76
+
77
+ - 原生后端二进制名 = `dbx-plugin-<slug>`;
78
+ - 生成的方法名前缀 = slug(`_` → `-`);
79
+ - `database_type` / `CONNECTION_TYPE` = slug;
80
+ - Go module = `github.com/<publisher>/<slug>`。
81
+
82
+ 所以目录名要有字母或数字,且建议只用小写字母、数字和 `-`。
83
+
84
+ ### 生成的文件
85
+
86
+ | 模板 | 文件 |
87
+ | --- | --- |
88
+ | 全部 | `.gitignore`、`assets/plugin.svg` |
89
+ | `frontend` | `dbx-plugin.toml`、`manifest.json`、`README.md`、`ui/index.html`、`.github/workflows/plugin-release.yml` |
90
+ | `svelte` | 上述 + `package.json`、`svelte.config.js`、`vite.config.js`、`index.html`、`src/main.js`、`src/App.svelte` |
91
+ | `rust` | `frontend` 的基础文件换成 `common/*`,另加 `backend/Cargo.toml`、`backend/src/main.rs` |
92
+ | `go` | 同上,另加 `backend/go.mod`、`backend/main.go` |
93
+
94
+ 生成的 `.gitignore` 已包含 `/dist/`、`/.dbx-dev/`、`.dbx-repository-signing-key.env`。
95
+
96
+ ### create 的校验规则
97
+
98
+ - 目标目录存在且非空 → 必须 `--force`,否则报 `... is not empty; use --force to overwrite generated files`。
99
+ - `--id` / `--publisher`:只允许小写字母、数字和 `.` `_` `-`,首字符不能是标点。
100
+ - `--version`:必须能被 semver 解析(`1.0.0`、`1.0.0-beta.1`)。
101
+ - `--name` / `--description`:非空且不能含控制字符。
102
+ - `--sdk-root` 用在 `frontend` / `svelte` 模板会报 `SDK root is only supported by Rust or Go plugin templates`。
103
+ - 模板渲染后若有未替换的 `{{MARKER}}` 会报错(模板 bug 防护)。
104
+
105
+ ## 3. `dbx-plugin dev`
106
+
107
+ ```bash
108
+ dbx-plugin dev [--path DIR] [--port PORT] [--data-dir DIR]
109
+ ```
110
+
111
+ | 选项 | 默认 | 说明 |
112
+ | --- | --- | --- |
113
+ | `--path DIR` | `.` | 插件项目目录 |
114
+ | `--port PORT` | `5190` | 回环端口;`0` 或被占用时自动选空闲端口 |
115
+ | `--data-dir DIR` | `<项目>/.dbx-dev` | 开发数据(**含明文凭据**) |
116
+
117
+ - **要求 Node.js 22+**;只监听 `127.0.0.1`。
118
+ - 不会启动 DBX 桌面端,也**不会自动安装插件依赖**。
119
+ - 前端构建由 `dbx-plugin.toml` 的 `[dev]` 决定(见 `debugging.md`)。
120
+ - 详细能力边界、诊断接口见 `debugging.md`。
121
+
122
+ ## 4. `dbx-plugin package`
123
+
124
+ ```bash
125
+ dbx-plugin package [project] [--target TARGET] [--output-dir DIR] [--artifact-url URL]
126
+ ```
127
+
128
+ | 选项 | 默认 | 说明 |
129
+ | --- | --- | --- |
130
+ | `project`(位置参数) | `.` | 项目目录 |
131
+ | `--target TARGET` | 见下 | artifact target,也读环境变量 `DBX_PLUGIN_TARGET` |
132
+ | `--output-dir DIR` | `dist` | 相对路径按项目目录解析;绝对路径原样使用 |
133
+ | `--artifact-url URL` | 包文件名 | 写进 artifact metadata 的 URL |
134
+
135
+ - `--key-id` 已移除:`package` **始终产出未签名候选包**;签名是仓库运营方在审核后做的独立步骤。
136
+
137
+ **target 规则**:
138
+
139
+ - 纯前端项目默认 `universal`。
140
+ - 原生项目默认当前主机 target(`darwin-arm64`、`darwin-x64`、`linux-x64`、`linux-arm64`、`windows-x64`、`windows-arm64` 形态)。
141
+ - 原生项目**显式指定与构建主机不同的 target 会报错**:
142
+ `Native plugin target 'X' does not match build host 'Y'; run this package command on the target platform`。
143
+ - target 只允许 `[a-z0-9-]`,长度 ≤64。
144
+
145
+ **产物**:
146
+
147
+ ```
148
+ dist/<plugin-id>-<version>-<target>.dbxp
149
+ dist/<plugin-id>-<version>-<target>.artifact.json
150
+ ```
151
+
152
+ `artifact.json` 内容(未签名时**不含** `signingKeyId`):
153
+
154
+ ```json
155
+ {
156
+ "target": "universal",
157
+ "url": "com.example.my-plugin-0.1.0-universal.dbxp",
158
+ "sha256": "<64 位十六进制>",
159
+ "size": 123456
160
+ }
161
+ ```
162
+
163
+ **打包行为要点**(详见 `packaging.md`):只打包 `[package].include` 声明的目录;重写包内 `manifest.json` 的 backend executable;拒绝符号链接、`.dbx-dev`、越界路径、过大文件与不安全输出位置。
164
+
165
+ ## 5. `dbx-plugin keygen`(仅私有/自定义仓库运营方)
166
+
167
+ ```bash
168
+ dbx-plugin keygen [KEY_ID] [--output FILE] [--force]
169
+ ```
170
+
171
+ | 选项 | 默认 | 说明 |
172
+ | --- | --- | --- |
173
+ | `KEY_ID`(位置参数或 `--key-id`) | 交互输入 | 公钥稳定标识,如 `company.plugins.release` |
174
+ | `-o, --output FILE` | `.dbx-repository-signing-key.env` | 私钥输出文件 |
175
+ | `--force` | 关 | 覆盖已存在文件 |
176
+
177
+ - 生成 **32 字节 Ed25519 seed** 的 env 文件,Unix 权限 `0600`,已存在则拒绝覆盖(除非 `--force`)。
178
+ - 文件内容形如:
179
+
180
+ ```bash
181
+ # Keep this file secret. Do not commit it.
182
+ export DBX_PLUGIN_SIGNING_KEY=<base64 私钥>
183
+ export DBX_PLUGIN_SIGNING_KEY_ID=<key id>
184
+ export DBX_PLUGIN_SIGNING_PUBLIC_KEY=<base64 公钥>
185
+ ```
186
+
187
+ - 终端只打印 Key ID 与公钥,**不打印私钥**。
188
+ - **官方商店插件作者不要运行 `keygen`,也不要填写 `signingKeyId`。**
189
+ - Key ID 命名建议「仓库 + 用途 + 轮换版本」,最长 128 字符,可用字母数字 `.` `-` `_` `:`。**同一 Key ID 必须永远对应同一把公钥**;轮换要换新 ID。
190
+
191
+ ## 6. 终端颜色
192
+
193
+ 颜色在交互终端自动启用。关闭与强制:
194
+
195
+ ```bash
196
+ NO_COLOR=1 dbx-plugin --help # 纯文本(优先级最高)
197
+ CLICOLOR=0 dbx-plugin --help # 同上
198
+ CLICOLOR_FORCE=1 dbx-plugin --help # 管道输出时也保留颜色
199
+ ```
200
+
201
+ ## 7. 环境变量汇总
202
+
203
+ | 变量 | 作用 |
204
+ | --- | --- |
205
+ | `DBX_PLUGIN_TARGET` | `package` 的默认 target |
206
+ | `DBX_PLUGIN_SDK_ROOT` | 用本地/自带的 Rust+Go SDK 源码构建后端(npm launcher 默认指向包内 `sdk-root`) |
207
+ | `DBX_PLUGIN_DEV_RUNTIME` | `dev` 运行时入口(覆盖默认 `dist/runtime.mjs`) |
208
+ | `DBX_PLUGIN_NODE` | `dev` 使用的 node 可执行文件 |
209
+ | `DBX_PLUGIN_CLI_BINARY` | launcher 使用的 CLI 二进制路径 |
210
+ | `NO_COLOR` / `CLICOLOR` / `CLICOLOR_FORCE` | 颜色控制 |
211
+
212
+ ## 8. 常见错误
213
+
214
+ | 报错 | 原因与修法 |
215
+ | --- | --- |
216
+ | `dbx-plugin: command not found` | npm 全局 bin 不在 `PATH`;或直接用 `npx @dbx-app/plugin-cli` |
217
+ | `The optional package @dbx-app/plugin-cli-<platform> was not installed` | 用了 `--no-optional` 安装,重新安装 |
218
+ | `DBX Plugin CLI does not provide a binary for <platform>` | 不支持的平台/架构(如 32 位或 musl) |
219
+ | `dev requires Node.js 22+` | 升级 Node,或设置 `DBX_PLUGIN_NODE` 指向 22+ |
220
+ | `... is not empty; use --force to overwrite generated files` | 目标目录非空,加 `--force` 或换目录 |
221
+ | `--signing-key-id is no longer used when creating plugins` | 删掉该参数,官方包由 DBX Store 签名 |
222
+ | `--key-id is no longer supported by dbx-plugin package` | 删掉该参数,`package` 只产出未签名候选 |
223
+ | `Native plugin target 'X' does not match build host 'Y'` | 在目标平台构建,或用 CI 矩阵 |
224
+ | `Failed to start Rust backend build: No such file or directory` | 未安装 `cargo`(Rust 模板才会用到) |
225
+ | `Go backend is missing <dir>/go.mod` | 目录结构与 `[backend].directory` 不一致 |