@nocobase/cli 2.1.0-beta.2 → 2.1.0-beta.21
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/LICENSE.txt +107 -0
- package/README.md +367 -19
- package/README.zh-CN.md +336 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +131 -0
- package/dist/commands/api/resource/create.js +15 -0
- package/dist/commands/api/resource/destroy.js +15 -0
- package/dist/commands/api/resource/get.js +15 -0
- package/dist/commands/api/resource/index.js +20 -0
- package/dist/commands/api/resource/list.js +16 -0
- package/dist/commands/api/resource/query.js +15 -0
- package/dist/commands/api/resource/update.js +15 -0
- package/dist/commands/build.js +57 -0
- package/dist/commands/db/logs.js +85 -0
- package/dist/commands/db/ps.js +60 -0
- package/dist/commands/db/shared.js +95 -0
- package/dist/commands/db/start.js +70 -0
- package/dist/commands/db/stop.js +70 -0
- package/dist/commands/dev.js +156 -0
- package/dist/commands/down.js +197 -0
- package/dist/commands/download.js +865 -0
- package/dist/commands/env/add.js +307 -0
- package/dist/commands/env/auth.js +55 -0
- package/dist/commands/env/list.js +36 -0
- package/dist/commands/env/remove.js +59 -0
- package/dist/commands/env/update.js +67 -0
- package/dist/commands/env/use.js +28 -0
- package/dist/commands/init.js +950 -0
- package/dist/commands/install.js +1927 -0
- package/dist/commands/logs.js +97 -0
- package/dist/commands/pm/disable.js +63 -0
- package/dist/commands/pm/enable.js +63 -0
- package/dist/commands/pm/list.js +61 -0
- package/dist/commands/prompts-stages.js +150 -0
- package/dist/commands/prompts-test.js +181 -0
- package/dist/commands/ps.js +119 -0
- package/dist/commands/restart.js +74 -0
- package/dist/commands/scaffold/migration.js +38 -0
- package/dist/commands/scaffold/plugin.js +37 -0
- package/dist/commands/self/check.js +71 -0
- package/dist/commands/self/index.js +20 -0
- package/dist/commands/self/update.js +86 -0
- package/dist/commands/skills/check.js +69 -0
- package/dist/commands/skills/index.js +20 -0
- package/dist/commands/skills/install.js +71 -0
- package/dist/commands/skills/update.js +71 -0
- package/dist/commands/start.js +218 -0
- package/dist/commands/stop.js +97 -0
- package/dist/commands/test.js +466 -0
- package/dist/commands/upgrade.js +594 -0
- package/dist/generated/command-registry.js +133 -0
- package/dist/help/runtime-help.js +20 -0
- package/dist/lib/api-client.js +244 -0
- package/dist/lib/app-runtime.js +153 -0
- package/dist/lib/auth-store.js +357 -0
- package/dist/lib/bootstrap.js +388 -0
- package/dist/lib/build-config.js +10 -0
- package/dist/lib/cli-home.js +61 -0
- package/dist/lib/cli-locale.js +115 -0
- package/dist/lib/command-discovery.js +39 -0
- package/dist/lib/env-auth.js +872 -0
- package/dist/lib/generated-command.js +150 -0
- package/dist/lib/http-request.js +49 -0
- package/dist/lib/naming.js +70 -0
- package/dist/lib/openapi.js +62 -0
- package/dist/lib/post-processors.js +23 -0
- package/dist/lib/prompt-catalog.js +581 -0
- package/dist/lib/prompt-validators.js +185 -0
- package/dist/lib/prompt-web-ui.js +2096 -0
- package/dist/lib/resource-command.js +343 -0
- package/dist/lib/resource-request.js +104 -0
- package/dist/lib/run-npm.js +197 -0
- package/dist/lib/runtime-generator.js +419 -0
- package/dist/lib/runtime-store.js +56 -0
- package/dist/lib/self-manager.js +246 -0
- package/dist/lib/skills-manager.js +269 -0
- package/dist/lib/startup-update.js +203 -0
- package/dist/lib/ui.js +175 -0
- package/dist/locale/en-US.json +336 -0
- package/dist/locale/zh-CN.json +336 -0
- package/dist/post-processors/data-modeling.js +66 -0
- package/dist/post-processors/data-source-manager.js +114 -0
- package/dist/post-processors/index.js +19 -0
- package/nocobase-ctl.config.json +287 -0
- package/package.json +60 -26
- package/LICENSE +0 -661
- package/bin/index.js +0 -39
- package/nocobase.conf.tpl +0 -95
- package/src/cli.js +0 -19
- package/src/commands/benchmark.js +0 -73
- package/src/commands/build.js +0 -49
- package/src/commands/clean.js +0 -30
- package/src/commands/client.js +0 -166
- package/src/commands/create-nginx-conf.js +0 -37
- package/src/commands/create-plugin.js +0 -33
- package/src/commands/dev.js +0 -200
- package/src/commands/doc.js +0 -76
- package/src/commands/e2e.js +0 -265
- package/src/commands/global.js +0 -43
- package/src/commands/index.js +0 -45
- package/src/commands/instance-id.js +0 -47
- package/src/commands/locale/cronstrue.js +0 -122
- package/src/commands/locale/react-js-cron/en-US.json +0 -75
- package/src/commands/locale/react-js-cron/index.js +0 -17
- package/src/commands/locale/react-js-cron/zh-CN.json +0 -33
- package/src/commands/locale/react-js-cron/zh-TW.json +0 -33
- package/src/commands/locale.js +0 -81
- package/src/commands/p-test.js +0 -88
- package/src/commands/perf.js +0 -63
- package/src/commands/pkg.js +0 -321
- package/src/commands/pm2.js +0 -37
- package/src/commands/postinstall.js +0 -88
- package/src/commands/start.js +0 -148
- package/src/commands/tar.js +0 -36
- package/src/commands/test-coverage.js +0 -55
- package/src/commands/test.js +0 -107
- package/src/commands/umi.js +0 -33
- package/src/commands/update-deps.js +0 -72
- package/src/commands/upgrade.js +0 -47
- package/src/commands/view-license-key.js +0 -44
- package/src/index.js +0 -14
- package/src/license.js +0 -76
- package/src/logger.js +0 -75
- package/src/plugin-generator.js +0 -80
- package/src/util.js +0 -517
- package/templates/bundle-status.html +0 -338
- package/templates/create-app-package.json +0 -39
- package/templates/plugin/.npmignore.tpl +0 -2
- package/templates/plugin/README.md.tpl +0 -1
- package/templates/plugin/client.d.ts +0 -2
- package/templates/plugin/client.js +0 -1
- package/templates/plugin/package.json.tpl +0 -11
- package/templates/plugin/server.d.ts +0 -2
- package/templates/plugin/server.js +0 -1
- package/templates/plugin/src/client/client.d.ts +0 -249
- package/templates/plugin/src/client/index.tsx.tpl +0 -1
- package/templates/plugin/src/client/locale.ts +0 -21
- package/templates/plugin/src/client/models/index.ts +0 -12
- package/templates/plugin/src/client/plugin.tsx.tpl +0 -10
- package/templates/plugin/src/index.ts +0 -2
- package/templates/plugin/src/locale/en-US.json +0 -1
- package/templates/plugin/src/locale/zh-CN.json +0 -1
- package/templates/plugin/src/server/collections/.gitkeep +0 -0
- package/templates/plugin/src/server/index.ts.tpl +0 -1
- package/templates/plugin/src/server/plugin.ts.tpl +0 -19
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# NocoBase CLI
|
|
2
|
+
|
|
3
|
+
NocoBase CLI (`nb`) 是用于在本地工作区初始化、连接和管理 NocoBase 应用的命令行工具。它可以帮助你准备 NocoBase 应用、保存 CLI env 配置,并提供启动、停止、查看日志、升级和清理等日常管理命令,让 coding agent 可以连接并使用 NocoBase。
|
|
4
|
+
|
|
5
|
+
CLI 支持两种常见的初始化方式:
|
|
6
|
+
|
|
7
|
+
- 连接已有的 NocoBase 应用,让 coding agent 直接使用。
|
|
8
|
+
- 通过 Docker、npm 或 Git 安装一个新的 NocoBase 应用,并保存为 CLI env。
|
|
9
|
+
|
|
10
|
+
## 前提条件
|
|
11
|
+
|
|
12
|
+
- Node.js v20+
|
|
13
|
+
- Yarn 1.x
|
|
14
|
+
- Git:选择 Git 源码安装时需要
|
|
15
|
+
- Docker:使用 Docker 方式安装,或使用内置数据库时需要
|
|
16
|
+
|
|
17
|
+
## 安装
|
|
18
|
+
|
|
19
|
+
全局安装 CLI:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g @nocobase/cli@alpha
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
查看可用命令:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
nb --help
|
|
29
|
+
nb init --help
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 核心概念
|
|
33
|
+
|
|
34
|
+
- **Workspace**:当前项目目录,CLI 会在这里保存 `.nocobase` 配置。
|
|
35
|
+
- **Env**:CLI 保存的一个 NocoBase 连接配置。在 `nb init` 中,app name 也就是 env name。
|
|
36
|
+
- **Source**:本地应用的来源,支持 `docker`、`npm` 和 `git`。
|
|
37
|
+
- **Remote env**:只保存已有 NocoBase 应用 API 连接的 env。
|
|
38
|
+
- **Runtime resources**:由 CLI 管理的本地运行资源,包括应用进程、Docker 应用容器、内置数据库容器、源码目录和存储目录。
|
|
39
|
+
|
|
40
|
+
## 快速开始
|
|
41
|
+
|
|
42
|
+
### 交互式初始化
|
|
43
|
+
|
|
44
|
+
在终端中启动引导式初始化:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
nb init
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
使用浏览器表单完成初始化:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
nb init --ui
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`nb init` 可以连接已有的 NocoBase 应用,也可以安装一个新的 NocoBase 应用。创建新应用时,还可以全局安装 NocoBase AI coding skills (`nocobase/skills`)。
|
|
57
|
+
|
|
58
|
+
### 非交互式初始化
|
|
59
|
+
|
|
60
|
+
跳过交互提示时,必须提供 app/env name:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
nb init --env app1 --yes
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
使用 Docker 安装:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
nb init --env app1 --yes --source docker --version alpha
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
使用 npm 安装:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
nb init --env app1 --yes --source npm --version alpha --app-port 13080
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
使用 Git 源码安装:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
nb init --env app1 --yes --source git --version alpha
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
对于 Git 源码安装,`--version alpha` 实际会解析为 `develop` 分支。
|
|
85
|
+
|
|
86
|
+
使用 Git 分支安装:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
nb init --env app1 --yes --source git --version fix/cli-v2
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`--version` 是三种 source 共用的版本参数:
|
|
93
|
+
|
|
94
|
+
- npm:包版本号
|
|
95
|
+
- Docker:镜像 tag
|
|
96
|
+
- Git:git ref,例如 branch 或 tag
|
|
97
|
+
|
|
98
|
+
默认情况下,新建本地应用会使用以下目录:
|
|
99
|
+
|
|
100
|
+
- 源码目录:`./<envName>/source/`
|
|
101
|
+
- 存储目录:`./<envName>/storage/`
|
|
102
|
+
|
|
103
|
+
### 恢复中断的初始化
|
|
104
|
+
|
|
105
|
+
如果 `nb init` 在 env 配置已经保存之后中断了,可以继续上一次初始化流程:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
nb init --env app1 --resume
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
对应的底层高级命令是:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
nb install --env app1 --resume
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`--resume` 会复用工作区里已保存的 env config,包括应用、source、数据库和 env 连接相关配置。在交互模式下,只会继续补齐缺失的初始化参数。
|
|
118
|
+
|
|
119
|
+
在非交互模式下,需要重新传这些只用于初始化、不会保存到 env config 的参数:
|
|
120
|
+
|
|
121
|
+
- `--lang`
|
|
122
|
+
- `--root-username`
|
|
123
|
+
- `--root-email`
|
|
124
|
+
- `--root-password`
|
|
125
|
+
- `--root-nickname`
|
|
126
|
+
|
|
127
|
+
## 常用命令
|
|
128
|
+
|
|
129
|
+
| 命令 | 说明 |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| `nb init` | 初始化 NocoBase,并连接为 coding agent 可使用的 CLI env。 |
|
|
132
|
+
| `nb install` | `nb init` 内部会使用的高级命令,用于安装本地 NocoBase 应用并保存 env 配置。通常建议直接使用 `nb init`。 |
|
|
133
|
+
| `nb download` | `nb init` 或 `nb upgrade` 会使用的高级命令,用于从 Docker、npm 或 Git 获取 NocoBase。通常很少直接使用。 |
|
|
134
|
+
| `nb start` | 启动选中的本地应用或 Docker 容器。 |
|
|
135
|
+
| `nb stop` | 停止选中的本地应用或 Docker 容器。 |
|
|
136
|
+
| `nb restart` | 先停止,再启动选中的本地应用或 Docker 容器。 |
|
|
137
|
+
| `nb dev` | 为 npm/Git 源码 env 启动开发模式。 |
|
|
138
|
+
| `nb logs` | 查看 npm/Git 或 Docker env 的应用日志。 |
|
|
139
|
+
| `nb ps` | 查看已配置 env 的运行状态。 |
|
|
140
|
+
| `nb db` | 查看或管理本地 env 的内置数据库运行状态。 |
|
|
141
|
+
| `nb upgrade` | 更新源码/镜像并重启选中的应用。 |
|
|
142
|
+
| `nb down` | 停止并移除某个 env 的本地运行容器。 |
|
|
143
|
+
| `nb env` | 管理已保存的 CLI env 连接。 |
|
|
144
|
+
| `nb api` | 通过 CLI 调用 NocoBase API 资源。 |
|
|
145
|
+
| `nb pm` | 管理选中 NocoBase env 的插件。 |
|
|
146
|
+
|
|
147
|
+
推荐在应用和运行时相关命令里显式使用 `--env`;`-e` 是它的简写:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
nb start --env app1
|
|
151
|
+
nb restart --env app1
|
|
152
|
+
nb logs --env app1
|
|
153
|
+
nb ps --env app1
|
|
154
|
+
nb db ps --env app1
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
等价的简写示例:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
nb start -e app1
|
|
161
|
+
nb restart -e app1
|
|
162
|
+
nb logs -e app1
|
|
163
|
+
nb upgrade -e app1
|
|
164
|
+
nb db start -e app1
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## 运行方式
|
|
168
|
+
|
|
169
|
+
### Docker
|
|
170
|
+
|
|
171
|
+
Docker env 会通过已保存的 Docker 容器和镜像进行管理:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
nb init --env app1 --yes --source docker --version alpha
|
|
175
|
+
nb start --env app1
|
|
176
|
+
nb restart --env app1
|
|
177
|
+
nb logs --env app1
|
|
178
|
+
nb stop --env app1
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Docker 下载支持指定平台:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
nb download --source docker --version alpha --docker-platform auto
|
|
185
|
+
nb download --source docker --version alpha --docker-platform linux/amd64
|
|
186
|
+
nb download --source docker --version alpha --docker-platform linux/arm64
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### npm 和 Git
|
|
190
|
+
|
|
191
|
+
npm 和 Git env 会使用本地源码目录,并支持开发模式:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
nb init --env app1 --yes --source git --version alpha
|
|
195
|
+
nb dev --env app1
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`nb dev` 只支持 npm/Git 源码 env。Docker env 可以通过 `nb logs` 查看日志,remote env 只支持 API 和 env 相关操作。
|
|
199
|
+
|
|
200
|
+
### 已有 NocoBase 应用
|
|
201
|
+
|
|
202
|
+
如果要连接已有应用,可以运行 `nb init` 并选择已有应用流程,也可以直接添加 env:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
nb env add app1 --api-base-url http://localhost:13000/api
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
`nb env add` 会在需要时自动进入认证流程。
|
|
209
|
+
|
|
210
|
+
## 升级
|
|
211
|
+
|
|
212
|
+
升级会更新已保存的源码或镜像,然后重启应用:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
nb upgrade --env app1
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
如果只想使用当前已保存的本地源码或 Docker 镜像重启应用,可以使用 `--skip-code-update` 或 `-s`:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
nb upgrade --env app1 -s
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## 数据库命令
|
|
225
|
+
|
|
226
|
+
可以使用 `nb db` 查看或管理本地 env 的内置数据库运行状态:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
nb db ps
|
|
230
|
+
nb db ps --env app1
|
|
231
|
+
nb db start --env app1
|
|
232
|
+
nb db stop --env app1
|
|
233
|
+
nb db logs --env app1
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
说明:
|
|
237
|
+
|
|
238
|
+
- `nb db start` 和 `nb db stop` 只适用于启用了内置数据库的 env。
|
|
239
|
+
- `nb db logs` 只适用于启用了内置数据库的 env。
|
|
240
|
+
- 对于没有 CLI 托管数据库容器的 env,`nb db ps` 也会显示 `external` 或 `remote` 状态。
|
|
241
|
+
|
|
242
|
+
## 清理
|
|
243
|
+
|
|
244
|
+
关闭并清理某个本地 env:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
nb down --env app1
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
默认情况下,`nb down` 会停止应用,并在存在时移除应用容器和数据库容器。它不会删除用户数据、源码文件和 CLI env 配置。
|
|
251
|
+
|
|
252
|
+
如需执行破坏性清理,需要显式指定参数:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
nb down --env app1 --remove-data
|
|
256
|
+
nb down --env app1 --remove-source
|
|
257
|
+
nb down --env app1 --remove-env
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
- `--remove-data`:删除 storage 和托管数据库数据。除非使用 `--yes`,否则需要二次确认。
|
|
261
|
+
- `--remove-source`:删除 npm/Git 源码目录。
|
|
262
|
+
- `--remove-env`:删除已保存的 CLI env 配置。
|
|
263
|
+
|
|
264
|
+
## Env 管理
|
|
265
|
+
|
|
266
|
+
查看当前 env:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
nb env
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
查看已配置的 env:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
nb env list
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
切换当前 env:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
nb env use app1
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
当凭证需要刷新时,重新认证某个 env:
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
nb env auth app1
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
从选中的应用更新运行时命令元数据:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
nb env update app1
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## API 命令
|
|
297
|
+
|
|
298
|
+
CLI 可以通过已配置的 env 调用 NocoBase 资源 API:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
nb api resource list --resource users -e app1
|
|
302
|
+
nb api resource get --resource users --filter-by-tk 1 -e app1
|
|
303
|
+
nb api resource create --resource users --values '{"nickname":"Ada"}' -e app1
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
如果需要输出原始 JSON,可以使用 `-j, --json-output`:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
nb api resource list --resource users -e app1 -j
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
可用的 API 命令分类:
|
|
313
|
+
|
|
314
|
+
| 命令 | 说明 |
|
|
315
|
+
| --- | --- |
|
|
316
|
+
| `nb api acl` | 基于角色、资源和操作管理访问控制。 |
|
|
317
|
+
| `nb api api-keys` | 管理用于 HTTP API 访问的 API keys。 |
|
|
318
|
+
| `nb api app` | 管理应用相关资源。 |
|
|
319
|
+
| `nb api authenticators` | 管理用户认证,包括密码认证、短信认证、SSO 协议和可扩展认证方式。 |
|
|
320
|
+
| `nb api data-modeling` | 管理数据源、数据表和数据库建模资源。 |
|
|
321
|
+
| `nb api file-manager` | 管理文件存储服务、文件集合和附件字段。 |
|
|
322
|
+
| `nb api flow-surfaces` | 组合和更新页面、标签页、区块、字段和操作等界面结构。 |
|
|
323
|
+
| `nb api pm` | 通过 API 命令管理插件。 |
|
|
324
|
+
| `nb api resource` | 操作通用集合资源。 |
|
|
325
|
+
| `nb api system-settings` | 调整系统标题、Logo、语言和其他全局设置。 |
|
|
326
|
+
| `nb api theme-editor` | 自定义 UI 颜色和尺寸,保存并切换主题。 |
|
|
327
|
+
| `nb api workflow` | 管理用于业务自动化的工作流资源。 |
|
|
328
|
+
|
|
329
|
+
## 本地数据
|
|
330
|
+
|
|
331
|
+
CLI 会在工作区的 `.nocobase` 中保存配置:
|
|
332
|
+
|
|
333
|
+
- `config.json`:env 定义、当前 env 和工作区级配置。
|
|
334
|
+
- `versions/<version>/commands.json`:从目标应用生成并缓存的运行时命令。
|
|
335
|
+
|
|
336
|
+
源码文件、storage 文件、Docker 容器和数据库数据等运行时数据,会根据 env 的 source 和安装选项分别管理。
|
package/bin/run.cmd
ADDED
package/bin/run.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
8
|
+
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const requireFromCli = createRequire(import.meta.url);
|
|
11
|
+
const root = path.resolve(__dirname, '..');
|
|
12
|
+
const realRoot = fs.realpathSync(root);
|
|
13
|
+
const isSourcePackage = realRoot.split(path.sep).join('/').endsWith('/packages/core/cli');
|
|
14
|
+
let isDev = isSourcePackage;
|
|
15
|
+
if (process.env.NB_CLI_USE_DIST === '1') {
|
|
16
|
+
isDev = false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* In the monorepo, plain `node` cannot load `.ts`. Re-exec once with `--import <tsx>`
|
|
21
|
+
* (same effect as a dedicated dev entry with `#!/usr/bin/env -S node --import tsx`).
|
|
22
|
+
*
|
|
23
|
+
* Use the tsx package resolved from this CLI install (not CWD), so `nb` works when
|
|
24
|
+
* invoked from a project directory that does not depend on `tsx`.
|
|
25
|
+
*/
|
|
26
|
+
function reexecWithTsx() {
|
|
27
|
+
let tsxEntry;
|
|
28
|
+
try {
|
|
29
|
+
tsxEntry = requireFromCli.resolve('tsx');
|
|
30
|
+
} catch {
|
|
31
|
+
console.error(
|
|
32
|
+
[
|
|
33
|
+
'Cannot load dev dependency `tsx` for the NocoBase CLI.',
|
|
34
|
+
'Install monorepo dependencies (e.g. `yarn install` at the repo root),',
|
|
35
|
+
'or set NB_CLI_USE_DIST=1 to run the compiled CLI without TypeScript sources.',
|
|
36
|
+
].join(' '),
|
|
37
|
+
);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const reexecArgs = ['--import', pathToFileURL(tsxEntry).href];
|
|
42
|
+
const supportedFlags = Array.from(process.allowedNodeEnvironmentFlags);
|
|
43
|
+
if (supportedFlags.some((flag) => flag === '--disable-warning' || flag.startsWith('--disable-warning='))) {
|
|
44
|
+
reexecArgs.push('--disable-warning=ExperimentalWarning');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const result = spawnSync(process.execPath, [...reexecArgs, ...process.argv.slice(1)], {
|
|
48
|
+
stdio: 'inherit',
|
|
49
|
+
env: {
|
|
50
|
+
...process.env,
|
|
51
|
+
_NOCO_CLI_TSX_CHILD: '1',
|
|
52
|
+
NODE_ENV: 'development',
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (isDev && !process.env._NOCO_CLI_TSX_CHILD) {
|
|
59
|
+
reexecWithTsx();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const bootstrapPath = isDev ? path.join(root, 'src/lib/bootstrap.ts') : path.join(root, 'dist/lib/bootstrap.js');
|
|
63
|
+
const { ensureRuntimeFromArgv } = await import(pathToFileURL(bootstrapPath).href);
|
|
64
|
+
const startupUpdatePath = isDev
|
|
65
|
+
? path.join(root, 'src/lib/startup-update.ts')
|
|
66
|
+
: path.join(root, 'dist/lib/startup-update.js');
|
|
67
|
+
const { maybeRunStartupUpdatePrompt } = await import(pathToFileURL(startupUpdatePath).href);
|
|
68
|
+
const { flush, run, settings } = await import('@oclif/core');
|
|
69
|
+
|
|
70
|
+
if (isDev) {
|
|
71
|
+
settings.debug = true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getCommandToken(argv) {
|
|
75
|
+
const tokens = [];
|
|
76
|
+
|
|
77
|
+
for (const token of argv) {
|
|
78
|
+
if (!token || token.startsWith('-')) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
tokens.push(token);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (tokens[0] === 'api') {
|
|
86
|
+
return tokens[1] ?? tokens[0];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return tokens[0];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function formatCliEntryError(error, argv) {
|
|
93
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
94
|
+
const missingCommandMatch = message.match(/^Command (.+) not found\.$/);
|
|
95
|
+
if (missingCommandMatch) {
|
|
96
|
+
const commandToken = getCommandToken(argv) ?? missingCommandMatch[1];
|
|
97
|
+
return [
|
|
98
|
+
`Unknown command: \`${commandToken}\`.`,
|
|
99
|
+
'If this is a built-in command or a typo, run `nb --help` to inspect available commands.',
|
|
100
|
+
`If \`${commandToken}\` should be a runtime command from your NocoBase app, run \`nb env update\` and try again.`,
|
|
101
|
+
].join('\n');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return message;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const argv = process.argv.slice(2);
|
|
109
|
+
const startupUpdate = await maybeRunStartupUpdatePrompt(argv);
|
|
110
|
+
if (startupUpdate.kind === 'updated') {
|
|
111
|
+
const result = spawnSync(process.execPath, process.argv.slice(1), {
|
|
112
|
+
stdio: 'inherit',
|
|
113
|
+
env: {
|
|
114
|
+
...process.env,
|
|
115
|
+
NB_SKIP_STARTUP_UPDATE: '1',
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
process.exit(result.status === null ? 1 : result.status);
|
|
119
|
+
}
|
|
120
|
+
if (argv[0] === 'api') {
|
|
121
|
+
await ensureRuntimeFromArgv(argv, {
|
|
122
|
+
configFile: path.join(root, 'nocobase-ctl.config.json'),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
await run(argv, import.meta.url);
|
|
126
|
+
flush();
|
|
127
|
+
} catch (error) {
|
|
128
|
+
const message = formatCliEntryError(error, process.argv.slice(2));
|
|
129
|
+
console.error(message);
|
|
130
|
+
process.exitCode = 1;
|
|
131
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { buildCreateArgs, createFlags, runResourceCommand } from '../../../lib/resource-command.js';
|
|
3
|
+
export default class ResourceCreate extends Command {
|
|
4
|
+
static summary = 'Create a record in a resource';
|
|
5
|
+
static description = 'Create a record in a generic resource. Pass record content through --values as a JSON object.';
|
|
6
|
+
static examples = [
|
|
7
|
+
`<%= config.bin %> <%= command.id %> --resource users --values '{"nickname":"Ada"}'`,
|
|
8
|
+
`<%= config.bin %> <%= command.id %> --resource posts.comments --source-id 1 --values '{"content":"Hello"}'`,
|
|
9
|
+
];
|
|
10
|
+
static flags = createFlags;
|
|
11
|
+
async run() {
|
|
12
|
+
const { flags } = await this.parse(ResourceCreate);
|
|
13
|
+
await runResourceCommand(this, 'create', flags, buildCreateArgs(flags));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { buildDestroyArgs, destroyFlags, runResourceCommand } from '../../../lib/resource-command.js';
|
|
3
|
+
export default class ResourceDestroy extends Command {
|
|
4
|
+
static summary = 'Delete records from a resource';
|
|
5
|
+
static description = 'Delete records from a generic resource. Target records with --filter-by-tk or --filter.';
|
|
6
|
+
static examples = [
|
|
7
|
+
'<%= config.bin %> <%= command.id %> --resource users --filter-by-tk 1',
|
|
8
|
+
`<%= config.bin %> <%= command.id %> --resource posts --filter '{"status":"archived"}'`,
|
|
9
|
+
];
|
|
10
|
+
static flags = destroyFlags;
|
|
11
|
+
async run() {
|
|
12
|
+
const { flags } = await this.parse(ResourceDestroy);
|
|
13
|
+
await runResourceCommand(this, 'destroy', flags, buildDestroyArgs(flags));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { buildGetArgs, getFlags, runResourceCommand } from '../../../lib/resource-command.js';
|
|
3
|
+
export default class ResourceGet extends Command {
|
|
4
|
+
static summary = 'Get a record from a resource';
|
|
5
|
+
static description = 'Get a record from a generic resource. Use --filter-by-tk for the primary key and association resource names with --source-id when needed.';
|
|
6
|
+
static examples = [
|
|
7
|
+
'<%= config.bin %> <%= command.id %> --resource users --filter-by-tk 1',
|
|
8
|
+
'<%= config.bin %> <%= command.id %> --resource posts.comments --source-id 1 --filter-by-tk 2',
|
|
9
|
+
];
|
|
10
|
+
static flags = getFlags;
|
|
11
|
+
async run() {
|
|
12
|
+
const { flags } = await this.parse(ResourceGet);
|
|
13
|
+
await runResourceCommand(this, 'get', flags, buildGetArgs(flags));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Command, loadHelpClass } from '@oclif/core';
|
|
10
|
+
export default class Resource extends Command {
|
|
11
|
+
static summary = 'Work with generic collection resources';
|
|
12
|
+
async run() {
|
|
13
|
+
await this.parse(Resource);
|
|
14
|
+
const Help = await loadHelpClass(this.config);
|
|
15
|
+
await new Help(this.config, this.config.pjson.oclif.helpOptions ?? this.config.pjson.helpOptions).showHelp([
|
|
16
|
+
this.id ?? 'api:resource',
|
|
17
|
+
...this.argv,
|
|
18
|
+
]);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { buildListArgs, listFlags, runResourceCommand } from '../../../lib/resource-command.js';
|
|
3
|
+
export default class ResourceList extends Command {
|
|
4
|
+
static summary = 'List records from a resource';
|
|
5
|
+
static description = 'List records from a generic resource. Use association resource names like posts.comments with --source-id when needed.';
|
|
6
|
+
static examples = [
|
|
7
|
+
'<%= config.bin %> <%= command.id %> --resource users',
|
|
8
|
+
'<%= config.bin %> <%= command.id %> --resource posts.comments --source-id 1 --fields id --fields content',
|
|
9
|
+
`<%= config.bin %> <%= command.id %> --resource users --filter '{"status":"active"}' --sort=-createdAt`,
|
|
10
|
+
];
|
|
11
|
+
static flags = listFlags;
|
|
12
|
+
async run() {
|
|
13
|
+
const { flags } = await this.parse(ResourceList);
|
|
14
|
+
await runResourceCommand(this, 'list', flags, buildListArgs(flags));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { buildQueryArgs, queryFlags, runResourceCommand } from '../../../lib/resource-command.js';
|
|
3
|
+
export default class ResourceQuery extends Command {
|
|
4
|
+
static summary = 'Run an aggregate query on a resource';
|
|
5
|
+
static description = 'Run an aggregate query on a generic resource. Pass measures, dimensions, and orders as JSON arrays.';
|
|
6
|
+
static examples = [
|
|
7
|
+
`<%= config.bin %> <%= command.id %> --resource orders --measures '[{"field":["id"],"aggregation":"count","alias":"count"}]'`,
|
|
8
|
+
`<%= config.bin %> <%= command.id %> --resource orders --dimensions '[{"field":["status"],"alias":"status"}]' --orders '[{"field":["createdAt"],"order":"desc"}]'`,
|
|
9
|
+
];
|
|
10
|
+
static flags = queryFlags;
|
|
11
|
+
async run() {
|
|
12
|
+
const { flags } = await this.parse(ResourceQuery);
|
|
13
|
+
await runResourceCommand(this, 'query', flags, buildQueryArgs(flags));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
import { buildUpdateArgs, runResourceCommand, updateFlags } from '../../../lib/resource-command.js';
|
|
3
|
+
export default class ResourceUpdate extends Command {
|
|
4
|
+
static summary = 'Update records in a resource';
|
|
5
|
+
static description = 'Update records in a generic resource. Target records with --filter-by-tk or --filter, and pass updated values through --values.';
|
|
6
|
+
static examples = [
|
|
7
|
+
`<%= config.bin %> <%= command.id %> --resource users --filter-by-tk 1 --values '{"nickname":"Grace"}'`,
|
|
8
|
+
`<%= config.bin %> <%= command.id %> --resource posts --filter '{"status":"draft"}' --values '{"status":"published"}'`,
|
|
9
|
+
];
|
|
10
|
+
static flags = updateFlags;
|
|
11
|
+
async run() {
|
|
12
|
+
const { flags } = await this.parse(ResourceUpdate);
|
|
13
|
+
await runResourceCommand(this, 'update', flags, buildUpdateArgs(flags));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
10
|
+
import { runNocoBaseCommand } from "../lib/run-npm.js";
|
|
11
|
+
import { setVerboseMode } from '../lib/ui.js';
|
|
12
|
+
export default class Build extends Command {
|
|
13
|
+
static args = {
|
|
14
|
+
/** Matches `nb build @nocobase/acl @nocobase/actions` — zero or more package names. */
|
|
15
|
+
packages: Args.string({
|
|
16
|
+
description: 'package names to build',
|
|
17
|
+
multiple: true,
|
|
18
|
+
required: false,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
static description = 'Run the legacy NocoBase build (forwards to `npm run build` in the repo root)';
|
|
22
|
+
static examples = [
|
|
23
|
+
'<%= config.bin %> <%= command.id %>',
|
|
24
|
+
'<%= config.bin %> <%= command.id %> --no-dts',
|
|
25
|
+
'<%= config.bin %> <%= command.id %> --sourcemap',
|
|
26
|
+
'<%= config.bin %> <%= command.id %> @nocobase/acl',
|
|
27
|
+
'<%= config.bin %> <%= command.id %> @nocobase/acl @nocobase/actions',
|
|
28
|
+
];
|
|
29
|
+
static flags = {
|
|
30
|
+
'cwd': Flags.string({ description: 'Current working directory', char: 'c', required: false }),
|
|
31
|
+
'no-dts': Flags.boolean({ description: 'not generate dts' }),
|
|
32
|
+
sourcemap: Flags.boolean({ description: 'generate sourcemap' }),
|
|
33
|
+
verbose: Flags.boolean({ description: 'Show detailed command output', default: false }),
|
|
34
|
+
};
|
|
35
|
+
async run() {
|
|
36
|
+
const { args, flags } = await this.parse(Build);
|
|
37
|
+
setVerboseMode(flags.verbose);
|
|
38
|
+
const packages = args.packages ?? [];
|
|
39
|
+
const npmArgs = ['build', ...packages];
|
|
40
|
+
if (flags['no-dts']) {
|
|
41
|
+
npmArgs.push('--no-dts');
|
|
42
|
+
}
|
|
43
|
+
if (flags.sourcemap) {
|
|
44
|
+
npmArgs.push('--sourcemap');
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await runNocoBaseCommand(npmArgs, {
|
|
48
|
+
cwd: flags['cwd'],
|
|
49
|
+
stdio: flags.verbose ? 'inherit' : 'ignore',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
54
|
+
this.error(message);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|